Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netlink: fix NETLINK_RECV_NO_ENOBUFS in netlink_set_err()

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>

authored by

Pablo Neira Ayuso and committed by
David S. Miller
1a50307b 73852e81

+15 -4
+1 -1
include/linux/netlink.h
··· 188 188 extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); 189 189 extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, 190 190 __u32 group, gfp_t allocation); 191 - extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); 191 + extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); 192 192 extern int netlink_register_notifier(struct notifier_block *nb); 193 193 extern int netlink_unregister_notifier(struct notifier_block *nb); 194 194
+14 -3
net/netlink/af_netlink.c
··· 1093 1093 struct netlink_set_err_data *p) 1094 1094 { 1095 1095 struct netlink_sock *nlk = nlk_sk(sk); 1096 + int ret = 0; 1096 1097 1097 1098 if (sk == p->exclude_sk) 1098 1099 goto out; ··· 1105 1104 !test_bit(p->group - 1, nlk->groups)) 1106 1105 goto out; 1107 1106 1107 + if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { 1108 + ret = 1; 1109 + goto out; 1110 + } 1111 + 1108 1112 sk->sk_err = p->code; 1109 1113 sk->sk_error_report(sk); 1110 1114 out: 1111 - return 0; 1115 + return ret; 1112 1116 } 1113 1117 1114 1118 /** ··· 1122 1116 * @pid: the PID of a process that we want to skip (if any) 1123 1117 * @groups: the broadcast group that will notice the error 1124 1118 * @code: error code, must be negative (as usual in kernelspace) 1119 + * 1120 + * This function returns the number of broadcast listeners that have set the 1121 + * NETLINK_RECV_NO_ENOBUFS socket option. 1125 1122 */ 1126 - void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) 1123 + int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) 1127 1124 { 1128 1125 struct netlink_set_err_data info; 1129 1126 struct hlist_node *node; 1130 1127 struct sock *sk; 1128 + int ret = 0; 1131 1129 1132 1130 info.exclude_sk = ssk; 1133 1131 info.pid = pid; ··· 1142 1132 read_lock(&nl_table_lock); 1143 1133 1144 1134 sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) 1145 - do_one_set_err(sk, &info); 1135 + ret += do_one_set_err(sk, &info); 1146 1136 1147 1137 read_unlock(&nl_table_lock); 1138 + return ret; 1148 1139 } 1149 1140 EXPORT_SYMBOL(netlink_set_err); 1150 1141