aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2010-03-18 10:24:42 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 19:02:08 -0400
commit9e9b5dce350fd6f34c2c6b7440951481fb594a29 (patch)
tree28b0d6dc72d1e85f8f6bf7e88f145959997794a2
parent7532d2c8a05ad49913e05716e96c3b402e1ca8ae (diff)
netlink: fix NETLINK_RECV_NO_ENOBUFS in netlink_set_err()
[ Upstream commit 1a50307ba1826e4da0024e64b245ce4eadf7688a ] Currently, ENOBUFS errors are reported to the socket via netlink_set_err() even if NETLINK_RECV_NO_ENOBUFS is set. However, that should not happen. This fixes this problem and it changes the prototype of netlink_set_err() to return the number of sockets that have set the NETLINK_RECV_NO_ENOBUFS socket option. This return value is used in the next patch in these bugfix series. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--include/linux/netlink.h2
-rw-r--r--net/netlink/af_netlink.c17
2 files changed, 15 insertions, 4 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index fde27c017326..6eaca5e1e8ca 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -188,7 +188,7 @@ extern int netlink_has_listeners(struct sock *sk, unsigned int group);
188extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); 188extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
189extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, 189extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
190 __u32 group, gfp_t allocation); 190 __u32 group, gfp_t allocation);
191extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); 191extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
192extern int netlink_register_notifier(struct notifier_block *nb); 192extern int netlink_register_notifier(struct notifier_block *nb);
193extern int netlink_unregister_notifier(struct notifier_block *nb); 193extern int netlink_unregister_notifier(struct notifier_block *nb);
194 194
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 4c5972ba8c78..0052d3c3fe00 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk,
1093 struct netlink_set_err_data *p) 1093 struct netlink_set_err_data *p)
1094{ 1094{
1095 struct netlink_sock *nlk = nlk_sk(sk); 1095 struct netlink_sock *nlk = nlk_sk(sk);
1096 int ret = 0;
1096 1097
1097 if (sk == p->exclude_sk) 1098 if (sk == p->exclude_sk)
1098 goto out; 1099 goto out;
@@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct sock *sk,
1104 !test_bit(p->group - 1, nlk->groups)) 1105 !test_bit(p->group - 1, nlk->groups))
1105 goto out; 1106 goto out;
1106 1107
1108 if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
1109 ret = 1;
1110 goto out;
1111 }
1112
1107 sk->sk_err = p->code; 1113 sk->sk_err = p->code;
1108 sk->sk_error_report(sk); 1114 sk->sk_error_report(sk);
1109out: 1115out:
1110 return 0; 1116 return ret;
1111} 1117}
1112 1118
1113/** 1119/**
@@ -1116,12 +1122,16 @@ out:
1116 * @pid: the PID of a process that we want to skip (if any) 1122 * @pid: the PID of a process that we want to skip (if any)
1117 * @groups: the broadcast group that will notice the error 1123 * @groups: the broadcast group that will notice the error
1118 * @code: error code, must be negative (as usual in kernelspace) 1124 * @code: error code, must be negative (as usual in kernelspace)
1125 *
1126 * This function returns the number of broadcast listeners that have set the
1127 * NETLINK_RECV_NO_ENOBUFS socket option.
1119 */ 1128 */
1120void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) 1129int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1121{ 1130{
1122 struct netlink_set_err_data info; 1131 struct netlink_set_err_data info;
1123 struct hlist_node *node; 1132 struct hlist_node *node;
1124 struct sock *sk; 1133 struct sock *sk;
1134 int ret = 0;
1125 1135
1126 info.exclude_sk = ssk; 1136 info.exclude_sk = ssk;
1127 info.pid = pid; 1137 info.pid = pid;
@@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1132 read_lock(&nl_table_lock); 1142 read_lock(&nl_table_lock);
1133 1143
1134 sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) 1144 sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
1135 do_one_set_err(sk, &info); 1145 ret += do_one_set_err(sk, &info);
1136 1146
1137 read_unlock(&nl_table_lock); 1147 read_unlock(&nl_table_lock);
1148 return ret;
1138} 1149}
1139EXPORT_SYMBOL(netlink_set_err); 1150EXPORT_SYMBOL(netlink_set_err);
1140 1151