Skip to content

Commit 6f96c3c

Browse files
congwangJakub Kicinski
authored andcommitted
net_sched: fix backward compatibility for TCA_KIND
Marcelo noticed a backward compatibility issue of TCA_KIND after we move from NLA_STRING to NLA_NUL_STRING, so it is probably too late to change it. Instead, to make everyone happy, we can just insert a NUL to terminate the string with nla_strlcpy() like we do for TC actions. Fixes: 62794fc ("net_sched: add max len check for TCA_KIND") Reported-by: Marcelo Ricardo Leitner <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Cc: Jiri Pirko <[email protected]> Signed-off-by: Cong Wang <[email protected]> Reviewed-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0041412 commit 6f96c3c

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

net/sched/cls_api.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,22 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
162162
return TC_H_MAJ(first);
163163
}
164164

165+
static bool tcf_proto_check_kind(struct nlattr *kind, char *name)
166+
{
167+
if (kind)
168+
return nla_strlcpy(name, kind, IFNAMSIZ) >= IFNAMSIZ;
169+
memset(name, 0, IFNAMSIZ);
170+
return false;
171+
}
172+
165173
static bool tcf_proto_is_unlocked(const char *kind)
166174
{
167175
const struct tcf_proto_ops *ops;
168176
bool ret;
169177

178+
if (strlen(kind) == 0)
179+
return false;
180+
170181
ops = tcf_proto_lookup_ops(kind, false, NULL);
171182
/* On error return false to take rtnl lock. Proto lookup/create
172183
* functions will perform lookup again and properly handle errors.
@@ -1843,6 +1854,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
18431854
{
18441855
struct net *net = sock_net(skb->sk);
18451856
struct nlattr *tca[TCA_MAX + 1];
1857+
char name[IFNAMSIZ];
18461858
struct tcmsg *t;
18471859
u32 protocol;
18481860
u32 prio;
@@ -1899,13 +1911,19 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
18991911
if (err)
19001912
return err;
19011913

1914+
if (tcf_proto_check_kind(tca[TCA_KIND], name)) {
1915+
NL_SET_ERR_MSG(extack, "Specified TC filter name too long");
1916+
err = -EINVAL;
1917+
goto errout;
1918+
}
1919+
19021920
/* Take rtnl mutex if rtnl_held was set to true on previous iteration,
19031921
* block is shared (no qdisc found), qdisc is not unlocked, classifier
19041922
* type is not specified, classifier is not unlocked.
19051923
*/
19061924
if (rtnl_held ||
19071925
(q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) ||
1908-
!tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) {
1926+
!tcf_proto_is_unlocked(name)) {
19091927
rtnl_held = true;
19101928
rtnl_lock();
19111929
}
@@ -2063,6 +2081,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
20632081
{
20642082
struct net *net = sock_net(skb->sk);
20652083
struct nlattr *tca[TCA_MAX + 1];
2084+
char name[IFNAMSIZ];
20662085
struct tcmsg *t;
20672086
u32 protocol;
20682087
u32 prio;
@@ -2102,13 +2121,18 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
21022121
if (err)
21032122
return err;
21042123

2124+
if (tcf_proto_check_kind(tca[TCA_KIND], name)) {
2125+
NL_SET_ERR_MSG(extack, "Specified TC filter name too long");
2126+
err = -EINVAL;
2127+
goto errout;
2128+
}
21052129
/* Take rtnl mutex if flushing whole chain, block is shared (no qdisc
21062130
* found), qdisc is not unlocked, classifier type is not specified,
21072131
* classifier is not unlocked.
21082132
*/
21092133
if (!prio ||
21102134
(q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) ||
2111-
!tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) {
2135+
!tcf_proto_is_unlocked(name)) {
21122136
rtnl_held = true;
21132137
rtnl_lock();
21142138
}
@@ -2216,6 +2240,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
22162240
{
22172241
struct net *net = sock_net(skb->sk);
22182242
struct nlattr *tca[TCA_MAX + 1];
2243+
char name[IFNAMSIZ];
22192244
struct tcmsg *t;
22202245
u32 protocol;
22212246
u32 prio;
@@ -2252,12 +2277,17 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
22522277
if (err)
22532278
return err;
22542279

2280+
if (tcf_proto_check_kind(tca[TCA_KIND], name)) {
2281+
NL_SET_ERR_MSG(extack, "Specified TC filter name too long");
2282+
err = -EINVAL;
2283+
goto errout;
2284+
}
22552285
/* Take rtnl mutex if block is shared (no qdisc found), qdisc is not
22562286
* unlocked, classifier type is not specified, classifier is not
22572287
* unlocked.
22582288
*/
22592289
if ((q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) ||
2260-
!tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) {
2290+
!tcf_proto_is_unlocked(name)) {
22612291
rtnl_held = true;
22622292
rtnl_lock();
22632293
}

net/sched/sch_api.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,8 +1390,7 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
13901390
}
13911391

13921392
const struct nla_policy rtm_tca_policy[TCA_MAX + 1] = {
1393-
[TCA_KIND] = { .type = NLA_NUL_STRING,
1394-
.len = IFNAMSIZ - 1 },
1393+
[TCA_KIND] = { .type = NLA_STRING },
13951394
[TCA_RATE] = { .type = NLA_BINARY,
13961395
.len = sizeof(struct tc_estimator) },
13971396
[TCA_STAB] = { .type = NLA_NESTED },

0 commit comments

Comments
 (0)