From: Kees Cook <keescook@chromium.org>
To: syzbot+e2d6cfb305e9f3911dea@syzkaller.appspotmail.com
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
Eric Biggers <ebiggers3@gmail.com>,
james.morse@arm.com, keun-o.park@darkmatter.ae,
labbott@redhat.com, linux-mm@kvack.org, mingo@kernel.org
Subject: [PATCH] socket: Provide bounce buffer for constant sized put_cmsg()
Date: Thu, 1 Feb 2018 02:41:43 -0800 [thread overview]
Message-ID: <20180201104143.GA10983@beast> (raw)
Most callers of put_cmsg() use a "sizeof(foo)" for the length argument.
Within put_cmsg(), a copy_to_user() call is made with a dynamic size, as a
result of the cmsg header calculations. This means that hardened usercopy
will examine the copy, even though it was technically a fixed size and
should be implicitly whitelisted. Since most whitelists for put_cmsg()
would need to be in skbuff_head_cache on a per-protocol basis, avoid this
complexity by just providing small bounce buffers where the size is fixed.
Original report was:
Bad or missing usercopy whitelist? Kernel memory exposure attempt detected from SLAB object 'skbuff_head_cache' (offset 64, size 16)!
WARNING: CPU: 0 PID: 3663 at mm/usercopy.c:81 usercopy_warn+0xdb/0x100 mm/usercopy.c:76
...
__check_heap_object+0x89/0xc0 mm/slab.c:4426
check_heap_object mm/usercopy.c:236 [inline]
__check_object_size+0x272/0x530 mm/usercopy.c:259
check_object_size include/linux/thread_info.h:112 [inline]
check_copy_size include/linux/thread_info.h:143 [inline]
copy_to_user include/linux/uaccess.h:154 [inline]
put_cmsg+0x233/0x3f0 net/core/scm.c:242
sock_recv_errqueue+0x200/0x3e0 net/core/sock.c:2913
packet_recvmsg+0xb2e/0x17a0 net/packet/af_packet.c:3296
sock_recvmsg_nosec net/socket.c:803 [inline]
sock_recvmsg+0xc9/0x110 net/socket.c:810
___sys_recvmsg+0x2a4/0x640 net/socket.c:2179
__sys_recvmmsg+0x2a9/0xaf0 net/socket.c:2287
SYSC_recvmmsg net/socket.c:2368 [inline]
SyS_recvmmsg+0xc4/0x160 net/socket.c:2352
entry_SYSCALL_64_fastpath+0x29/0xa0
Reported-by: syzbot+e2d6cfb305e9f3911dea@syzkaller.appspotmail.com
Fixes: 6d07d1cd300f ("usercopy: Restrict non-usercopy caches to size 0")
Signed-off-by: Kees Cook <keescook@chromium.org>
---
include/linux/socket.h | 18 +++++++++++++++++-
net/core/scm.c | 4 ++--
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9286a5a8c60c..b3c5a075b7b3 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -342,7 +342,23 @@ struct ucred {
#define IPX_TYPE 1
extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
-extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+extern int __put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+/*
+ * Provide a bounce buffer for copying cmsg data to userspace when the size
+ * is constant. Without this, hardened usercopy will see the dynamic size
+ * calculation in __put_cmsg and try to block it. Constant sized copies
+ * should not trigger hardened usercopy checks.
+ */
+#define put_cmsg(_msg, _level, _type, _len, _ptr) ({ \
+ int _rc; \
+ if (__builtin_constant_p(_len)) { \
+ typeof(*(_ptr)) _val = *(_ptr); \
+ BUILD_BUG_ON(sizeof(_val) != (_len)); \
+ _rc = __put_cmsg(_msg, _level, _type, sizeof(_val), &_val); \
+ } else { \
+ _rc = __put_cmsg(_msg, _level, _type, _len, _ptr); \
+ } \
+ _rc;})
struct timespec;
diff --git a/net/core/scm.c b/net/core/scm.c
index b1ff8a441748..3a3ecf528800 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -213,7 +213,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
}
EXPORT_SYMBOL(__scm_send);
-int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
+int __put_cmsg(struct msghdr *msg, int level, int type, int len, void *data)
{
struct cmsghdr __user *cm
= (__force struct cmsghdr __user *)msg->msg_control;
@@ -250,7 +250,7 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
out:
return err;
}
-EXPORT_SYMBOL(put_cmsg);
+EXPORT_SYMBOL(__put_cmsg);
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
{
--
2.7.4
--
Kees Cook
Pixel Security
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
WARNING: multiple messages have this Message-ID (diff)
From: Kees Cook <keescook@chromium.org>
To: syzbot+e2d6cfb305e9f3911dea@syzkaller.appspotmail.com
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
Eric Biggers <ebiggers3@gmail.com>,
james.morse@arm.com, keun-o.park@darkmatter.ae,
labbott@redhat.com, linux-mm@kvack.org, mingo@kernel.org
Subject: [PATCH] socket: Provide bounce buffer for constant sized put_cmsg()
Date: Thu, 1 Feb 2018 02:41:43 -0800 [thread overview]
Message-ID: <20180201104143.GA10983@beast> (raw)
Most callers of put_cmsg() use a "sizeof(foo)" for the length argument.
Within put_cmsg(), a copy_to_user() call is made with a dynamic size, as a
result of the cmsg header calculations. This means that hardened usercopy
will examine the copy, even though it was technically a fixed size and
should be implicitly whitelisted. Since most whitelists for put_cmsg()
would need to be in skbuff_head_cache on a per-protocol basis, avoid this
complexity by just providing small bounce buffers where the size is fixed.
Original report was:
Bad or missing usercopy whitelist? Kernel memory exposure attempt detected from SLAB object 'skbuff_head_cache' (offset 64, size 16)!
WARNING: CPU: 0 PID: 3663 at mm/usercopy.c:81 usercopy_warn+0xdb/0x100 mm/usercopy.c:76
...
__check_heap_object+0x89/0xc0 mm/slab.c:4426
check_heap_object mm/usercopy.c:236 [inline]
__check_object_size+0x272/0x530 mm/usercopy.c:259
check_object_size include/linux/thread_info.h:112 [inline]
check_copy_size include/linux/thread_info.h:143 [inline]
copy_to_user include/linux/uaccess.h:154 [inline]
put_cmsg+0x233/0x3f0 net/core/scm.c:242
sock_recv_errqueue+0x200/0x3e0 net/core/sock.c:2913
packet_recvmsg+0xb2e/0x17a0 net/packet/af_packet.c:3296
sock_recvmsg_nosec net/socket.c:803 [inline]
sock_recvmsg+0xc9/0x110 net/socket.c:810
___sys_recvmsg+0x2a4/0x640 net/socket.c:2179
__sys_recvmmsg+0x2a9/0xaf0 net/socket.c:2287
SYSC_recvmmsg net/socket.c:2368 [inline]
SyS_recvmmsg+0xc4/0x160 net/socket.c:2352
entry_SYSCALL_64_fastpath+0x29/0xa0
Reported-by: syzbot+e2d6cfb305e9f3911dea@syzkaller.appspotmail.com
Fixes: 6d07d1cd300f ("usercopy: Restrict non-usercopy caches to size 0")
Signed-off-by: Kees Cook <keescook@chromium.org>
---
include/linux/socket.h | 18 +++++++++++++++++-
net/core/scm.c | 4 ++--
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9286a5a8c60c..b3c5a075b7b3 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -342,7 +342,23 @@ struct ucred {
#define IPX_TYPE 1
extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
-extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+extern int __put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+/*
+ * Provide a bounce buffer for copying cmsg data to userspace when the size
+ * is constant. Without this, hardened usercopy will see the dynamic size
+ * calculation in __put_cmsg and try to block it. Constant sized copies
+ * should not trigger hardened usercopy checks.
+ */
+#define put_cmsg(_msg, _level, _type, _len, _ptr) ({ \
+ int _rc; \
+ if (__builtin_constant_p(_len)) { \
+ typeof(*(_ptr)) _val = *(_ptr); \
+ BUILD_BUG_ON(sizeof(_val) != (_len)); \
+ _rc = __put_cmsg(_msg, _level, _type, sizeof(_val), &_val); \
+ } else { \
+ _rc = __put_cmsg(_msg, _level, _type, _len, _ptr); \
+ } \
+ _rc;})
struct timespec;
diff --git a/net/core/scm.c b/net/core/scm.c
index b1ff8a441748..3a3ecf528800 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -213,7 +213,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
}
EXPORT_SYMBOL(__scm_send);
-int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
+int __put_cmsg(struct msghdr *msg, int level, int type, int len, void *data)
{
struct cmsghdr __user *cm
= (__force struct cmsghdr __user *)msg->msg_control;
@@ -250,7 +250,7 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
out:
return err;
}
-EXPORT_SYMBOL(put_cmsg);
+EXPORT_SYMBOL(__put_cmsg);
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
{
--
2.7.4
--
Kees Cook
Pixel Security
next reply other threads:[~2018-02-01 10:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-01 10:41 Kees Cook [this message]
2018-02-01 10:41 ` [PATCH] socket: Provide bounce buffer for constant sized put_cmsg() Kees Cook
2018-02-02 4:30 ` kbuild test robot
2018-02-02 6:34 ` kbuild test robot
2018-02-02 6:34 ` kbuild test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180201104143.GA10983@beast \
--to=keescook@chromium.org \
--cc=ebiggers3@gmail.com \
--cc=james.morse@arm.com \
--cc=keun-o.park@darkmatter.ae \
--cc=labbott@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mingo@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=syzbot+e2d6cfb305e9f3911dea@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.