Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1601491imu; Wed, 12 Dec 2018 00:37:32 -0800 (PST) X-Google-Smtp-Source: AFSGD/WacE/KcPrCE/cspkjjtoq0pAozQqoO+n3XnQPUqYqvOFeXvCWKXyMWPoDPwWoAXuQfhwOP X-Received: by 2002:a62:938f:: with SMTP id r15mr19298837pfk.27.1544603852771; Wed, 12 Dec 2018 00:37:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544603852; cv=none; d=google.com; s=arc-20160816; b=fwsx0AQjvntN1C9TQSw5T0Ty6AHqJuBW6X9Mwt5lTc4M6N6o7OcEMYnCgQ9YP8T/WN dGDgDlhpPx3Jh6DjV69mLQos94xKABZ4b5NxMH1+YALTZPxFPxhSHj0/R0qG4cYGagaV tT0Ve/aRPlSUuhQBmXVpYS5WB0AghJbP6ref6x2dR0cA2LNQxEIRZqY3wk5Z/oWmrN/P M/J2SdnZn1I4Sq6YhvBCLx9eg3+aPn0iKUiYqBVHDHBG8a3f1u9ItvivlberIpsfHq4r F4U8jBVvWLGenGTuFdfg+Qg+pYuXYFwS3VdPctyWRaF1iur4INBkoYZm8rpLt3Vk5cTd 8BaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=M+cUo5o2BsJDfgS+r/NDUUPHJLkP9sIO4OkGtr+ASC8=; b=MijpvhEzQVH9kE5CFOKO5vpHIG5Jq2Dbkphp2CSvXv0QzuN4bf7tiYopzUmRfFAYLF VTJ6cJVoN/M1kECguWeIet29NvXVdCckBGjH8/Y7I2JoHe3UhWVo3tbgvumQUIohXjB2 wGgTXa4grFt90Q10ncstVv29lkhiEi39fuei9uiHMgpL3Y0ORzJl+dxxZQyliOOPtkKX hKE6vqMRQBuSsAfSOqhjTsqCpqsRCKKd4HvBAlEZ/DtMzwrZeMYaPt3tZ2HGsB1gxDRj STA3V3TFXnDIfo0Ch/49kAL2JVxo1BDnlNlyr6jJtQj7XEk5Eecg8/xfJCAlFmXlkRBC qFfw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r22si13307314pgl.537.2018.12.12.00.37.14; Wed, 12 Dec 2018 00:37:32 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726893AbeLLIel (ORCPT + 99 others); Wed, 12 Dec 2018 03:34:41 -0500 Received: from smtp-sh2.infomaniak.ch ([128.65.195.6]:44079 "EHLO smtp-sh2.infomaniak.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726242AbeLLIee (ORCPT ); Wed, 12 Dec 2018 03:34:34 -0500 Received: from smtp7.infomaniak.ch (smtp7.infomaniak.ch [83.166.132.30]) by smtp-sh.infomaniak.ch (8.14.5/8.14.5) with ESMTP id wBC8HkJd022559 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 12 Dec 2018 09:17:46 +0100 Received: from localhost (ns3096276.ip-94-23-54.eu [94.23.54.103]) (authenticated bits=0) by smtp7.infomaniak.ch (8.14.5/8.14.5) with ESMTP id wBC8HkTd061382; Wed, 12 Dec 2018 09:17:46 +0100 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= To: linux-kernel@vger.kernel.org Cc: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Al Viro , James Morris , Jonathan Corbet , Kees Cook , Matthew Garrett , Michael Kerrisk , =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Mimi Zohar , =?UTF-8?q?Philippe=20Tr=C3=A9buchet?= , Shuah Khan , Thibaut Sautereau , Vincent Strubel , Yves-Alexis Perez , kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH v1 3/5] Yama: Enforces noexec mounts or file executability through O_MAYEXEC Date: Wed, 12 Dec 2018 09:17:10 +0100 Message-Id: <20181212081712.32347-4-mic@digikod.net> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181212081712.32347-1-mic@digikod.net> References: <20181212081712.32347-1-mic@digikod.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Antivirus: Dr.Web (R) for Unix mail servers drweb plugin ver.6.0.2.8 X-Antivirus-Code: 0x100000 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Enable to either propagate the mount options from the underlying VFS mount to prevent execution, or to propagate the file execute permission. This may allow a script interpreter to check execution permissions before reading commands from a file. The main goal is to be able to protect the kernel by restricting arbitrary syscalls that an attacker could perform with a crafted binary or certain script languages. It also improves multilevel isolation by reducing the ability of an attacker to use side channels with specific code. These restrictions can natively be enforced for ELF binaries (with the noexec mount option) but require this kernel extension to properly handle scripts (e.g., Python, Perl). Add a new sysctl kernel.yama.open_mayexec_enforce to control this behavior. A following patch adds documentation. Signed-off-by: Mickaël Salaün Reviewed-by: Philippe Trébuchet Reviewed-by: Thibaut Sautereau Cc: Kees Cook Cc: Mickaël Salaün --- security/yama/Kconfig | 3 +- security/yama/yama_lsm.c | 82 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/security/yama/Kconfig b/security/yama/Kconfig index 96b27405558a..9457619fabd5 100644 --- a/security/yama/Kconfig +++ b/security/yama/Kconfig @@ -5,7 +5,8 @@ config SECURITY_YAMA help This selects Yama, which extends DAC support with additional system-wide security settings beyond regular Linux discretionary - access controls. Currently available is ptrace scope restriction. + access controls. Currently available are ptrace scope restriction and + enforcement of the O_MAYEXEC open flag. Like capabilities, this security module stacks with other LSMs. Further information can be found in Documentation/admin-guide/LSM/Yama.rst. diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index ffda91a4a1aa..120664e94ee5 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -1,10 +1,12 @@ /* * Yama Linux Security Module * - * Author: Kees Cook + * Authors: Kees Cook + * Mickaël Salaün * * Copyright (C) 2010 Canonical, Ltd. * Copyright (C) 2011 The Chromium OS Authors. + * Copyright (C) 2018 ANSSI * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as @@ -28,7 +30,14 @@ #define YAMA_SCOPE_CAPABILITY 2 #define YAMA_SCOPE_NO_ATTACH 3 +#define YAMA_OMAYEXEC_ENFORCE_NONE 0 +#define YAMA_OMAYEXEC_ENFORCE_MOUNT (1 << 0) +#define YAMA_OMAYEXEC_ENFORCE_FILE (1 << 1) +#define _YAMA_OMAYEXEC_LAST YAMA_OMAYEXEC_ENFORCE_FILE +#define _YAMA_OMAYEXEC_MASK ((_YAMA_OMAYEXEC_LAST << 1) - 1) + static int ptrace_scope = YAMA_SCOPE_RELATIONAL; +static int open_mayexec_enforce = YAMA_OMAYEXEC_ENFORCE_NONE; /* describe a ptrace relationship for potential exception */ struct ptrace_relation { @@ -423,7 +432,40 @@ int yama_ptrace_traceme(struct task_struct *parent) return rc; } +/** + * yama_inode_permission - check O_MAYEXEC permission before accessing an inode + * @inode: inode structure to check + * @mask: permission mask + * + * Return 0 if access is permitted, -EACCES otherwise. + */ +int yama_inode_permission(struct inode *inode, int mask) +{ + if (!(mask & MAY_OPENEXEC)) + return 0; + /* + * Match regular files and directories to make it easier to + * modify script interpreters. + */ + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) + return 0; + + if ((open_mayexec_enforce & YAMA_OMAYEXEC_ENFORCE_MOUNT) && + !(mask & MAY_EXECMOUNT)) + return -EACCES; + + /* + * May prefer acl_permission_check() instead of generic_permission(), + * to not be bypassable with CAP_DAC_READ_SEARCH. + */ + if (open_mayexec_enforce & YAMA_OMAYEXEC_ENFORCE_FILE) + return generic_permission(inode, MAY_EXEC); + + return 0; +} + static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { + LSM_HOOK_INIT(inode_permission, yama_inode_permission), LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), LSM_HOOK_INIT(task_prctl, yama_task_prctl), @@ -447,6 +489,37 @@ static int yama_dointvec_minmax(struct ctl_table *table, int write, return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos); } +static int yama_dointvec_bitmask_macadmin(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int error; + + if (write) { + struct ctl_table table_copy; + int tmp_mayexec_enforce; + + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + tmp_mayexec_enforce = *((int *)table->data); + table_copy = *table; + /* do not erase open_mayexec_enforce */ + table_copy.data = &tmp_mayexec_enforce; + error = proc_dointvec(&table_copy, write, buffer, lenp, ppos); + if (error) + return error; + if ((tmp_mayexec_enforce | _YAMA_OMAYEXEC_MASK) != + _YAMA_OMAYEXEC_MASK) + return -EINVAL; + *((int *)table->data) = tmp_mayexec_enforce; + } else { + error = proc_dointvec(table, write, buffer, lenp, ppos); + if (error) + return error; + } + return 0; +} + static int zero; static int max_scope = YAMA_SCOPE_NO_ATTACH; @@ -466,6 +539,13 @@ static struct ctl_table yama_sysctl_table[] = { .extra1 = &zero, .extra2 = &max_scope, }, + { + .procname = "open_mayexec_enforce", + .data = &open_mayexec_enforce, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = yama_dointvec_bitmask_macadmin, + }, { } }; static void __init yama_init_sysctl(void) -- 2.20.0.rc2