aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/rtnetlink.c46
-rw-r--r--net/netfilter/nf_conntrack_netlink.c46
-rw-r--r--net/netfilter/nfnetlink.c26
-rw-r--r--net/netfilter/nfnetlink_log.c4
-rw-r--r--net/netfilter/nfnetlink_queue.c6
-rw-r--r--net/netlink/af_netlink.c21
-rw-r--r--net/netlink/genetlink.c56
-rw-r--r--net/xfrm/xfrm_user.c40
8 files changed, 91 insertions, 154 deletions
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
855static __inline__ int 855static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
856rtnetlink_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
936err_inval: 922 return doit(skb, nlh, (void *)&rta_buf[0]);
937 *errp = -EINVAL;
938 return -1;
939} 923}
940 924
941static void rtnetlink_rcv(struct sock *sk, int len) 925static 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
662static int 662static int
663ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 663ctnetlink_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
710static int 710static int
711ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 711ctnetlink_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
1010static int 1003static int
1011ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 1004ctnetlink_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
1261static int 1254static int
1262ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 1255ctnetlink_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
1331static int 1319static int
1332ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 1320ctnetlink_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
1465static int 1453static int
1466ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, 1454ctnetlink_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)
195EXPORT_SYMBOL_GPL(nfnetlink_unicast); 195EXPORT_SYMBOL_GPL(nfnetlink_unicast);
196 196
197/* Process one complete nfnetlink message. */ 197/* Process one complete nfnetlink message. */
198static int nfnetlink_rcv_msg(struct sk_buff *skb, 198static 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
253err_inval:
254 *errp = -EINVAL;
255 return -1;
256} 246}
257 247
258static void nfnetlink_rcv(struct sock *sk, int len) 248static 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
760static int 760static int
761nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, 761nfulnl_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
798static int 798static int
799nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, 799nfulnl_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
784static int 784static int
785nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, 785nfqnl_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
849static int 849static int
850nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, 850nfqnl_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
866static int 866static int
867nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, 867nfqnl_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
1465static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, 1465static 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 }
1494skip: 1492skip:
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 */
1519void netlink_run_queue(struct sock *sk, unsigned int *qlen, 1522void 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
298static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 298static 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
364errout:
365 *errp = err;
366 return -1;
367} 351}
368 352
369static void genl_rcv(struct sock *sk, int len) 353static 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
1855static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) 1855static 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
1917err_einval: 1907 return link->doit(skb, nlh, xfrma);
1918 *errp = -EINVAL;
1919 return -1;
1920} 1908}
1921 1909
1922static void xfrm_netlink_rcv(struct sock *sk, int len) 1910static void xfrm_netlink_rcv(struct sock *sk, int len)