diff options
-rw-r--r-- | include/linux/netfilter/nfnetlink.h | 2 | ||||
-rw-r--r-- | include/net/netlink.h | 2 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 46 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 46 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 26 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 6 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 21 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 56 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 40 |
10 files changed, 93 insertions, 156 deletions
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index e1ea5dfbbbd4..0f9311df1559 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
@@ -111,7 +111,7 @@ struct nfgenmsg { | |||
111 | struct nfnl_callback | 111 | struct nfnl_callback |
112 | { | 112 | { |
113 | int (*call)(struct sock *nl, struct sk_buff *skb, | 113 | int (*call)(struct sock *nl, struct sk_buff *skb, |
114 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); | 114 | struct nlmsghdr *nlh, struct nfattr *cda[]); |
115 | u_int16_t attr_count; /* number of nfattr's */ | 115 | u_int16_t attr_count; /* number of nfattr's */ |
116 | }; | 116 | }; |
117 | 117 | ||
diff --git a/include/net/netlink.h b/include/net/netlink.h index 510ca7fabe18..1c11518fc822 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h | |||
@@ -214,7 +214,7 @@ struct nl_info { | |||
214 | 214 | ||
215 | extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, | 215 | extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, |
216 | int (*cb)(struct sk_buff *, | 216 | int (*cb)(struct sk_buff *, |
217 | struct nlmsghdr *, int *)); | 217 | struct nlmsghdr *)); |
218 | extern void netlink_queue_skip(struct nlmsghdr *nlh, | 218 | extern void netlink_queue_skip(struct nlmsghdr *nlh, |
219 | struct sk_buff *skb); | 219 | struct sk_buff *skb); |
220 | extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, | 220 | extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b2136accd267..14241ada41a1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -852,8 +852,7 @@ static int rtattr_max; | |||
852 | 852 | ||
853 | /* Process one rtnetlink message. */ | 853 | /* Process one rtnetlink message. */ |
854 | 854 | ||
855 | static __inline__ int | 855 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
856 | rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | ||
857 | { | 856 | { |
858 | rtnl_doit_func doit; | 857 | rtnl_doit_func doit; |
859 | int sz_idx, kind; | 858 | int sz_idx, kind; |
@@ -863,10 +862,8 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | |||
863 | int err; | 862 | int err; |
864 | 863 | ||
865 | type = nlh->nlmsg_type; | 864 | type = nlh->nlmsg_type; |
866 | |||
867 | /* Unknown message: reply with EINVAL */ | ||
868 | if (type > RTM_MAX) | 865 | if (type > RTM_MAX) |
869 | goto err_inval; | 866 | return -EINVAL; |
870 | 867 | ||
871 | type -= RTM_BASE; | 868 | type -= RTM_BASE; |
872 | 869 | ||
@@ -875,40 +872,33 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | |||
875 | return 0; | 872 | return 0; |
876 | 873 | ||
877 | family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; | 874 | family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; |
878 | if (family >= NPROTO) { | 875 | if (family >= NPROTO) |
879 | *errp = -EAFNOSUPPORT; | 876 | return -EAFNOSUPPORT; |
880 | return -1; | ||
881 | } | ||
882 | 877 | ||
883 | sz_idx = type>>2; | 878 | sz_idx = type>>2; |
884 | kind = type&3; | 879 | kind = type&3; |
885 | 880 | ||
886 | if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) { | 881 | if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) |
887 | *errp = -EPERM; | 882 | return -EPERM; |
888 | return -1; | ||
889 | } | ||
890 | 883 | ||
891 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { | 884 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { |
892 | rtnl_dumpit_func dumpit; | 885 | rtnl_dumpit_func dumpit; |
893 | 886 | ||
894 | dumpit = rtnl_get_dumpit(family, type); | 887 | dumpit = rtnl_get_dumpit(family, type); |
895 | if (dumpit == NULL) | 888 | if (dumpit == NULL) |
896 | goto err_inval; | 889 | return -EINVAL; |
897 | |||
898 | if ((*errp = netlink_dump_start(rtnl, skb, nlh, | ||
899 | dumpit, NULL)) != 0) { | ||
900 | return -1; | ||
901 | } | ||
902 | 890 | ||
903 | netlink_queue_skip(nlh, skb); | 891 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); |
904 | return -1; | 892 | if (err == 0) |
893 | err = -EINTR; | ||
894 | return err; | ||
905 | } | 895 | } |
906 | 896 | ||
907 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); | 897 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); |
908 | 898 | ||
909 | min_len = rtm_min[sz_idx]; | 899 | min_len = rtm_min[sz_idx]; |
910 | if (nlh->nlmsg_len < min_len) | 900 | if (nlh->nlmsg_len < min_len) |
911 | goto err_inval; | 901 | return -EINVAL; |
912 | 902 | ||
913 | if (nlh->nlmsg_len > min_len) { | 903 | if (nlh->nlmsg_len > min_len) { |
914 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | 904 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); |
@@ -918,7 +908,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | |||
918 | unsigned flavor = attr->rta_type; | 908 | unsigned flavor = attr->rta_type; |
919 | if (flavor) { | 909 | if (flavor) { |
920 | if (flavor > rta_max[sz_idx]) | 910 | if (flavor > rta_max[sz_idx]) |
921 | goto err_inval; | 911 | return -EINVAL; |
922 | rta_buf[flavor-1] = attr; | 912 | rta_buf[flavor-1] = attr; |
923 | } | 913 | } |
924 | attr = RTA_NEXT(attr, attrlen); | 914 | attr = RTA_NEXT(attr, attrlen); |
@@ -927,15 +917,9 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | |||
927 | 917 | ||
928 | doit = rtnl_get_doit(family, type); | 918 | doit = rtnl_get_doit(family, type); |
929 | if (doit == NULL) | 919 | if (doit == NULL) |
930 | goto err_inval; | 920 | return -EINVAL; |
931 | err = doit(skb, nlh, (void *)&rta_buf[0]); | ||
932 | |||
933 | *errp = err; | ||
934 | return err; | ||
935 | 921 | ||
936 | err_inval: | 922 | return doit(skb, nlh, (void *)&rta_buf[0]); |
937 | *errp = -EINVAL; | ||
938 | return -1; | ||
939 | } | 923 | } |
940 | 924 | ||
941 | static void rtnetlink_rcv(struct sock *sk, int len) | 925 | static void rtnetlink_rcv(struct sock *sk, int len) |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 76f11f325919..443ba7753a33 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -661,7 +661,7 @@ static const size_t cta_min[CTA_MAX] = { | |||
661 | 661 | ||
662 | static int | 662 | static int |
663 | ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | 663 | ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, |
664 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 664 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
665 | { | 665 | { |
666 | struct nf_conntrack_tuple_hash *h; | 666 | struct nf_conntrack_tuple_hash *h; |
667 | struct nf_conntrack_tuple tuple; | 667 | struct nf_conntrack_tuple tuple; |
@@ -709,7 +709,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
709 | 709 | ||
710 | static int | 710 | static int |
711 | ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | 711 | ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, |
712 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 712 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
713 | { | 713 | { |
714 | struct nf_conntrack_tuple_hash *h; | 714 | struct nf_conntrack_tuple_hash *h; |
715 | struct nf_conntrack_tuple tuple; | 715 | struct nf_conntrack_tuple tuple; |
@@ -720,22 +720,15 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
720 | int err = 0; | 720 | int err = 0; |
721 | 721 | ||
722 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 722 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
723 | u32 rlen; | ||
724 | |||
725 | #ifndef CONFIG_NF_CT_ACCT | 723 | #ifndef CONFIG_NF_CT_ACCT |
726 | if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO) | 724 | if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO) |
727 | return -ENOTSUPP; | 725 | return -ENOTSUPP; |
728 | #endif | 726 | #endif |
729 | if ((*errp = netlink_dump_start(ctnl, skb, nlh, | 727 | err = netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, |
730 | ctnetlink_dump_table, | 728 | ctnetlink_done); |
731 | ctnetlink_done)) != 0) | 729 | if (err == 0) |
732 | return -EINVAL; | 730 | err = -EINTR; |
733 | 731 | return err; | |
734 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | ||
735 | if (rlen > skb->len) | ||
736 | rlen = skb->len; | ||
737 | skb_pull(skb, rlen); | ||
738 | return 0; | ||
739 | } | 732 | } |
740 | 733 | ||
741 | if (nfattr_bad_size(cda, CTA_MAX, cta_min)) | 734 | if (nfattr_bad_size(cda, CTA_MAX, cta_min)) |
@@ -1009,7 +1002,7 @@ err: | |||
1009 | 1002 | ||
1010 | static int | 1003 | static int |
1011 | ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | 1004 | ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, |
1012 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 1005 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1013 | { | 1006 | { |
1014 | struct nf_conntrack_tuple otuple, rtuple; | 1007 | struct nf_conntrack_tuple otuple, rtuple; |
1015 | struct nf_conntrack_tuple_hash *h = NULL; | 1008 | struct nf_conntrack_tuple_hash *h = NULL; |
@@ -1260,7 +1253,7 @@ static const size_t cta_min_exp[CTA_EXPECT_MAX] = { | |||
1260 | 1253 | ||
1261 | static int | 1254 | static int |
1262 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | 1255 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, |
1263 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 1256 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1264 | { | 1257 | { |
1265 | struct nf_conntrack_tuple tuple; | 1258 | struct nf_conntrack_tuple tuple; |
1266 | struct nf_conntrack_expect *exp; | 1259 | struct nf_conntrack_expect *exp; |
@@ -1273,17 +1266,12 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1273 | return -EINVAL; | 1266 | return -EINVAL; |
1274 | 1267 | ||
1275 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1268 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1276 | u32 rlen; | 1269 | err = netlink_dump_start(ctnl, skb, nlh, |
1277 | 1270 | ctnetlink_exp_dump_table, | |
1278 | if ((*errp = netlink_dump_start(ctnl, skb, nlh, | 1271 | ctnetlink_done); |
1279 | ctnetlink_exp_dump_table, | 1272 | if (err == 0) |
1280 | ctnetlink_done)) != 0) | 1273 | err = -EINTR; |
1281 | return -EINVAL; | 1274 | return err; |
1282 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | ||
1283 | if (rlen > skb->len) | ||
1284 | rlen = skb->len; | ||
1285 | skb_pull(skb, rlen); | ||
1286 | return 0; | ||
1287 | } | 1275 | } |
1288 | 1276 | ||
1289 | if (cda[CTA_EXPECT_MASTER-1]) | 1277 | if (cda[CTA_EXPECT_MASTER-1]) |
@@ -1330,7 +1318,7 @@ out: | |||
1330 | 1318 | ||
1331 | static int | 1319 | static int |
1332 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | 1320 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, |
1333 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 1321 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1334 | { | 1322 | { |
1335 | struct nf_conntrack_expect *exp, *tmp; | 1323 | struct nf_conntrack_expect *exp, *tmp; |
1336 | struct nf_conntrack_tuple tuple; | 1324 | struct nf_conntrack_tuple tuple; |
@@ -1464,7 +1452,7 @@ out: | |||
1464 | 1452 | ||
1465 | static int | 1453 | static int |
1466 | ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | 1454 | ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, |
1467 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 1455 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1468 | { | 1456 | { |
1469 | struct nf_conntrack_tuple tuple; | 1457 | struct nf_conntrack_tuple tuple; |
1470 | struct nf_conntrack_expect *exp; | 1458 | struct nf_conntrack_expect *exp; |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index dec36abdf949..c37ed0156b07 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -195,17 +195,14 @@ int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) | |||
195 | EXPORT_SYMBOL_GPL(nfnetlink_unicast); | 195 | EXPORT_SYMBOL_GPL(nfnetlink_unicast); |
196 | 196 | ||
197 | /* Process one complete nfnetlink message. */ | 197 | /* Process one complete nfnetlink message. */ |
198 | static int nfnetlink_rcv_msg(struct sk_buff *skb, | 198 | static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
199 | struct nlmsghdr *nlh, int *errp) | ||
200 | { | 199 | { |
201 | struct nfnl_callback *nc; | 200 | struct nfnl_callback *nc; |
202 | struct nfnetlink_subsystem *ss; | 201 | struct nfnetlink_subsystem *ss; |
203 | int type, err = 0; | 202 | int type, err; |
204 | 203 | ||
205 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) { | 204 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) |
206 | *errp = -EPERM; | 205 | return -EPERM; |
207 | return -1; | ||
208 | } | ||
209 | 206 | ||
210 | /* Only requests are handled by kernel now. */ | 207 | /* Only requests are handled by kernel now. */ |
211 | if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) | 208 | if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) |
@@ -227,12 +224,12 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
227 | ss = nfnetlink_get_subsys(type); | 224 | ss = nfnetlink_get_subsys(type); |
228 | if (!ss) | 225 | if (!ss) |
229 | #endif | 226 | #endif |
230 | goto err_inval; | 227 | return -EINVAL; |
231 | } | 228 | } |
232 | 229 | ||
233 | nc = nfnetlink_find_client(type, ss); | 230 | nc = nfnetlink_find_client(type, ss); |
234 | if (!nc) | 231 | if (!nc) |
235 | goto err_inval; | 232 | return -EINVAL; |
236 | 233 | ||
237 | { | 234 | { |
238 | u_int16_t attr_count = | 235 | u_int16_t attr_count = |
@@ -243,16 +240,9 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
243 | 240 | ||
244 | err = nfnetlink_check_attributes(ss, nlh, cda); | 241 | err = nfnetlink_check_attributes(ss, nlh, cda); |
245 | if (err < 0) | 242 | if (err < 0) |
246 | goto err_inval; | 243 | return err; |
247 | 244 | return nc->call(nfnl, skb, nlh, cda); | |
248 | err = nc->call(nfnl, skb, nlh, cda, errp); | ||
249 | *errp = err; | ||
250 | return err; | ||
251 | } | 245 | } |
252 | |||
253 | err_inval: | ||
254 | *errp = -EINVAL; | ||
255 | return -1; | ||
256 | } | 246 | } |
257 | 247 | ||
258 | static void nfnetlink_rcv(struct sock *sk, int len) | 248 | static void nfnetlink_rcv(struct sock *sk, int len) |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 9709f94787f8..b174aadd73e6 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -759,7 +759,7 @@ static struct notifier_block nfulnl_rtnl_notifier = { | |||
759 | 759 | ||
760 | static int | 760 | static int |
761 | nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, | 761 | nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, |
762 | struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) | 762 | struct nlmsghdr *nlh, struct nfattr *nfqa[]) |
763 | { | 763 | { |
764 | return -ENOTSUPP; | 764 | return -ENOTSUPP; |
765 | } | 765 | } |
@@ -797,7 +797,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = { | |||
797 | 797 | ||
798 | static int | 798 | static int |
799 | nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | 799 | nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, |
800 | struct nlmsghdr *nlh, struct nfattr *nfula[], int *errp) | 800 | struct nlmsghdr *nlh, struct nfattr *nfula[]) |
801 | { | 801 | { |
802 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); | 802 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); |
803 | u_int16_t group_num = ntohs(nfmsg->res_id); | 803 | u_int16_t group_num = ntohs(nfmsg->res_id); |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b6585caa431e..9aefb1c9bfa3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -783,7 +783,7 @@ static const int nfqa_verdict_min[NFQA_MAX] = { | |||
783 | 783 | ||
784 | static int | 784 | static int |
785 | nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | 785 | nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, |
786 | struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) | 786 | struct nlmsghdr *nlh, struct nfattr *nfqa[]) |
787 | { | 787 | { |
788 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); | 788 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); |
789 | u_int16_t queue_num = ntohs(nfmsg->res_id); | 789 | u_int16_t queue_num = ntohs(nfmsg->res_id); |
@@ -848,7 +848,7 @@ err_out_put: | |||
848 | 848 | ||
849 | static int | 849 | static int |
850 | nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, | 850 | nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, |
851 | struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) | 851 | struct nlmsghdr *nlh, struct nfattr *nfqa[]) |
852 | { | 852 | { |
853 | return -ENOTSUPP; | 853 | return -ENOTSUPP; |
854 | } | 854 | } |
@@ -865,7 +865,7 @@ static struct nf_queue_handler nfqh = { | |||
865 | 865 | ||
866 | static int | 866 | static int |
867 | nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | 867 | nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, |
868 | struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) | 868 | struct nlmsghdr *nlh, struct nfattr *nfqa[]) |
869 | { | 869 | { |
870 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); | 870 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); |
871 | u_int16_t queue_num = ntohs(nfmsg->res_id); | 871 | u_int16_t queue_num = ntohs(nfmsg->res_id); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5d1079b1838c..1823b7c63156 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1463,7 +1463,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | 1465 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, |
1466 | struct nlmsghdr *, int *)) | 1466 | struct nlmsghdr *)) |
1467 | { | 1467 | { |
1468 | struct nlmsghdr *nlh; | 1468 | struct nlmsghdr *nlh; |
1469 | int err; | 1469 | int err; |
@@ -1483,13 +1483,11 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | |||
1483 | if (nlh->nlmsg_type < NLMSG_MIN_TYPE) | 1483 | if (nlh->nlmsg_type < NLMSG_MIN_TYPE) |
1484 | goto skip; | 1484 | goto skip; |
1485 | 1485 | ||
1486 | if (cb(skb, nlh, &err) < 0) { | 1486 | err = cb(skb, nlh); |
1487 | /* Not an error, but we have to interrupt processing | 1487 | if (err == -EINTR) { |
1488 | * here. Note: that in this case we do not pull | 1488 | /* Not an error, but we interrupt processing */ |
1489 | * message from skb, it will be processed later. | 1489 | netlink_queue_skip(nlh, skb); |
1490 | */ | 1490 | return err; |
1491 | if (err == 0) | ||
1492 | return -1; | ||
1493 | } | 1491 | } |
1494 | skip: | 1492 | skip: |
1495 | if (nlh->nlmsg_flags & NLM_F_ACK || err) | 1493 | if (nlh->nlmsg_flags & NLM_F_ACK || err) |
@@ -1515,9 +1513,14 @@ skip: | |||
1515 | * | 1513 | * |
1516 | * qlen must be initialized to 0 before the initial entry, afterwards | 1514 | * qlen must be initialized to 0 before the initial entry, afterwards |
1517 | * the function may be called repeatedly until qlen reaches 0. | 1515 | * the function may be called repeatedly until qlen reaches 0. |
1516 | * | ||
1517 | * The callback function may return -EINTR to signal that processing | ||
1518 | * of netlink messages shall be interrupted. In this case the message | ||
1519 | * currently being processed will NOT be requeued onto the receive | ||
1520 | * queue. | ||
1518 | */ | 1521 | */ |
1519 | void netlink_run_queue(struct sock *sk, unsigned int *qlen, | 1522 | void netlink_run_queue(struct sock *sk, unsigned int *qlen, |
1520 | int (*cb)(struct sk_buff *, struct nlmsghdr *, int *)) | 1523 | int (*cb)(struct sk_buff *, struct nlmsghdr *)) |
1521 | { | 1524 | { |
1522 | struct sk_buff *skb; | 1525 | struct sk_buff *skb; |
1523 | 1526 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 95391e609046..1b897bc92e61 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -295,60 +295,49 @@ int genl_unregister_family(struct genl_family *family) | |||
295 | return -ENOENT; | 295 | return -ENOENT; |
296 | } | 296 | } |
297 | 297 | ||
298 | static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | 298 | static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
299 | int *errp) | ||
300 | { | 299 | { |
301 | struct genl_ops *ops; | 300 | struct genl_ops *ops; |
302 | struct genl_family *family; | 301 | struct genl_family *family; |
303 | struct genl_info info; | 302 | struct genl_info info; |
304 | struct genlmsghdr *hdr = nlmsg_data(nlh); | 303 | struct genlmsghdr *hdr = nlmsg_data(nlh); |
305 | int hdrlen, err = -EINVAL; | 304 | int hdrlen, err; |
306 | 305 | ||
307 | family = genl_family_find_byid(nlh->nlmsg_type); | 306 | family = genl_family_find_byid(nlh->nlmsg_type); |
308 | if (family == NULL) { | 307 | if (family == NULL) |
309 | err = -ENOENT; | 308 | return -ENOENT; |
310 | goto errout; | ||
311 | } | ||
312 | 309 | ||
313 | hdrlen = GENL_HDRLEN + family->hdrsize; | 310 | hdrlen = GENL_HDRLEN + family->hdrsize; |
314 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) | 311 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) |
315 | goto errout; | 312 | return -EINVAL; |
316 | 313 | ||
317 | ops = genl_get_cmd(hdr->cmd, family); | 314 | ops = genl_get_cmd(hdr->cmd, family); |
318 | if (ops == NULL) { | 315 | if (ops == NULL) |
319 | err = -EOPNOTSUPP; | 316 | return -EOPNOTSUPP; |
320 | goto errout; | ||
321 | } | ||
322 | 317 | ||
323 | if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) { | 318 | if ((ops->flags & GENL_ADMIN_PERM) && |
324 | err = -EPERM; | 319 | security_netlink_recv(skb, CAP_NET_ADMIN)) |
325 | goto errout; | 320 | return -EPERM; |
326 | } | ||
327 | 321 | ||
328 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 322 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
329 | if (ops->dumpit == NULL) { | 323 | if (ops->dumpit == NULL) |
330 | err = -EOPNOTSUPP; | 324 | return -EOPNOTSUPP; |
331 | goto errout; | ||
332 | } | ||
333 | 325 | ||
334 | *errp = err = netlink_dump_start(genl_sock, skb, nlh, | 326 | err = netlink_dump_start(genl_sock, skb, nlh, |
335 | ops->dumpit, ops->done); | 327 | ops->dumpit, ops->done); |
336 | if (err == 0) | 328 | if (err == 0) |
337 | skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len), | 329 | err = -EINTR; |
338 | skb->len)); | 330 | return err; |
339 | return -1; | ||
340 | } | 331 | } |
341 | 332 | ||
342 | if (ops->doit == NULL) { | 333 | if (ops->doit == NULL) |
343 | err = -EOPNOTSUPP; | 334 | return -EOPNOTSUPP; |
344 | goto errout; | ||
345 | } | ||
346 | 335 | ||
347 | if (family->attrbuf) { | 336 | if (family->attrbuf) { |
348 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, | 337 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, |
349 | ops->policy); | 338 | ops->policy); |
350 | if (err < 0) | 339 | if (err < 0) |
351 | goto errout; | 340 | return err; |
352 | } | 341 | } |
353 | 342 | ||
354 | info.snd_seq = nlh->nlmsg_seq; | 343 | info.snd_seq = nlh->nlmsg_seq; |
@@ -358,12 +347,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
358 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; | 347 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; |
359 | info.attrs = family->attrbuf; | 348 | info.attrs = family->attrbuf; |
360 | 349 | ||
361 | *errp = err = ops->doit(skb, &info); | 350 | return ops->doit(skb, &info); |
362 | return err; | ||
363 | |||
364 | errout: | ||
365 | *errp = err; | ||
366 | return -1; | ||
367 | } | 351 | } |
368 | 352 | ||
369 | static void genl_rcv(struct sock *sk, int len) | 353 | static void genl_rcv(struct sock *sk, int len) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4d2f2094e6df..5e52d6275bad 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1852,46 +1852,39 @@ static struct xfrm_link { | |||
1852 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, | 1852 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, |
1853 | }; | 1853 | }; |
1854 | 1854 | ||
1855 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | 1855 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
1856 | { | 1856 | { |
1857 | struct rtattr *xfrma[XFRMA_MAX]; | 1857 | struct rtattr *xfrma[XFRMA_MAX]; |
1858 | struct xfrm_link *link; | 1858 | struct xfrm_link *link; |
1859 | int type, min_len; | 1859 | int type, min_len, err; |
1860 | 1860 | ||
1861 | type = nlh->nlmsg_type; | 1861 | type = nlh->nlmsg_type; |
1862 | |||
1863 | /* Unknown message: reply with EINVAL */ | ||
1864 | if (type > XFRM_MSG_MAX) | 1862 | if (type > XFRM_MSG_MAX) |
1865 | goto err_einval; | 1863 | return -EINVAL; |
1866 | 1864 | ||
1867 | type -= XFRM_MSG_BASE; | 1865 | type -= XFRM_MSG_BASE; |
1868 | link = &xfrm_dispatch[type]; | 1866 | link = &xfrm_dispatch[type]; |
1869 | 1867 | ||
1870 | /* All operations require privileges, even GET */ | 1868 | /* All operations require privileges, even GET */ |
1871 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) { | 1869 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) |
1872 | *errp = -EPERM; | 1870 | return -EPERM; |
1873 | return -1; | ||
1874 | } | ||
1875 | 1871 | ||
1876 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || | 1872 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || |
1877 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && | 1873 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && |
1878 | (nlh->nlmsg_flags & NLM_F_DUMP)) { | 1874 | (nlh->nlmsg_flags & NLM_F_DUMP)) { |
1879 | if (link->dump == NULL) | 1875 | if (link->dump == NULL) |
1880 | goto err_einval; | 1876 | return -EINVAL; |
1881 | |||
1882 | if ((*errp = netlink_dump_start(xfrm_nl, skb, nlh, | ||
1883 | link->dump, NULL)) != 0) { | ||
1884 | return -1; | ||
1885 | } | ||
1886 | 1877 | ||
1887 | netlink_queue_skip(nlh, skb); | 1878 | err = netlink_dump_start(xfrm_nl, skb, nlh, link->dump, NULL); |
1888 | return -1; | 1879 | if (err == 0) |
1880 | err = -EINTR; | ||
1881 | return err; | ||
1889 | } | 1882 | } |
1890 | 1883 | ||
1891 | memset(xfrma, 0, sizeof(xfrma)); | 1884 | memset(xfrma, 0, sizeof(xfrma)); |
1892 | 1885 | ||
1893 | if (nlh->nlmsg_len < (min_len = xfrm_msg_min[type])) | 1886 | if (nlh->nlmsg_len < (min_len = xfrm_msg_min[type])) |
1894 | goto err_einval; | 1887 | return -EINVAL; |
1895 | 1888 | ||
1896 | if (nlh->nlmsg_len > min_len) { | 1889 | if (nlh->nlmsg_len > min_len) { |
1897 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | 1890 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); |
@@ -1901,7 +1894,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err | |||
1901 | unsigned short flavor = attr->rta_type; | 1894 | unsigned short flavor = attr->rta_type; |
1902 | if (flavor) { | 1895 | if (flavor) { |
1903 | if (flavor > XFRMA_MAX) | 1896 | if (flavor > XFRMA_MAX) |
1904 | goto err_einval; | 1897 | return -EINVAL; |
1905 | xfrma[flavor - 1] = attr; | 1898 | xfrma[flavor - 1] = attr; |
1906 | } | 1899 | } |
1907 | attr = RTA_NEXT(attr, attrlen); | 1900 | attr = RTA_NEXT(attr, attrlen); |
@@ -1909,14 +1902,9 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err | |||
1909 | } | 1902 | } |
1910 | 1903 | ||
1911 | if (link->doit == NULL) | 1904 | if (link->doit == NULL) |
1912 | goto err_einval; | 1905 | return -EINVAL; |
1913 | *errp = link->doit(skb, nlh, xfrma); | ||
1914 | |||
1915 | return *errp; | ||
1916 | 1906 | ||
1917 | err_einval: | 1907 | return link->doit(skb, nlh, xfrma); |
1918 | *errp = -EINVAL; | ||
1919 | return -1; | ||
1920 | } | 1908 | } |
1921 | 1909 | ||
1922 | static void xfrm_netlink_rcv(struct sock *sk, int len) | 1910 | static void xfrm_netlink_rcv(struct sock *sk, int len) |