sysfs_emit() was introduced in v5.10 as the preferred replacement for sprintf() in sysfs show() handlers. It bounds output to PAGE_SIZE and avoids potential buffer overruns. Convert all show() callbacks and the NCM_PARM_ATTR macro from sprintf() to sysfs_emit(). Signed-off-by: Omer Zalman --- drivers/net/usb/cdc_ncm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 7057c6c0cfc6..6fcb4d711a64 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -204,7 +204,7 @@ static ssize_t min_tx_pkt_show(struct device *d, struct usbnet *dev = netdev_priv(to_net_dev(d)); struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - return sprintf(buf, "%u\n", ctx->min_tx_pkt); + return sysfs_emit(buf, "%u\n", ctx->min_tx_pkt); } static ssize_t rx_max_show(struct device *d, @@ -213,7 +213,7 @@ static ssize_t rx_max_show(struct device *d, struct usbnet *dev = netdev_priv(to_net_dev(d)); struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - return sprintf(buf, "%u\n", ctx->rx_max); + return sysfs_emit(buf, "%u\n", ctx->rx_max); } static ssize_t tx_max_show(struct device *d, @@ -222,7 +222,7 @@ static ssize_t tx_max_show(struct device *d, struct usbnet *dev = netdev_priv(to_net_dev(d)); struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - return sprintf(buf, "%u\n", ctx->tx_max); + return sysfs_emit(buf, "%u\n", ctx->tx_max); } static ssize_t tx_timer_usecs_show(struct device *d, @@ -231,7 +231,7 @@ static ssize_t tx_timer_usecs_show(struct device *d, struct usbnet *dev = netdev_priv(to_net_dev(d)); struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - return sprintf(buf, "%u\n", ctx->timer_interval / (u32)NSEC_PER_USEC); + return sysfs_emit(buf, "%u\n", ctx->timer_interval / (u32)NSEC_PER_USEC); } static ssize_t min_tx_pkt_store(struct device *d, @@ -313,7 +313,7 @@ static ssize_t ndp_to_end_show(struct device *d, struct device_attribute *attr, struct usbnet *dev = netdev_priv(to_net_dev(d)); struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - return sprintf(buf, "%c\n", ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END ? 'Y' : 'N'); + return sysfs_emit(buf, "%c\n", ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END ? 'Y' : 'N'); } static ssize_t ndp_to_end_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) @@ -362,7 +362,7 @@ static ssize_t cdc_ncm_show_##name(struct device *d, struct device_attribute *at { \ struct usbnet *dev = netdev_priv(to_net_dev(d)); \ struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; \ - return sprintf(buf, format "\n", tocpu(ctx->ncm_parm.name)); \ + return sysfs_emit(buf, format "\n", tocpu(ctx->ncm_parm.name)); \ } \ static DEVICE_ATTR(name, 0444, cdc_ncm_show_##name, NULL) -- 2.39.5 (Apple Git-154) min_tx_pkt is a u16 field but the sysfs store handler accepted any unsigned long and assigned it directly. Values that do not fit in 16 bits silently truncate: writing 65537 wraps to 1, turning a "never pad" intent into "always pad". ctx->tx_max can itself reach 65537 because cdc_ncm_update_rxtx_max() increments the negotiated NTB size by one pad byte when it is an exact multiple of the USB maxpacket size. Clamp the stored value to min(tx_max, U16_MAX). Any value above tx_max is already semantically equivalent to tx_max since frame lengths never exceed it; the U16_MAX cap ensures the result is always representable in the u16 field without wrapping. Fixes: 39eb7e0e8c88 ("net: cdc_ncm: allow tuning min_tx_pkt") Signed-off-by: Omer Zalman --- drivers/net/usb/cdc_ncm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 6fcb4d711a64..edd69f4e1596 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -242,11 +242,17 @@ static ssize_t min_tx_pkt_store(struct device *d, struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; unsigned long val; - /* no need to restrict values - anything from 0 to infinity is OK */ if (kstrtoul(buf, 0, &val)) return -EINVAL; - ctx->min_tx_pkt = val; + /* Clamp to tx_max: the frame length can never exceed tx_max, + * so any threshold above it has the same effect (padding is + * never applied). Also cap at U16_MAX since min_tx_pkt is + * a u16 - without this, values like 65537 silently wrap to 1 + * and invert the intended behavior. + */ + ctx->min_tx_pkt = min_t(unsigned long, val, + min_t(u32, ctx->tx_max, U16_MAX)); return len; } -- 2.39.5 (Apple Git-154)