aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2007-03-23 02:30:12 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:27:30 -0400
commit1d00a4eb42bdade33a6ec0961cada93577a66ae6 (patch)
treea181b141818f594eb544601386bf09e45e6193bb
parent45e7ae7f716086994e4e747226881f901c67b031 (diff)
[NETLINK]: Remove error pointer from netlink message handler
The error pointer argument in netlink message handlers is used to signal the special case where processing has to be interrupted because a dump was started but no error happened. Instead it is simpler and more clear to return -EINTR and have netlink_run_queue() deal with getting the queue right. nfnetlink passed on this error pointer to its subsystem handlers but only uses it to signal the start of a netlink dump. Therefore it can be removed there as well. This patch also cleans up the error handling in the affected message handlers to be consistent since it had to be touched anyway. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/nfnetlink.h2
-rw-r--r--include/net/netlink.h2
-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
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 {
111struct nfnl_callback 111struct 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
215extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, 215extern 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 *));
218extern void netlink_queue_skip(struct nlmsghdr *nlh, 218extern void netlink_queue_skip(struct nlmsghdr *nlh,
219 struct sk_buff *skb); 219 struct sk_buff *skb);
220extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, 220extern 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
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)