From patchwork Wed Nov 22 00:54:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10070273 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DD4C760353 for ; Wed, 22 Nov 2017 11:05:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC58529AF8 for ; Wed, 22 Nov 2017 11:05:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D130229C7F; Wed, 22 Nov 2017 11:05:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id AF88A29C72 for ; Wed, 22 Nov 2017 11:05:20 +0000 (UTC) Received: (qmail 32578 invoked by uid 550); 22 Nov 2017 11:05:18 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Delivered-To: moderator for kernel-hardening@lists.openwall.com Received: (qmail 14261 invoked from network); 22 Nov 2017 00:54:47 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:date:message-id:subject:from:to:cc; bh=57FULy53vsi3kmbvmA+loFuUOjj4d4PXjKZefu7ieCA=; b=sIC3JcqO8FI4ARCg319gb88VFe0rHUVN1V5qID1S5AW0rrA2R1zxi7P1Z+gTpWfMwJ A1S0fmpxIeO80IOFEF7LeA6sAGN5BDjjz4fm8ULqSAur+JgoevLYCCl/9Mqixp8dTVrz EAuOS0MZ0vORYGluQPFW9kvsifZ1V/FElojb6S2WRHA7jej3r5+G6WiRqoEfFm1QXsCn YotG4SekLhCoYUMeuyLMYiqx7pe0TLnrKJNJ5X/dps6cT4ecNufRWD3dCZWefogg8/Kh OBf5XdafM0bWrBdgRnYIX44PzDkpEMpyIzMJAU9FPlQFuNnFVxD7e8/lb/dZGcHVKvPL LugA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc; bh=57FULy53vsi3kmbvmA+loFuUOjj4d4PXjKZefu7ieCA=; b=jJGePpiB0pQu0lNX3Krwt9LDmW4ync7ThWtQp7ZnFe6xQUDAcbH+RavODok2o/ETVs cckNcUiCkzbd8akEfjuSNALbNSbdLmvyqC5CQF4bm6O47NYghr2qL3pN7S8L3zdMYZwz bTEe2zkLF+ztM+Qbduuhq0nFHopKEUso3wTDczl3zdqMtBaWnqWOgvvzEhu8xcN6FkQ2 ffuSdhhXXKgBx881RalKgVUL4ZromV/K1U2kNMK+Z4mXJlfN8L1FcF8ZmYVTwwO/LkS+ hsEq2wuE1TB31qrejWTenXGo5jq6dfIKTAsbT81AGjXVmjxBV2+q0ExCSfjUEiQxkjz+ 9ygw== X-Gm-Message-State: AJaThX66Eio0wij/bB4kKYIU+NgIGafqzfTDQc2czOCAZJe3hw1FKMar dK8xgyg7A5gejgkDtUjWmJNX1ZjpZ36tyq5tZXFTzQ== X-Google-Smtp-Source: AGs4zMaUart1EaP6HZUmrtvDu/2rFbG+yY6oXdlhpZkSdDduQk00d+YSfoMfJoowuy5ZMevhCYXCe77zG0ah0uv9CGxIlg== MIME-Version: 1.0 X-Received: by 10.157.44.39 with SMTP id f36mr8251230otb.56.1511312075625; Tue, 21 Nov 2017 16:54:35 -0800 (PST) Date: Tue, 21 Nov 2017 16:54:32 -0800 Message-Id: <20171122005432.4974-1-mjg59@google.com> X-Mailer: git-send-email 2.15.0.448.gf294e3d99a-goog From: Matthew Garrett To: keescook@chromium.org Cc: kernel-hardening@lists.openwall.com, Matthew Garrett Subject: [kernel-hardening] [PATCH] usercopy: Allow runtime disabling of usercopy fallback X-Virus-Scanned: ClamAV using ClamSMTP Distributions are likely to build with CONFIG_HARDENED_USERCOPY_FALLBACK, but individual sites may wish to disable that functionality. Add a sysctl that allows the fallback to be disabled and then forbids any attempt to re-enable it. Signed-off-by: Matthew Garrett --- Documentation/sysctl/vm.txt | 9 +++++++++ include/linux/mm.h | 7 +++++++ kernel/sysctl.c | 11 +++++++++++ mm/memory.c | 17 +++++++++++++++++ mm/slab.c | 4 +--- mm/slub.c | 4 +--- 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 9baf66a9ef4e..b494b292fd93 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -60,6 +60,7 @@ Currently, these files are in /proc/sys/vm: - stat_refresh - swappiness - user_reserve_kbytes +- usercopy_fallback - vfs_cache_pressure - watermark_scale_factor - zone_reclaim_mode @@ -822,6 +823,14 @@ Changing this takes effect whenever an application requests memory. ============================================================== +usercopy_fallback + +If 1, attempts to copy data from userland will generate a kernel warning +if the target has not been whitelisted, but will still be permitted. If 0, +this will result in a kernel BUG(). This may be set from 1 to 0 at runtime, +but may not be modified if 0. + +============================================================== vfs_cache_pressure ------------------ diff --git a/include/linux/mm.h b/include/linux/mm.h index f8c10d336e42..511237addbf9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2456,6 +2456,8 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, void drop_slab(void); void drop_slab_node(int nid); +extern bool usercopy_fallback; + #ifndef CONFIG_MMU #define randomize_va_space 0 #else @@ -2602,5 +2604,10 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +#ifdef CONFIG_HARDENED_USERCOPY +int usercopy_fallback_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *length, loff_t *ppos); +#endif + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 423554ad3610..ba3366335b40 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1663,6 +1663,17 @@ static struct ctl_table vm_table[] = { .extra1 = (void *)&mmap_rnd_compat_bits_min, .extra2 = (void *)&mmap_rnd_compat_bits_max, }, +#endif +#ifdef CONFIG_HARDENED_USERCOPY + { + .procname = "usercopy_fallback", + .data = &usercopy_fallback, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = usercopy_fallback_handler, + .extra1 = &zero, + .extra2 = &one, + }, #endif { } }; diff --git a/mm/memory.c b/mm/memory.c index ec4e15494901..29ed21083a8d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -104,6 +104,11 @@ EXPORT_SYMBOL(mem_map); void *high_memory; EXPORT_SYMBOL(high_memory); +#ifdef CONFIG_HARDENED_USERCOPY +/* Permit non-whitelisted usercopy targets */ +bool usercopy_fallback = IS_ENABLED(CONFIG_HARDENED_USERCOPY_FALLBACK); +#endif + /* * Randomize the address space (stacks, mmaps, brk, etc.). * @@ -4668,3 +4673,15 @@ void ptlock_free(struct page *page) kmem_cache_free(page_ptl_cachep, page->ptl); } #endif + +#ifdef CONFIG_HARDENED_USERCOPY +int usercopy_fallback_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *length, loff_t *ppos) +{ + /* Don't allow re-enabling fallback if it's been disabled */ + if (write && !usercopy_fallback) + return -EINVAL; + + return proc_dointvec_minmax(table, write, buffer, length, ppos); +} +#endif diff --git a/mm/slab.c b/mm/slab.c index 23c53dc46cd6..6afcac1d8b97 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4435,21 +4435,19 @@ const char *__check_heap_object(const void *ptr, unsigned long n, if (offset < cachep->useroffset || offset - cachep->useroffset > cachep->usersize || n > cachep->useroffset - offset + cachep->usersize) { -#ifdef CONFIG_HARDENED_USERCOPY_FALLBACK /* * If no whitelist exists, and FALLBACK is set, produce * a warning instead of rejecting the copy. This is intended * to be a temporary method to find any missing usercopy * whitelists. */ - if (cachep->usersize == 0 && + if (usercopy_fallback && cachep->usersize == 0 && offset <= cachep->object_size && n <= cachep->object_size - offset) { WARN_ONCE(1, "unexpected usercopy without slab whitelist from %s offset %lu size %lu", cachep->name, offset, n); return NULL; } -#endif return cachep->name; } diff --git a/mm/slub.c b/mm/slub.c index 82e7f15162a8..e664c6e715e6 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3867,7 +3867,6 @@ const char *__check_heap_object(const void *ptr, unsigned long n, if (offset < s->useroffset || offset - s->useroffset > s->usersize || n > s->useroffset - offset + s->usersize) { -#ifdef CONFIG_HARDENED_USERCOPY_FALLBACK size_t object_size; object_size = slab_ksize(s); @@ -3878,13 +3877,12 @@ const char *__check_heap_object(const void *ptr, unsigned long n, * to be a temporary method to find any missing usercopy * whitelists. */ - if (s->usersize == 0 && + if (usercopy_fallback && s->usersize == 0 && (offset <= object_size && n <= object_size - offset)) { WARN_ONCE(1, "unexpected usercopy without slab whitelist from %s offset %lu size %lu", s->name, offset, n); return NULL; } -#endif return s->name; }