diff options
| author | seteiro <[email protected]> | 2026-11-12 00:40:13 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-11-13 09:47:35 +0800 |
| commit | 6c955645ec82372469f20746ead53e2ce3b5eda5 (patch) | |
| tree | 65f40ab740bd3d30ee9c92726a35ac6a2a82d315 /components | |
| parent | 5114bfecc77b3f433edb8db776b7e5e7ce776f35 (diff) | |
[drivers][serial] marshal RT_DEVICE_CTRL_CONFIG from userspace
Close the remaining userspace ioctl boundary gaps on top of the serial v1/v2
LWP marshaling:
- In serial_fops_ioctl() for both dev_serial.c and dev_serial_v2.c, return 0
directly after updating fd->flags on F_SETFL instead of forwarding to
ops->control(), and reject any unmarshaled/unknown command from an LWP
caller with -RT_ENOSYS instead of passing raw user pointers into
rt_device_control() / serial->ops->control().
- Guard the LWP marshaling block with defined(RT_USING_LWP) &&
defined(ARCH_MM_MMU), matching lwp_user_mm.h.
- In rt_serial_control(), reject baudrate == 0 (e.g. B0 or unmapped speed)
with -RT_EINVAL in TCSETA*/TCSETS* just like RT_DEVICE_CTRL_CONFIG, and
add missing RT_NULL and ops->configure checks in v1/v2 control handlers.
Fixes #11429
Diffstat (limited to 'components')
| -rw-r--r-- | components/drivers/serial/dev_serial.c | 52 | ||||
| -rw-r--r-- | components/drivers/serial/dev_serial_v2.c | 34 |
2 files changed, 75 insertions, 11 deletions
diff --git a/components/drivers/serial/dev_serial.c b/components/drivers/serial/dev_serial.c index 2b020c8306..4878e8a17c 100644 --- a/components/drivers/serial/dev_serial.c +++ b/components/drivers/serial/dev_serial.c @@ -148,10 +148,10 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args) flags &= mask; fd->flags &= ~mask; fd->flags |= flags; - break; + return 0; } -#ifdef RT_USING_LWP +#if defined(RT_USING_LWP) && defined(ARCH_MM_MMU) if (lwp_self() != RT_NULL) { union serial_user_ioctl_arg @@ -227,8 +227,13 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args) kptr = &karg.winsize; copy_out = RT_TRUE; break; +#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_TTY) + case TCFLSH: + case TCXONC: + return rt_device_control(device, cmd, args); +#endif default: - break; + return -RT_ENOSYS; } if (arg_size) @@ -1203,7 +1208,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, break; case RT_DEVICE_CTRL_CONFIG: - if (args) + if (args == RT_NULL) + { + return -RT_EINVAL; + } + else { struct serial_configure *pconfig = (struct serial_configure *) args; if (pconfig->bufsz != serial->config.bufsz && serial->parent.ref_count) @@ -1218,6 +1227,10 @@ static rt_err_t rt_serial_control(struct rt_device *dev, if (serial->parent.ref_count) { + if (serial->ops == RT_NULL || serial->ops->configure == RT_NULL) + { + return -RT_ENOSYS; + } /* serial device has been opened, to configure it */ ret = serial->ops->configure(serial, pconfig); if (ret != RT_EOK) @@ -1249,6 +1262,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, { struct termios *tio, tmp = { 0 }; + if (args == RT_NULL) + { + return -RT_EINVAL; + } + if (cmd == TCGETS) { tio = (struct termios*)args; @@ -1258,8 +1276,6 @@ static rt_err_t rt_serial_control(struct rt_device *dev, tio = &tmp; } - if (tio == RT_NULL) return -RT_EINVAL; - tio->c_iflag = 0; tio->c_oflag = 0; tio->c_lflag = 0; @@ -1306,6 +1322,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, struct serial_configure config; struct termios *tio, tmp; + if (args == RT_NULL) + { + return -RT_EINVAL; + } + if ((cmd >= TCSETA) && (cmd <= TCSETA + 2)) { _termio_to_termios(args, &tmp); @@ -1316,10 +1337,12 @@ static rt_err_t rt_serial_control(struct rt_device *dev, tio = (struct termios*)args; } - if (tio == RT_NULL) return -RT_EINVAL; - config = serial->config; baudrate = _get_baudrate(cfgetospeed(tio)); + if (baudrate == 0) + { + return -RT_EINVAL; + } config.baud_rate = baudrate; switch (tio->c_cflag & CSIZE) @@ -1351,6 +1374,10 @@ static rt_err_t rt_serial_control(struct rt_device *dev, /* Software-only termios changes must not reset the UART FIFO. */ if (rt_memcmp(&config, &serial->config, sizeof(config)) != 0) { + if (serial->ops == RT_NULL || serial->ops->configure == RT_NULL) + { + return -RT_ENOSYS; + } ret = serial->ops->configure(serial, &config); if (ret != RT_EOK) { @@ -1377,6 +1404,10 @@ static rt_err_t rt_serial_control(struct rt_device *dev, { struct winsize* p_winsize; + if (args == RT_NULL) + { + return -RT_EINVAL; + } p_winsize = (struct winsize*)args; rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row); } @@ -1442,6 +1473,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, rt_ssize_t recved = 0; rt_base_t level; + if (args == RT_NULL) + { + return -RT_EINVAL; + } + level = rt_spin_lock_irqsave(&(serial->spinlock)); recved = _serial_fifo_calc_recved_len(serial); rt_spin_unlock_irqrestore(&(serial->spinlock), level); diff --git a/components/drivers/serial/dev_serial_v2.c b/components/drivers/serial/dev_serial_v2.c index 239af74924..952d2c1f78 100644 --- a/components/drivers/serial/dev_serial_v2.c +++ b/components/drivers/serial/dev_serial_v2.c @@ -147,12 +147,12 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args) flags &= mask; fd->flags &= ~mask; fd->flags |= flags; - break; + return 0; default: break; } -#ifdef RT_USING_LWP +#if defined(RT_USING_LWP) && defined(ARCH_MM_MMU) if (lwp_self() != RT_NULL) { union serial_user_ioctl_arg @@ -243,8 +243,15 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args) kptr = &karg.winsize; copy_out = RT_TRUE; break; + case RT_SERIAL_CTRL_RX_FLUSH: + case RT_SERIAL_CTRL_TX_FLUSH: +#ifdef RT_USING_POSIX_TERMIOS + case TCFLSH: + case TCXONC: +#endif + return rt_device_control(device, cmd, args); default: - break; + return -RT_ENOSYS; } if (arg_size) @@ -1596,6 +1603,12 @@ static rt_err_t rt_serial_control(struct rt_device *dev, break; } + if (serial->ops == RT_NULL || serial->ops->configure == RT_NULL) + { + ret = -RT_ENOSYS; + break; + } + ret = serial->ops->configure(serial, pconfig); if (ret != RT_EOK) { @@ -1806,6 +1819,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, config = serial->config; baudrate = _get_baudrate(cfgetospeed(tio)); + if (baudrate == 0) + { + ret = -RT_EINVAL; + break; + } config.baud_rate = baudrate; switch (tio->c_cflag & CSIZE) @@ -1847,6 +1865,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, /* Software-only termios changes must not reset the UART FIFO. */ if (rt_memcmp(&config, &serial->config, sizeof(config)) != 0) { + if (serial->ops == RT_NULL || serial->ops->configure == RT_NULL) + { + ret = -RT_ENOSYS; + break; + } ret = serial->ops->configure(serial, &config); if (ret != RT_EOK) { @@ -1872,6 +1895,11 @@ static rt_err_t rt_serial_control(struct rt_device *dev, { struct winsize *p_winsize; + if (args == RT_NULL) + { + ret = -RT_EINVAL; + break; + } p_winsize = (struct winsize *)args; rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row); } |
