diff options
author | Hong zhi guo <honkiko@gmail.com> | 2013-03-25 13:36:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-26 12:35:27 -0400 |
commit | de179c8c12e9e5a292269fa59e7c26ca797dc7bf (patch) | |
tree | e14c3f431303e9fd538395bd4669fe9255252d7d /net/sched | |
parent | 8dc57da2e23085642cad20d11385e13e079715c4 (diff) |
netlink: have length check of rtnl msg before deref
When the legacy array rtm_min still exists, the length check within
these functions is covered by rtm_min[RTM_NEWTFILTER],
rtm_min[RTM_NEWQDISC] and rtm_min[RTM_NEWTCLASS].
But after Thomas Graf removed rtm_min several days ago, these checks
are missing. Other doit functions should be OK.
Signed-off-by: Hong Zhiguo <honkiko@gmail.com>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_api.c | 9 | ||||
-rw-r--r-- | net/sched/sch_api.c | 36 |
2 files changed, 26 insertions, 19 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 9a04b981bc13..9d71d4ded53b 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -141,7 +141,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) | |||
141 | 141 | ||
142 | if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN)) | 142 | if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN)) |
143 | return -EPERM; | 143 | return -EPERM; |
144 | |||
144 | replay: | 145 | replay: |
146 | err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL); | ||
147 | if (err < 0) | ||
148 | return err; | ||
149 | |||
145 | t = nlmsg_data(n); | 150 | t = nlmsg_data(n); |
146 | protocol = TC_H_MIN(t->tcm_info); | 151 | protocol = TC_H_MIN(t->tcm_info); |
147 | prio = TC_H_MAJ(t->tcm_info); | 152 | prio = TC_H_MAJ(t->tcm_info); |
@@ -164,10 +169,6 @@ replay: | |||
164 | if (dev == NULL) | 169 | if (dev == NULL) |
165 | return -ENODEV; | 170 | return -ENODEV; |
166 | 171 | ||
167 | err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL); | ||
168 | if (err < 0) | ||
169 | return err; | ||
170 | |||
171 | /* Find qdisc */ | 172 | /* Find qdisc */ |
172 | if (!parent) { | 173 | if (!parent) { |
173 | q = dev->qdisc; | 174 | q = dev->qdisc; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0bbce229ac69..d7468baf890e 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -977,7 +977,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n) | |||
977 | struct tcmsg *tcm = nlmsg_data(n); | 977 | struct tcmsg *tcm = nlmsg_data(n); |
978 | struct nlattr *tca[TCA_MAX + 1]; | 978 | struct nlattr *tca[TCA_MAX + 1]; |
979 | struct net_device *dev; | 979 | struct net_device *dev; |
980 | u32 clid = tcm->tcm_parent; | 980 | u32 clid; |
981 | struct Qdisc *q = NULL; | 981 | struct Qdisc *q = NULL; |
982 | struct Qdisc *p = NULL; | 982 | struct Qdisc *p = NULL; |
983 | int err; | 983 | int err; |
@@ -985,14 +985,15 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n) | |||
985 | if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN)) | 985 | if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN)) |
986 | return -EPERM; | 986 | return -EPERM; |
987 | 987 | ||
988 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); | ||
989 | if (!dev) | ||
990 | return -ENODEV; | ||
991 | |||
992 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 988 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
993 | if (err < 0) | 989 | if (err < 0) |
994 | return err; | 990 | return err; |
995 | 991 | ||
992 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); | ||
993 | if (!dev) | ||
994 | return -ENODEV; | ||
995 | |||
996 | clid = tcm->tcm_parent; | ||
996 | if (clid) { | 997 | if (clid) { |
997 | if (clid != TC_H_ROOT) { | 998 | if (clid != TC_H_ROOT) { |
998 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { | 999 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { |
@@ -1053,6 +1054,10 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n) | |||
1053 | 1054 | ||
1054 | replay: | 1055 | replay: |
1055 | /* Reinit, just in case something touches this. */ | 1056 | /* Reinit, just in case something touches this. */ |
1057 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | ||
1058 | if (err < 0) | ||
1059 | return err; | ||
1060 | |||
1056 | tcm = nlmsg_data(n); | 1061 | tcm = nlmsg_data(n); |
1057 | clid = tcm->tcm_parent; | 1062 | clid = tcm->tcm_parent; |
1058 | q = p = NULL; | 1063 | q = p = NULL; |
@@ -1061,9 +1066,6 @@ replay: | |||
1061 | if (!dev) | 1066 | if (!dev) |
1062 | return -ENODEV; | 1067 | return -ENODEV; |
1063 | 1068 | ||
1064 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | ||
1065 | if (err < 0) | ||
1066 | return err; | ||
1067 | 1069 | ||
1068 | if (clid) { | 1070 | if (clid) { |
1069 | if (clid != TC_H_ROOT) { | 1071 | if (clid != TC_H_ROOT) { |
@@ -1382,22 +1384,22 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n) | |||
1382 | const struct Qdisc_class_ops *cops; | 1384 | const struct Qdisc_class_ops *cops; |
1383 | unsigned long cl = 0; | 1385 | unsigned long cl = 0; |
1384 | unsigned long new_cl; | 1386 | unsigned long new_cl; |
1385 | u32 portid = tcm->tcm_parent; | 1387 | u32 portid; |
1386 | u32 clid = tcm->tcm_handle; | 1388 | u32 clid; |
1387 | u32 qid = TC_H_MAJ(clid); | 1389 | u32 qid; |
1388 | int err; | 1390 | int err; |
1389 | 1391 | ||
1390 | if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN)) | 1392 | if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN)) |
1391 | return -EPERM; | 1393 | return -EPERM; |
1392 | 1394 | ||
1393 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); | ||
1394 | if (!dev) | ||
1395 | return -ENODEV; | ||
1396 | |||
1397 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1395 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
1398 | if (err < 0) | 1396 | if (err < 0) |
1399 | return err; | 1397 | return err; |
1400 | 1398 | ||
1399 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); | ||
1400 | if (!dev) | ||
1401 | return -ENODEV; | ||
1402 | |||
1401 | /* | 1403 | /* |
1402 | parent == TC_H_UNSPEC - unspecified parent. | 1404 | parent == TC_H_UNSPEC - unspecified parent. |
1403 | parent == TC_H_ROOT - class is root, which has no parent. | 1405 | parent == TC_H_ROOT - class is root, which has no parent. |
@@ -1413,6 +1415,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n) | |||
1413 | 1415 | ||
1414 | /* Step 1. Determine qdisc handle X:0 */ | 1416 | /* Step 1. Determine qdisc handle X:0 */ |
1415 | 1417 | ||
1418 | portid = tcm->tcm_parent; | ||
1419 | clid = tcm->tcm_handle; | ||
1420 | qid = TC_H_MAJ(clid); | ||
1421 | |||
1416 | if (portid != TC_H_ROOT) { | 1422 | if (portid != TC_H_ROOT) { |
1417 | u32 qid1 = TC_H_MAJ(portid); | 1423 | u32 qid1 = TC_H_MAJ(portid); |
1418 | 1424 | ||