Skip to content

Commit 62966b0

Browse files
Takamitsu Iwaiopsiff
authored andcommitted
net/sched: taprio: enforce minimum value for picos_per_byte
[ Upstream commit ae8508b25def57982493c48694ef135973bfabe0 ] 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: fb66df2 ("net/sched: taprio: extend minimum interval restriction to entire cycle too") Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=398e1ee4ca2cac05fddb Signed-off-by: Takamitsu Iwai <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit a7176675c39a242e860663f94394b09904de9221)
1 parent c4cf14a commit 62966b0

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

net/sched/sch_taprio.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ static struct static_key_false taprio_have_working_mqprio;
4141
#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
4242
#define FULL_OFFLOAD_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)
4343
#define TAPRIO_FLAGS_INVALID U32_MAX
44+
/* Minimum value for picos_per_byte to ensure non-zero duration
45+
* for minimum-sized Ethernet frames (ETH_ZLEN = 60).
46+
* 60 * 17 > PSEC_PER_NSEC (1000)
47+
*/
48+
#define TAPRIO_PICOS_PER_BYTE_MIN 17
4449

4550
struct sched_entry {
4651
/* Durations between this GCL entry and the GCL entry where the
@@ -1294,7 +1299,8 @@ static void taprio_start_sched(struct Qdisc *sch,
12941299
}
12951300

12961301
static void taprio_set_picos_per_byte(struct net_device *dev,
1297-
struct taprio_sched *q)
1302+
struct taprio_sched *q,
1303+
struct netlink_ext_ack *extack)
12981304
{
12991305
struct ethtool_link_ksettings ecmd;
13001306
int speed = SPEED_10;
@@ -1310,6 +1316,15 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
13101316

13111317
skip:
13121318
picos_per_byte = (USEC_PER_SEC * 8) / speed;
1319+
if (picos_per_byte < TAPRIO_PICOS_PER_BYTE_MIN) {
1320+
if (!extack)
1321+
pr_warn("Link speed %d is too high. Schedule may be inaccurate.\n",
1322+
speed);
1323+
NL_SET_ERR_MSG_FMT_MOD(extack,
1324+
"Link speed %d is too high. Schedule may be inaccurate.",
1325+
speed);
1326+
picos_per_byte = TAPRIO_PICOS_PER_BYTE_MIN;
1327+
}
13131328

13141329
atomic64_set(&q->picos_per_byte, picos_per_byte);
13151330
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,
13341349
if (dev != qdisc_dev(q->root))
13351350
continue;
13361351

1337-
taprio_set_picos_per_byte(dev, q);
1352+
taprio_set_picos_per_byte(dev, q, NULL);
13381353

13391354
stab = rtnl_dereference(q->root->stab);
13401355

@@ -1871,7 +1886,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
18711886
q->flags = err;
18721887

18731888
/* Needed for length_to_duration() during netlink attribute parsing */
1874-
taprio_set_picos_per_byte(dev, q);
1889+
taprio_set_picos_per_byte(dev, q, extack);
18751890

18761891
err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags);
18771892
if (err < 0)

0 commit comments

Comments
 (0)