summaryrefslogtreecommitdiff
path: root/net/netlink
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-10-08 23:44:00 -0400
committerJiri Slaby <jslaby@suse.cz>2014-11-13 19:02:16 +0100
commitec84c5e8a19be56aa297f195885e0303a956230f (patch)
treedccb125f4437cb6cada5069619f9c47278a8c0a8 /net/netlink
parentca57f7e423849774b8fbc4547c8a7f43b876216b (diff)
downloadlwn-ec84c5e8a19be56aa297f195885e0303a956230f.tar.gz
lwn-ec84c5e8a19be56aa297f195885e0303a956230f.zip
fix misuses of f_count() in ppp and netlink
commit 24dff96a37a2ca319e75a74d3929b2de22447ca6 upstream. we used to check for "nobody else could start doing anything with that opened file" by checking that refcount was 2 or less - one for descriptor table and one we'd acquired in fget() on the way to wherever we are. That was race-prone (somebody else might have had a reference to descriptor table and do fget() just as we'd been checking) and it had become flat-out incorrect back when we switched to fget_light() on those codepaths - unlike fget(), it doesn't grab an extra reference unless the descriptor table is shared. The same change allowed a race-free check, though - we are safe exactly when refcount is less than 2. It was a long time ago; pre-2.6.12 for ioctl() (the codepath leading to ppp one) and 2.6.17 for sendmsg() (netlink one). OTOH, netlink hadn't grown that check until 3.9 and ppp used to live in drivers/net, not drivers/net/ppp until 3.1. The bug existed well before that, though, and the same fix used to apply in old location of file. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2a4f35e7b5c0..2735facbbf91 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -699,7 +699,7 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg,
* after validation, the socket and the ring may only be used by a
* single process, otherwise we fall back to copying.
*/
- if (atomic_long_read(&sk->sk_socket->file->f_count) > 2 ||
+ if (atomic_long_read(&sk->sk_socket->file->f_count) > 1 ||
atomic_read(&nlk->mapped) > 1)
excl = false;