Skip to content

Commit

Permalink
taprio: Fix allowing too small intervals
Browse files Browse the repository at this point in the history
[ Upstream commit b5b73b2 ]

It's possible that the user specifies an interval that couldn't allow
any packet to be transmitted. This also avoids the issue of the
hrtimer handler starving the other threads because it's running too
often.

The solution is to reject interval sizes that according to the current
link speed wouldn't allow any packet to be transmitted.

Reported-by: syzbot+8267241609ae8c23b248@syzkaller.appspotmail.com
Fixes: 5a781cc ("tc: Add support for configuring the taprio scheduler")
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
vcgomes authored and gregkh committed Sep 26, 2020
1 parent f705d35 commit 83bd589
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions net/sched/sch_taprio.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,9 +777,11 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
[TCA_TAPRIO_ATTR_TXTIME_DELAY] = { .type = NLA_U32 },
};

static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
static int fill_sched_entry(struct taprio_sched *q, struct nlattr **tb,
struct sched_entry *entry,
struct netlink_ext_ack *extack)
{
int min_duration = length_to_duration(q, ETH_ZLEN);
u32 interval = 0;

if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
Expand All @@ -794,7 +796,10 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
interval = nla_get_u32(
tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]);

if (interval == 0) {
/* The interval should allow at least the minimum ethernet
* frame to go out.
*/
if (interval < min_duration) {
NL_SET_ERR_MSG(extack, "Invalid interval for schedule entry");
return -EINVAL;
}
Expand All @@ -804,8 +809,9 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
return 0;
}

static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,
int index, struct netlink_ext_ack *extack)
static int parse_sched_entry(struct taprio_sched *q, struct nlattr *n,
struct sched_entry *entry, int index,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { };
int err;
Expand All @@ -819,10 +825,10 @@ static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,

entry->index = index;

return fill_sched_entry(tb, entry, extack);
return fill_sched_entry(q, tb, entry, extack);
}

static int parse_sched_list(struct nlattr *list,
static int parse_sched_list(struct taprio_sched *q, struct nlattr *list,
struct sched_gate_list *sched,
struct netlink_ext_ack *extack)
{
Expand All @@ -847,7 +853,7 @@ static int parse_sched_list(struct nlattr *list,
return -ENOMEM;
}

err = parse_sched_entry(n, entry, i, extack);
err = parse_sched_entry(q, n, entry, i, extack);
if (err < 0) {
kfree(entry);
return err;
Expand All @@ -862,7 +868,7 @@ static int parse_sched_list(struct nlattr *list,
return i;
}

static int parse_taprio_schedule(struct nlattr **tb,
static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
struct sched_gate_list *new,
struct netlink_ext_ack *extack)
{
Expand All @@ -883,8 +889,8 @@ static int parse_taprio_schedule(struct nlattr **tb,
new->cycle_time = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]);

if (tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST])
err = parse_sched_list(
tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST], new, extack);
err = parse_sched_list(q, tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST],
new, extack);
if (err < 0)
return err;

Expand Down Expand Up @@ -1474,7 +1480,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
goto free_sched;
}

err = parse_taprio_schedule(tb, new_admin, extack);
err = parse_taprio_schedule(q, tb, new_admin, extack);
if (err < 0)
goto free_sched;

Expand Down

0 comments on commit 83bd589

Please sign in to comment.