From 30c2c9f158f6c9cef41e916d1c7c11097df4befb Mon Sep 17 00:00:00 2001 From: David Windsor Date: Sat, 10 Jun 2017 22:50:42 -0400 Subject: net: Define usercopy region in struct proto slab cache In support of usercopy hardening, this patch defines a region in the struct proto slab cache in which userspace copy operations are allowed. Some protocols need to copy objects to/from userspace, and they can declare the region via their proto structure with the new usersize and useroffset fields. Initially, if no region is specified (usersize == 0), the entire field is marked as whitelisted. This allows protocols to be whitelisted in subsequent patches. Once all protocols have been annotated, the full-whitelist default can be removed. This region is known as the slab cache's usercopy region. Slab caches can now check that each dynamically sized copy operation involving cache-managed memory falls entirely within the slab's usercopy region. This patch is modified from Brad Spengler/PaX Team's PAX_USERCOPY whitelisting code in the last public patch of grsecurity/PaX based on my understanding of the code. Changes or omissions from the original code are mine and don't reflect the original grsecurity/PaX code. Signed-off-by: David Windsor [kees: adjust commit log, split off per-proto patches] [kees: add logic for by-default full-whitelist] Cc: "David S. Miller" Cc: Eric Dumazet Cc: Paolo Abeni Cc: David Howells Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook --- net/core/sock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net/core') diff --git a/net/core/sock.c b/net/core/sock.c index c0b5b2f17412..261e6dbf0259 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -3151,8 +3151,12 @@ static int req_prot_init(const struct proto *prot) int proto_register(struct proto *prot, int alloc_slab) { if (alloc_slab) { - prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, + prot->slab = kmem_cache_create_usercopy(prot->name, + prot->obj_size, 0, SLAB_HWCACHE_ALIGN | prot->slab_flags, + prot->usersize ? prot->useroffset : 0, + prot->usersize ? prot->usersize + : prot->obj_size, NULL); if (prot->slab == NULL) { -- cgit v1.2.3 From 289a4860d1f5de35b308c1c9e7c8592022c90af9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 24 Aug 2017 16:59:38 -0700 Subject: net: Restrict unwhitelisted proto caches to size 0 Now that protocols have been annotated (the copy of icsk_ca_ops->name is of an ops field from outside the slab cache): $ git grep 'copy_.*_user.*sk.*->' caif/caif_socket.c: copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { ipv4/raw.c: if (copy_from_user(&raw_sk(sk)->filter, optval, optlen)) ipv4/raw.c: copy_to_user(optval, &raw_sk(sk)->filter, len)) ipv4/tcp.c: if (copy_to_user(optval, icsk->icsk_ca_ops->name, len)) ipv4/tcp.c: if (copy_to_user(optval, icsk->icsk_ulp_ops->name, len)) ipv6/raw.c: if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen)) ipv6/raw.c: if (copy_to_user(optval, &raw6_sk(sk)->filter, len)) sctp/socket.c: if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) sctp/socket.c: if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) sctp/socket.c: if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len)) we can switch the default proto usercopy region to size 0. Any protocols needing to add whitelisted regions must annotate the fields with the useroffset and usersize fields of struct proto. This patch is modified from Brad Spengler/PaX Team's PAX_USERCOPY whitelisting code in the last public patch of grsecurity/PaX based on my understanding of the code. Changes or omissions from the original code are mine and don't reflect the original grsecurity/PaX code. Cc: "David S. Miller" Cc: Eric Dumazet Cc: Paolo Abeni Cc: David Howells Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook --- net/core/sock.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/core') diff --git a/net/core/sock.c b/net/core/sock.c index 261e6dbf0259..f39206b41b32 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -3154,9 +3154,7 @@ int proto_register(struct proto *prot, int alloc_slab) prot->slab = kmem_cache_create_usercopy(prot->name, prot->obj_size, 0, SLAB_HWCACHE_ALIGN | prot->slab_flags, - prot->usersize ? prot->useroffset : 0, - prot->usersize ? prot->usersize - : prot->obj_size, + prot->useroffset, prot->usersize, NULL); if (prot->slab == NULL) { -- cgit v1.2.3