| From 24dff96a37a2ca319e75a74d3929b2de22447ca6 Mon Sep 17 00:00:00 2001 |
| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Wed, 8 Oct 2014 23:44:00 -0400 |
| Subject: fix misuses of f_count() in ppp and netlink |
| |
| From: Al Viro <viro@zeniv.linux.org.uk> |
| |
| 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/ppp/ppp_generic.c | 2 +- |
| net/netlink/af_netlink.c | 2 +- |
| 2 files changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/ppp/ppp_generic.c |
| +++ b/drivers/net/ppp/ppp_generic.c |
| @@ -594,7 +594,7 @@ static long ppp_ioctl(struct file *file, |
| if (file == ppp->owner) |
| ppp_shutdown_interface(ppp); |
| } |
| - if (atomic_long_read(&file->f_count) <= 2) { |
| + if (atomic_long_read(&file->f_count) < 2) { |
| ppp_release(NULL, file); |
| err = 0; |
| } else |
| --- a/net/netlink/af_netlink.c |
| +++ b/net/netlink/af_netlink.c |
| @@ -723,7 +723,7 @@ static int netlink_mmap_sendmsg(struct s |
| * 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; |
| |