Commit b5b73b26 authored by Vinicius Costa Gomes's avatar Vinicius Costa Gomes Committed by David S. Miller

taprio: Fix allowing too small intervals

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: 5a781ccb ("tc: Add support for configuring the taprio scheduler")
Signed-off-by: default avatarVinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 53467ecb
...@@ -777,9 +777,11 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { ...@@ -777,9 +777,11 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
[TCA_TAPRIO_ATTR_TXTIME_DELAY] = { .type = NLA_U32 }, [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) struct netlink_ext_ack *extack)
{ {
int min_duration = length_to_duration(q, ETH_ZLEN);
u32 interval = 0; u32 interval = 0;
if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD]) if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
...@@ -794,7 +796,10 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry, ...@@ -794,7 +796,10 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
interval = nla_get_u32( interval = nla_get_u32(
tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]); 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"); NL_SET_ERR_MSG(extack, "Invalid interval for schedule entry");
return -EINVAL; return -EINVAL;
} }
...@@ -804,8 +809,9 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry, ...@@ -804,8 +809,9 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
return 0; return 0;
} }
static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry, static int parse_sched_entry(struct taprio_sched *q, struct nlattr *n,
int index, struct netlink_ext_ack *extack) struct sched_entry *entry, int index,
struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { }; struct nlattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { };
int err; int err;
...@@ -819,10 +825,10 @@ static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry, ...@@ -819,10 +825,10 @@ static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,
entry->index = index; 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 sched_gate_list *sched,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
...@@ -847,7 +853,7 @@ static int parse_sched_list(struct nlattr *list, ...@@ -847,7 +853,7 @@ static int parse_sched_list(struct nlattr *list,
return -ENOMEM; return -ENOMEM;
} }
err = parse_sched_entry(n, entry, i, extack); err = parse_sched_entry(q, n, entry, i, extack);
if (err < 0) { if (err < 0) {
kfree(entry); kfree(entry);
return err; return err;
...@@ -862,7 +868,7 @@ static int parse_sched_list(struct nlattr *list, ...@@ -862,7 +868,7 @@ static int parse_sched_list(struct nlattr *list,
return i; 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 sched_gate_list *new,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
...@@ -883,8 +889,8 @@ static int parse_taprio_schedule(struct nlattr **tb, ...@@ -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]); new->cycle_time = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]);
if (tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST]) if (tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST])
err = parse_sched_list( err = parse_sched_list(q, tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST],
tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST], new, extack); new, extack);
if (err < 0) if (err < 0)
return err; return err;
...@@ -1473,7 +1479,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, ...@@ -1473,7 +1479,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
goto free_sched; goto free_sched;
} }
err = parse_taprio_schedule(tb, new_admin, extack); err = parse_taprio_schedule(q, tb, new_admin, extack);
if (err < 0) if (err < 0)
goto free_sched; goto free_sched;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment