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) |
