From patchwork Mon Nov 27 17:18:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Djalal Harouni X-Patchwork-Id: 10077643 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 84F9C602BC for ; Mon, 27 Nov 2017 17:19:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6606A28DC1 for ; Mon, 27 Nov 2017 17:19:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 58E7428E4E; Mon, 27 Nov 2017 17:19: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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 05C6A28DC1 for ; Mon, 27 Nov 2017 17:19:45 +0000 (UTC) Received: (qmail 30705 invoked by uid 550); 27 Nov 2017 17:19:31 -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 Received: (qmail 30321 invoked from network); 27 Nov 2017 17:19:23 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iDvvJ1JYnDduZRCoBQfGyFwA6kMXuKxwHPeddDtjMoI=; b=TlzPoVPyUM8g92nxwyLsSdSq0UJq1hZM/SWTwujk7EiEDNPDqt+sDotVw0N0VHs8kD zTUxptzxIaD60wVf9QPf1luEWaqS2RLWctcY0a970E45YMrIqAA7GxpQ6YyaxnYSFMve oDwmFSHhyNzXT9RT9Th9R/U5fNvS3tMTIaki5XBw6CA308ittxO1ZX1pm/mkQR+Nw0/X MmHnF21GUINXHMNLThKNCZKDy8r12Cf7Z4zMaKEAWxXyxvBOiGCQlkvC2YyqHAKum1xj FSaG0aRVzc6OayiIltbHYF9PjrbdK1edtJpjqSsEJqeWJ5Mm0V5+oSBfpiOzDjxf/BkI fZYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iDvvJ1JYnDduZRCoBQfGyFwA6kMXuKxwHPeddDtjMoI=; b=VyAPanstj3B7Wa0TKJ5OH+AbvRQPe00AiWBYiDeRc6+BdBm0qiFgtHFoJLaeRxdAmH FxZAF8GORDq8uxc1ABiXXKs9B/rl2/xFqiCawWC2IoDSiI6eZota9d+mFyigElKUwj12 GTWAaBh9aMOsNB7vT54SFFsbau5gRq3GbxgagiplGF1YR5QOH/FTduy0jyEq8fDxMa3j /4BGamvw858ia7f8LIJqfv2FU0YRlooKGXGwnG+hBpjLzNl7tjRbC53yrfbiST1fSVIb D3ArKfMqFx7fwAtEFCmiHthC7MxksWM0qtTPkmSjhDXPF1qCyGeBlySjijOMDlk4ADju B1tg== X-Gm-Message-State: AJaThX5gEKr3Gr/3ka5FbLMD/NOfeoi+qQpUybPgum4P11uogYeGpSwY dBvyl0BCDCAarXPTKvL5r9c= X-Google-Smtp-Source: AGs4zMZcX1C4F7xBGP0FFQPY1mEdBEcs7ZIUKuSH/T1tZk1RR0k6sTjHO+rPdffhVX0NOLvyqLaV9g== X-Received: by 10.80.244.132 with SMTP id s4mr53552844edm.294.1511803151917; Mon, 27 Nov 2017 09:19:11 -0800 (PST) From: Djalal Harouni To: Kees Cook , Andy Lutomirski , Andrew Morton , "Luis R. Rodriguez" , James Morris , Ben Hutchings , Solar Designer , Serge Hallyn , Jessica Yu , Rusty Russell , linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, kernel-hardening@lists.openwall.com Cc: Jonathan Corbet , Ingo Molnar , "David S. Miller" , netdev@vger.kernel.org, Peter Zijlstra , Linus Torvalds , Djalal Harouni Date: Mon, 27 Nov 2017 18:18:35 +0100 Message-Id: <1511803118-2552-3-git-send-email-tixxdz@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1511803118-2552-1-git-send-email-tixxdz@gmail.com> References: <1511803118-2552-1-git-send-email-tixxdz@gmail.com> Subject: [kernel-hardening] [PATCH v5 next 2/5] modules:capabilities: add cap_kernel_module_request() permission check X-Virus-Scanned: ClamAV using ClamSMTP This is a preparation patch to improve for the module auto-load infrastrucutre. With this change, subsystems that want to autoload modules and implement onsite capability checks, can defer the checks to the capability subsystem by passing the required capabilities with the appropriate modules alias. The capability subsystem will trust callers about the passed values and perform a capability check to either allow module auto-loading or deny it. This patch changes: * Adds cap_kernel_module_request() capability hook. * Adds an empty may_autoload_module() that will be updated in the next patch. Cc: James Morris Cc: Serge Hallyn Cc: Andy Lutomirski Cc: Ben Hutchings Suggested-by: Rusty Russell Suggested-by: Kees Cook Signed-off-by: Djalal Harouni --- include/linux/module.h | 10 ++++++++++ include/linux/security.h | 4 +++- kernel/module.c | 23 +++++++++++++++++++++++ security/commoncap.c | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/linux/module.h b/include/linux/module.h index c69b49a..5cbb239 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -497,6 +497,10 @@ bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr); bool is_module_percpu_address(unsigned long addr); bool is_module_text_address(unsigned long addr); +/* Determine whether a module auto-load operation is permitted. */ +int may_autoload_module(char *kmod_name, int required_cap, + const char *kmod_prefix); + static inline bool within_module_core(unsigned long addr, const struct module *mod) { @@ -643,6 +647,12 @@ bool is_module_sig_enforced(void); #else /* !CONFIG_MODULES... */ +static inline int may_autoload_module(char *kmod_name, int required_cap, + const char *kmod_prefix) +{ + return -ENOSYS; +} + static inline struct module *__module_address(unsigned long addr) { return NULL; diff --git a/include/linux/security.h b/include/linux/security.h index 41e700a..9bb53b5 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -102,6 +102,8 @@ extern int cap_task_setscheduler(struct task_struct *p); extern int cap_task_setioprio(struct task_struct *p, int ioprio); extern int cap_task_setnice(struct task_struct *p, int nice); extern int cap_vm_enough_memory(struct mm_struct *mm, long pages); +extern int cap_kernel_module_request(char *kmod_name, int required_cap, + const char *kmod_prefix); struct msghdr; struct sk_buff; @@ -924,7 +926,7 @@ static inline int security_kernel_module_request(char *kmod_name, int required_cap, const char *prefix) { - return 0; + return cap_kernel_module_request(kmod_name, required_cap, prefix); } static inline int security_kernel_read_file(struct file *file, diff --git a/kernel/module.c b/kernel/module.c index f0411a2..3380d39 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4340,6 +4340,29 @@ struct module *__module_text_address(unsigned long addr) } EXPORT_SYMBOL_GPL(__module_text_address); +/** + * may_autoload_module - Determine whether a module auto-load operation + * is permitted + * @kmod_name: The module name + * @required_cap: if positive, may allow to auto-load the module if this + * capability is set + * @kmod_prefix: The module prefix if any, otherwise NULL + * + * Determine whether a module auto-load operation is allowed or not. + * + * This allows to have more control on automatic module loading, and align it + * with explicit load/unload module operations. The kernel contains several + * modules, some of them are not updated often and may contain bugs and + * vulnerabilities. + * + * Returns 0 if the module request is allowed or -EPERM if not. + */ +int may_autoload_module(char *kmod_name, int required_cap, + const char *kmod_prefix) +{ + return 0; +} + /* Don't grab lock, we're oopsing. */ void print_modules(void) { diff --git a/security/commoncap.c b/security/commoncap.c index 4f8e093..236e573 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1340,6 +1340,31 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, return 0; } +/** + * cap_kernel_module_request - Determine whether a module auto-load is permitted + * @kmod_name: The module name + * @required_cap: if positive, may allow to auto-load the module if this + * capability is set + * @kmod_prefix: the module prefix if any, otherwise NULL + * + * Determine whether a module should be automatically loaded. + * Returns 0 if the module request should be allowed, -EPERM if not. + */ +int cap_kernel_module_request(char *kmod_name, int required_cap, + const char *kmod_prefix) +{ + int ret; + char comm[sizeof(current->comm)]; + + ret = may_autoload_module(kmod_name, required_cap, kmod_prefix); + if (ret < 0) + pr_notice_ratelimited( + "module: automatic module loading of %.64s by \"%s\"[%d] was denied\n", + kmod_name, get_task_comm(comm, current), current->pid); + + return ret; +} + #ifdef CONFIG_SECURITY struct security_hook_list capability_hooks[] __lsm_ro_after_init = { @@ -1361,6 +1386,7 @@ struct security_hook_list capability_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(task_setioprio, cap_task_setioprio), LSM_HOOK_INIT(task_setnice, cap_task_setnice), LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory), + LSM_HOOK_INIT(kernel_module_request, cap_kernel_module_request), }; void __init capability_add_hooks(void)