summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorseteiro <[email protected]>2026-11-12 00:40:13 +0800
committerRbb666 <[email protected]>2026-11-13 09:47:35 +0800
commit6c955645ec82372469f20746ead53e2ce3b5eda5 (patch)
tree65f40ab740bd3d30ee9c92726a35ac6a2a82d315
parent5114bfecc77b3f433edb8db776b7e5e7ce776f35 (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
-rw-r--r--components/drivers/serial/dev_serial.c52
-rw-r--r--components/drivers/serial/dev_serial_v2.c34
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);
}