mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
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: 5a781ccbd1
("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>
This commit is contained in:
parent
53467ecb6f
commit
b5b73b26b3
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user