From patchwork Fri Oct 27 21:45:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 10030675 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 57ACF6032C for ; Fri, 27 Oct 2017 21:45:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F9B128D67 for ; Fri, 27 Oct 2017 21:45:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3442328FE3; Fri, 27 Oct 2017 21:45:11 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D3D328D67 for ; Fri, 27 Oct 2017 21:45:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932378AbdJ0VpJ (ORCPT ); Fri, 27 Oct 2017 17:45:09 -0400 Received: from sonic310-28.consmr.mail.ne1.yahoo.com ([66.163.186.209]:42422 "EHLO sonic310-28.consmr.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932360AbdJ0VpI (ORCPT ); Fri, 27 Oct 2017 17:45:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1509140707; bh=bAj0cgWV/MU9qGYZs0lhlJh9AKqEgbzLjEu0hau4VcY=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From:Subject; b=qWGnwBeKdDQQFyK5XiaRn5zmGNuIRTRqJLnI4Ln09bMGej/pHvJe7rdY5kq2cqMUCYsWUC4/llm/iu2Vv+he57tdWZ7fQrpZNoUuw/jyV/6b6j6jyoNo6f10B4ikVmve0uTLMwB3yE3nvg+FLRea7zvG3c1soYzsejy5Mp7wNvQWrWAkkVPJAaAd8+mLZcUDDvKXjxDFA9T3c2gmf3W/0q7S12n5uTq47MR1zLfUFYLzErvUMty73IvZbHpcG2/9I8XRUitGsmKZwUTCOdKtahcaN5oEuKULcalimDiaw2BqKvz49wLiXWvGqR1LwZ1hsnepGN25ceFso2CKHMV6mQ== X-YMail-OSG: .8uDMWcVM1kF0IvlHPGJwgIEtqD46H73G617DkPWKOA040nnJMVggv5310l3c9t ..Tvgi1cnDDEKihApx4nk6i01PAyhB3a14hs__bvBMDtds9Q9HuarLoVESjaUyjxsksEbgRR.YqJ T15XFBbY8dkrThcbVwJPw8pRKnjBvrz2mzfNt8z0MqGnGZTJcp0IJscTsXaHr_C12m6RNWd1.cbb vqquZoibluKSFpx_kRcBI90Id1BPEQSLjbOED58C6Kx8uIyfS3nr5BC7Uo5z4zjRilcZZgGC9Brz KqlIm3dRh4ZqL1B6RQ.eeYZRq6GwuKEvNyTl7MzU3xNaXzHnXX08r26NtO9DMBaIN_5ElcEBks3l bc5jlVFVq0_6ZB5iyfXjdWFQTZ6QWL1BC._0XXr_PvxYeE.H8Sjt.3Bhm6YuqaieCrTdw3AnEF7z .UaZAQbYftDqqieR5H4ye8lb2nFu_cl9Mq5TDCP16T1W4_9e9i2467zl0TVoZNrtQfIFTQXgk79n GAsGDQgw9MfiEXgbn1gHw Received: from sonic.gate.mail.ne1.yahoo.com by sonic310.consmr.mail.ne1.yahoo.com with HTTP; Fri, 27 Oct 2017 21:45:07 +0000 Received: from [127.0.0.1] by smtp110.mail.ne1.yahoo.com with NNFMP; 27 Oct 2017 21:45:07 -0000 X-Yahoo-Newman-Id: 37744.9194.bm@smtp110.mail.ne1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: .8uDMWcVM1kF0IvlHPGJwgIEtqD46H73G617DkPWKOA040n nJMVggv5310l3c9t..Tvgi1cnDDEKihApx4nk6i01PAyhB3a14hs__bvBMDt ds9Q9HuarLoVESjaUyjxsksEbgRR.YqJT15XFBbY8dkrThcbVwJPw8pRKnjB vrz2mzfNt8z0MqGnGZTJcp0IJscTsXaHr_C12m6RNWd1.cbbvqquZoibluKS Fpx_kRcBI90Id1BPEQSLjbOED58C6Kx8uIyfS3nr5BC7Uo5z4zjRilcZZgGC 9BrzKqlIm3dRh4ZqL1B6RQ.eeYZRq6GwuKEvNyTl7MzU3xNaXzHnXX08r26N tO9DMBaIN_5ElcEBks3lbc5jlVFVq0_6ZB5iyfXjdWFQTZ6QWL1BC._0XXr_ PvxYeE.H8Sjt.3Bhm6YuqaieCrTdw3AnEF7z.UaZAQbYftDqqieR5H4ye8lb 2nFu_cl9Mq5TDCP16T1W4_9e9i2467zl0TVoZNrtQfIFTQXgk79nGAsGDQgw 9MfiEXgbn1gHw X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Subject: [PATCH 1/9] procfs: add smack subdir to attrs To: LSM , James Morris Cc: John Johansen , Tetsuo Handa , Paul Moore , Kees Cook , Stephen Smalley References: <1473402e-a714-7ace-2698-b65d73e3f17e@schaufler-ca.com> From: Casey Schaufler Message-ID: <0fe962c9-e300-6407-58f0-77b084e13ac2@schaufler-ca.com> Date: Fri, 27 Oct 2017 14:45:03 -0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <1473402e-a714-7ace-2698-b65d73e3f17e@schaufler-ca.com> Content-Language: en-US Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Subject: [PATCH 1/9] procfs: add smack subdir to attrs Back in 2007 I made what turned out to be a rather serious mistake in the implementation of the Smack security module. The SELinux module used an interface in /proc to manipulate the security context on processes. Rather than use a similar interface, I used the same interface. The AppArmor team did likewise. Now /proc/.../attr/current will tell you the security "context" of the process, but it will be different depending on the security module you're using. This patch provides a subdirectory in /proc/.../attr for Smack. Smack user space can use the "current" file in this subdirectory and never have to worry about getting SELinux attributes by mistake. Programs that use the old interface will continue to work (or fail, as the case may be) as before. The original implementation is by Kees Cook. Signed-off-by: Casey Schaufler --- Documentation/admin-guide/LSM/index.rst | 13 +++++-- fs/proc/base.c | 63 ++++++++++++++++++++++++++++----- fs/proc/internal.h | 1 + include/linux/security.h | 15 +++++--- security/security.c | 24 ++++++++++--- 5 files changed, 95 insertions(+), 21 deletions(-) diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst index c980dfe9abf1..9842e21afd4a 100644 --- a/Documentation/admin-guide/LSM/index.rst +++ b/Documentation/admin-guide/LSM/index.rst @@ -17,9 +17,8 @@ MAC extensions, other extensions can be built using the LSM to provide specific changes to system operation when these tweaks are not available in the core functionality of Linux itself. -Without a specific LSM built into the kernel, the default LSM will be the -Linux capabilities system. Most LSMs choose to extend the capabilities -system, building their checks on top of the defined capability hooks. +The Linux capabilities modules will always be included. This may be +followed by any number of "minor" modules and at most one "major" module. For more details on capabilities, see ``capabilities(7)`` in the Linux man-pages project. @@ -30,6 +29,14 @@ order in which checks are made. The capability module will always be first, followed by any "minor" modules (e.g. Yama) and then the one "major" module (e.g. SELinux) if there is one configured. +Process attributes associated with "major" security modules should +be accessed and maintained using the special files in ``/proc/.../attr``. +A security module may maintain a module specific subdirectory there, +named after the module. ``/proc/.../attr/smack`` is provided by the Smack +security module and contains all its special files. The files directly +in ``/proc/.../attr`` remain as legacy interfaces for modules that provide +subdirectories. + .. toctree:: :maxdepth: 1 diff --git a/fs/proc/base.c b/fs/proc/base.c index ad3b0762cc3e..a096e90fc12e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -139,9 +139,13 @@ struct pid_entry { #define REG(NAME, MODE, fops) \ NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}) #define ONE(NAME, MODE, show) \ - NOD(NAME, (S_IFREG|(MODE)), \ + NOD(NAME, (S_IFREG|(MODE)), \ NULL, &proc_single_file_operations, \ { .proc_show = show } ) +#define ATTR(LSM, NAME, MODE) \ + NOD(NAME, (S_IFREG|(MODE)), \ + NULL, &proc_pid_attr_operations, \ + { .lsm = LSM }) /* * Count the number of hardlinks for the pid_entry table, excluding the . @@ -2496,7 +2500,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, if (!task) return -ESRCH; - length = security_getprocattr(task, + length = security_getprocattr(task, PROC_I(inode)->op.lsm, (char*)file->f_path.dentry->d_name.name, &p); put_task_struct(task); @@ -2542,7 +2546,8 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, if (length < 0) goto out_free; - length = security_setprocattr(file->f_path.dentry->d_name.name, + length = security_setprocattr(PROC_I(inode)->op.lsm, + file->f_path.dentry->d_name.name, page, count); mutex_unlock(¤t->signal->cred_guard_mutex); out_free: @@ -2559,13 +2564,53 @@ static const struct file_operations proc_pid_attr_operations = { .llseek = generic_file_llseek, }; +#define LSM_DIR_OPS(LSM) \ +static int proc_##LSM##_attr_dir_iterate(struct file *filp, \ + struct dir_context *ctx) \ +{ \ + return proc_pident_readdir(filp, ctx, \ + LSM##_attr_dir_stuff, \ + ARRAY_SIZE(LSM##_attr_dir_stuff)); \ +} \ +\ +static const struct file_operations proc_##LSM##_attr_dir_ops = { \ + .read = generic_read_dir, \ + .iterate = proc_##LSM##_attr_dir_iterate, \ + .llseek = default_llseek, \ +}; \ +\ +static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \ + struct dentry *dentry, unsigned int flags) \ +{ \ + return proc_pident_lookup(dir, dentry, \ + LSM##_attr_dir_stuff, \ + ARRAY_SIZE(LSM##_attr_dir_stuff)); \ +} \ +\ +static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \ + .lookup = proc_##LSM##_attr_dir_lookup, \ + .getattr = pid_getattr, \ + .setattr = proc_setattr, \ +} + +#ifdef CONFIG_SECURITY_SMACK +static const struct pid_entry smack_attr_dir_stuff[] = { + ATTR("smack", "current", 0666), +}; +LSM_DIR_OPS(smack); +#endif + static const struct pid_entry attr_dir_stuff[] = { - REG("current", S_IRUGO|S_IWUGO, proc_pid_attr_operations), - REG("prev", S_IRUGO, proc_pid_attr_operations), - REG("exec", S_IRUGO|S_IWUGO, proc_pid_attr_operations), - REG("fscreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), - REG("keycreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), - REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), + ATTR(NULL, "current", 0666), + ATTR(NULL, "prev", 0444), + ATTR(NULL, "exec", 0666), + ATTR(NULL, "fscreate", 0666), + ATTR(NULL, "keycreate", 0666), + ATTR(NULL, "sockcreate", 0666), +#ifdef CONFIG_SECURITY_SMACK + DIR("smack", 0555, + proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops), +#endif }; static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) diff --git a/fs/proc/internal.h b/fs/proc/internal.h index a34195e92b20..758e32874444 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -58,6 +58,7 @@ union proc_op { int (*proc_show)(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); + const char *lsm; }; struct proc_inode { diff --git a/include/linux/security.h b/include/linux/security.h index ce6265960d6c..46ec92658ad3 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -375,8 +375,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd); int security_sem_semop(struct sem_array *sma, struct sembuf *sops, unsigned nsops, int alter); void security_d_instantiate(struct dentry *dentry, struct inode *inode); -int security_getprocattr(struct task_struct *p, char *name, char **value); -int security_setprocattr(const char *name, void *value, size_t size); +int security_getprocattr(struct task_struct *p, const char *lsm, char *name, + char **value); +int security_setprocattr(const char *lsm, const char *name, void *value, + size_t size); int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_ismaclabel(const char *name); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); @@ -1128,15 +1130,18 @@ static inline int security_sem_semop(struct sem_array *sma, return 0; } -static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode) +static inline void security_d_instantiate(struct dentry *dentry, + struct inode *inode) { } -static inline int security_getprocattr(struct task_struct *p, char *name, char **value) +static inline int security_getprocattr(struct task_struct *p, const char *lsm, + char *name, char **value) { return -EINVAL; } -static inline int security_setprocattr(char *name, void *value, size_t size) +static inline int security_setprocattr(const char *lsm, char *name, + void *value, size_t size) { return -EINVAL; } diff --git a/security/security.c b/security/security.c index 4bf0f571b4ef..49a069bb76da 100644 --- a/security/security.c +++ b/security/security.c @@ -1253,14 +1253,30 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) } EXPORT_SYMBOL(security_d_instantiate); -int security_getprocattr(struct task_struct *p, char *name, char **value) +int security_getprocattr(struct task_struct *p, const char *lsm, char *name, + char **value) { - return call_int_hook(getprocattr, -EINVAL, p, name, value); + struct security_hook_list *hp; + + list_for_each_entry(hp, &security_hook_heads.getprocattr, list) { + if (lsm != NULL && strcmp(lsm, hp->lsm)) + continue; + return hp->hook.getprocattr(p, name, value); + } + return -EINVAL; } -int security_setprocattr(const char *name, void *value, size_t size) +int security_setprocattr(const char *lsm, const char *name, void *value, + size_t size) { - return call_int_hook(setprocattr, -EINVAL, name, value, size); + struct security_hook_list *hp; + + list_for_each_entry(hp, &security_hook_heads.setprocattr, list) { + if (lsm != NULL && strcmp(lsm, hp->lsm)) + continue; + return hp->hook.setprocattr(name, value, size); + } + return -EINVAL; } int security_netlink_send(struct sock *sk, struct sk_buff *skb)