mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
synced 2025-10-17 01:06:55 +10:00
net/sched: taprio: enforce minimum value for picos_per_byte
[ Upstream commitae8508b25d
] Syzbot reported a WARNING in taprio_get_start_time(). When link speed is 470,589 or greater, q->picos_per_byte becomes too small, causing length_to_duration(q, ETH_ZLEN) to return zero. This zero value leads to validation failures in fill_sched_entry() and parse_taprio_schedule(), allowing arbitrary values to be assigned to entry->interval and cycle_time. As a result, sched->cycle can become zero. Since SPEED_800000 is the largest defined speed in include/uapi/linux/ethtool.h, this issue can occur in realistic scenarios. To ensure length_to_duration() returns a non-zero value for minimum-sized Ethernet frames (ETH_ZLEN = 60), picos_per_byte must be at least 17 (60 * 17 > PSEC_PER_NSEC which is 1000). This patch enforces a minimum value of 17 for picos_per_byte when the calculated value would be lower, and adds a warning message to inform users that scheduling accuracy may be affected at very high link speeds. Fixes:fb66df20a7
("net/sched: taprio: extend minimum interval restriction to entire cycle too") Reported-by: syzbot+398e1ee4ca2cac05fddb@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=398e1ee4ca2cac05fddb Signed-off-by: Takamitsu Iwai <takamitz@amazon.co.jp> Link: https://patch.msgid.link/20250728173149.45585-1-takamitz@amazon.co.jp Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
0d45954034
commit
a7176675c3
@ -41,6 +41,11 @@ static struct static_key_false taprio_have_working_mqprio;
|
||||
#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
|
||||
#define FULL_OFFLOAD_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)
|
||||
#define TAPRIO_FLAGS_INVALID U32_MAX
|
||||
/* Minimum value for picos_per_byte to ensure non-zero duration
|
||||
* for minimum-sized Ethernet frames (ETH_ZLEN = 60).
|
||||
* 60 * 17 > PSEC_PER_NSEC (1000)
|
||||
*/
|
||||
#define TAPRIO_PICOS_PER_BYTE_MIN 17
|
||||
|
||||
struct sched_entry {
|
||||
/* Durations between this GCL entry and the GCL entry where the
|
||||
@ -1294,7 +1299,8 @@ static void taprio_start_sched(struct Qdisc *sch,
|
||||
}
|
||||
|
||||
static void taprio_set_picos_per_byte(struct net_device *dev,
|
||||
struct taprio_sched *q)
|
||||
struct taprio_sched *q,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ethtool_link_ksettings ecmd;
|
||||
int speed = SPEED_10;
|
||||
@ -1310,6 +1316,15 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
|
||||
|
||||
skip:
|
||||
picos_per_byte = (USEC_PER_SEC * 8) / speed;
|
||||
if (picos_per_byte < TAPRIO_PICOS_PER_BYTE_MIN) {
|
||||
if (!extack)
|
||||
pr_warn("Link speed %d is too high. Schedule may be inaccurate.\n",
|
||||
speed);
|
||||
NL_SET_ERR_MSG_FMT_MOD(extack,
|
||||
"Link speed %d is too high. Schedule may be inaccurate.",
|
||||
speed);
|
||||
picos_per_byte = TAPRIO_PICOS_PER_BYTE_MIN;
|
||||
}
|
||||
|
||||
atomic64_set(&q->picos_per_byte, picos_per_byte);
|
||||
netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
|
||||
@ -1334,7 +1349,7 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
|
||||
if (dev != qdisc_dev(q->root))
|
||||
continue;
|
||||
|
||||
taprio_set_picos_per_byte(dev, q);
|
||||
taprio_set_picos_per_byte(dev, q, NULL);
|
||||
|
||||
stab = rtnl_dereference(q->root->stab);
|
||||
|
||||
@ -1871,7 +1886,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
|
||||
q->flags = err;
|
||||
|
||||
/* Needed for length_to_duration() during netlink attribute parsing */
|
||||
taprio_set_picos_per_byte(dev, q);
|
||||
taprio_set_picos_per_byte(dev, q, extack);
|
||||
|
||||
err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags);
|
||||
if (err < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user