| From d8e9e5e80e882b4f90cba7edf1e6cb7376e52e54 Mon Sep 17 00:00:00 2001 |
| From: Richard Weinberger <richard@nod.at> |
| Date: Wed, 9 Nov 2016 22:52:58 +0100 |
| Subject: drbd: Fix kernel_sendmsg() usage - potential NULL deref |
| |
| From: Richard Weinberger <richard@nod.at> |
| |
| commit d8e9e5e80e882b4f90cba7edf1e6cb7376e52e54 upstream. |
| |
| Don't pass a size larger than iov_len to kernel_sendmsg(). |
| Otherwise it will cause a NULL pointer deref when kernel_sendmsg() |
| returns with rv < size. |
| |
| DRBD as external module has been around in the kernel 2.4 days already. |
| We used to be compatible to 2.4 and very early 2.6 kernels, |
| we used to use |
| rv = sock_sendmsg(sock, &msg, iov.iov_len); |
| then later changed to |
| rv = kernel_sendmsg(sock, &msg, &iov, 1, size); |
| when we should have used |
| rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); |
| |
| tcp_sendmsg() used to totally ignore the size parameter. |
| 57be5bd ip: convert tcp_sendmsg() to iov_iter primitives |
| changes that, and exposes our long standing error. |
| |
| Even with this error exposed, to trigger the bug, we would need to have |
| an environment (config or otherwise) causing us to not use sendpage() |
| for larger transfers, a failing connection, and have it fail "just at the |
| right time". Apparently that was unlikely enough for most, so this went |
| unnoticed for years. |
| |
| Still, it is known to trigger at least some of these, |
| and suspected for the others: |
| [0] http://lists.linbit.com/pipermail/drbd-user/2016-July/023112.html |
| [1] http://lists.linbit.com/pipermail/drbd-dev/2016-March/003362.html |
| [2] https://forums.grsecurity.net/viewtopic.php?f=3&t=4546 |
| [3] https://ubuntuforums.org/showthread.php?t=2336150 |
| [4] http://e2.howsolveproblem.com/i/1175162/ |
| |
| This should go into 4.9, |
| and into all stable branches since and including v4.0, |
| which is the first to contain the exposing change. |
| |
| It is correct for all stable branches older than that as well |
| (which contain the DRBD driver; which is 2.6.33 and up). |
| |
| It requires a small "conflict" resolution for v4.4 and earlier, with v4.5 |
| we dropped the comment block immediately preceding the kernel_sendmsg(). |
| |
| Fixes: b411b3637fa7 ("The DRBD driver") |
| Cc: viro@zeniv.linux.org.uk |
| Cc: christoph.lechleitner@iteg.at |
| Cc: wolfgang.glas@iteg.at |
| Reported-by: Christoph Lechleitner <christoph.lechleitner@iteg.at> |
| Tested-by: Christoph Lechleitner <christoph.lechleitner@iteg.at> |
| Signed-off-by: Richard Weinberger <richard@nod.at> |
| [changed oneliner to be "obvious" without context; more verbose message] |
| Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> |
| Signed-off-by: Jens Axboe <axboe@fb.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/block/drbd/drbd_main.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/block/drbd/drbd_main.c |
| +++ b/drivers/block/drbd/drbd_main.c |
| @@ -1802,7 +1802,7 @@ int drbd_send(struct drbd_connection *co |
| * do we need to block DRBD_SIG if sock == &meta.socket ?? |
| * otherwise wake_asender() might interrupt some send_*Ack ! |
| */ |
| - rv = kernel_sendmsg(sock, &msg, &iov, 1, size); |
| + rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); |
| if (rv == -EAGAIN) { |
| if (we_should_drop_the_connection(connection, sock)) |
| break; |