From patchwork Fri Oct 19 20:47:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Edgecombe, Rick P" X-Patchwork-Id: 10650189 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9108112B for ; Fri, 19 Oct 2018 20:52:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A4F9927FA3 for ; Fri, 19 Oct 2018 20:52:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 982D828451; Fri, 19 Oct 2018 20:52:47 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5A9D627FA3 for ; Fri, 19 Oct 2018 20:52:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=tC61Gjjw/4ZScEIzTc5jDjojWJo2FMJ6P/TF1VK2XYg=; b=t8cdAkyKIRwHmWd7+/yfz+szLa oo1wkszvhy0OeE9ouVke8eY6h9PskplOVhpdpcdGvyqfZeVZuxAsm0T8KlvBgia/bTpPVknyaq71L odL6reJzfNmMbVFSsvznYi+y7HteM1XE+1gmKumEVK3/d4zrSsLoWmjbBz/w8b6ZU/voM33U+V2dP kXyfdfHSiQRg4xbUaMr0yI5o/Lgqx0ieCMJ10SgdWjThb/0vGhKPFEOkipOIeYdaUS1qtP6Rg7BA3 W39cnEv8mB80Jc5VFPNd/K9D+8W4e8FG0RE2hsXSbtIE0PGlAto6wEzSZ5FLK9JRnkyAx07ahlEhU 6ZBsZS4Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gDbkv-0006Pn-Ru; Fri, 19 Oct 2018 20:52:25 +0000 Received: from mga07.intel.com ([134.134.136.100]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gDbjh-0005o2-U3 for linux-arm-kernel@lists.infradead.org; Fri, 19 Oct 2018 20:51:20 +0000 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Oct 2018 13:50:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,401,1534834800"; d="scan'208";a="100971849" Received: from rpedgeco-desk5.jf.intel.com ([10.54.75.168]) by orsmga001.jf.intel.com with ESMTP; 19 Oct 2018 13:50:51 -0700 From: Rick Edgecombe To: kernel-hardening@lists.openwall.com, daniel@iogearbox.net, keescook@chromium.org, catalin.marinas@arm.com, will.deacon@arm.com, davem@davemloft.net, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, x86@kernel.org, arnd@arndb.de, jeyu@kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mips@linux-mips.org, linux-s390@vger.kernel.org, sparclinux@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, jannh@google.com Subject: [PATCH v3 3/3] bpf: Add system wide BPF JIT limit Date: Fri, 19 Oct 2018 13:47:23 -0700 Message-Id: <20181019204723.3903-4-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181019204723.3903-1-rick.p.edgecombe@intel.com> References: <20181019204723.3903-1-rick.p.edgecombe@intel.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181019_135110_059592_3DF72EE2 X-CRM114-Status: GOOD ( 18.04 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dave.hansen@intel.com, deneen.t.dock@intel.com, Rick Edgecombe , arjan@linux.intel.com, kristen@linux.intel.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP In case of games played with multiple users, also add a system wide limit (in bytes) for BPF JIT. The default intends to be big enough for 10000 BPF JIT filters. This cannot help with the DOS in the case of CONFIG_BPF_JIT_ALWAYS_ON, but it can help with DOS for module space and with forcing a module to be loaded at a paticular address. The limit can be set like this: echo 5000000 > /proc/sys/net/core/bpf_jit_limit Signed-off-by: Rick Edgecombe --- include/linux/bpf.h | 7 +++++++ include/linux/filter.h | 1 + kernel/bpf/core.c | 22 +++++++++++++++++++++- kernel/bpf/inode.c | 16 ++++++++++++++++ net/core/sysctl_net_core.c | 7 +++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 523481a3471b..4d7b729a1fe7 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -827,4 +827,11 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto; void bpf_user_rnd_init_once(void); u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); +#ifndef MOD_BPF_LIMIT_DEFAULT +/* + * Leave room for 10000 large eBPF filters as default. + */ +#define MOD_BPF_LIMIT_DEFAULT (5 * PAGE_SIZE * 10000) +#endif + #endif /* _LINUX_BPF_H */ diff --git a/include/linux/filter.h b/include/linux/filter.h index 6791a0ac0139..3e91ffc7962b 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -854,6 +854,7 @@ bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk, extern int bpf_jit_enable; extern int bpf_jit_harden; extern int bpf_jit_kallsyms; +extern int bpf_jit_limit; typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 3f5bf1af0826..12c20fa6f04b 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -369,6 +369,9 @@ void bpf_prog_kallsyms_del_all(struct bpf_prog *fp) int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_ALWAYS_ON); int bpf_jit_harden __read_mostly; int bpf_jit_kallsyms __read_mostly; +int bpf_jit_limit __read_mostly; + +static atomic_long_t module_vm; static __always_inline void bpf_get_prog_addr_region(const struct bpf_prog *prog, @@ -583,17 +586,31 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, bpf_jit_fill_hole_t bpf_fill_ill_insns) { struct bpf_binary_header *hdr; - unsigned int size, hole, start; + unsigned int size, hole, start, vpages; /* Most of BPF filters are really small, but if some of them * fill a page, allow at least 128 extra bytes to insert a * random section of illegal instructions. */ size = round_up(proglen + sizeof(*hdr) + 128, PAGE_SIZE); + + /* Size plus a guard page */ + vpages = (PAGE_ALIGN(size) >> PAGE_SHIFT) + 1; + + if (atomic_long_read(&module_vm) + vpages > bpf_jit_limit >> PAGE_SHIFT) + return NULL; + hdr = module_alloc(size); if (hdr == NULL) return NULL; + atomic_long_add(vpages, &module_vm); + + if (atomic_long_read(&module_vm) > bpf_jit_limit >> PAGE_SHIFT) { + bpf_jit_binary_free(hdr); + return NULL; + } + /* Fill space with illegal/arch-dep instructions. */ bpf_fill_ill_insns(hdr, size); @@ -610,7 +627,10 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, void bpf_jit_binary_free(struct bpf_binary_header *hdr) { + /* Size plus the guard page */ + unsigned int vpages = hdr->pages + 1; module_memfree(hdr); + atomic_long_sub(vpages, &module_vm); } /* This symbol is only overridden by archs that have different diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 2ada5e21dfa6..d0a109733294 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -667,10 +667,26 @@ static struct file_system_type bpf_fs_type = { .kill_sb = kill_litter_super, }; +#ifdef CONFIG_BPF_JIT +void set_bpf_jit_limit(void) +{ + bpf_jit_limit = MOD_BPF_LIMIT_DEFAULT; +} +#else +void set_bpf_jit_limit(void) +{ +} +#endif + static int __init bpf_init(void) { int ret; + /* + * Module space size can be non-compile time constant so set it here. + */ + set_bpf_jit_limit(); + ret = sysfs_create_mount_point(fs_kobj, "bpf"); if (ret) return ret; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index b1a2c5e38530..6bdf4a3da2b2 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -396,6 +396,13 @@ static struct ctl_table net_core_table[] = { .extra1 = &zero, .extra2 = &one, }, + { + .procname = "bpf_jit_limit", + .data = &bpf_jit_limit, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, # endif #endif {