From patchwork Wed Oct 14 12:41:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukasz Pawelczyk X-Patchwork-Id: 7394481 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 863899F1B9 for ; Wed, 14 Oct 2015 12:59:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 65E60206DD for ; Wed, 14 Oct 2015 12:59:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1E5BD206DF for ; Wed, 14 Oct 2015 12:59:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932195AbbJNM7K (ORCPT ); Wed, 14 Oct 2015 08:59:10 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:9689 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753230AbbJNMmb (ORCPT ); Wed, 14 Oct 2015 08:42:31 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NW7003WFNARE900@mailout3.w1.samsung.com>; Wed, 14 Oct 2015 13:42:27 +0100 (BST) X-AuditID: cbfec7f4-f79c56d0000012ee-f3-561e4db28d6e Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id AE.B2.04846.2BD4E165; Wed, 14 Oct 2015 13:42:26 +0100 (BST) Received: from amdc2143.DIGITAL.local ([106.120.53.33]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NW700BB0NAK6E50@eusync2.samsung.com>; Wed, 14 Oct 2015 13:42:26 +0100 (BST) From: Lukasz Pawelczyk To: "David S. Miller" , "Eric W. Biederman" , "Serge E. Hallyn" , Al Viro , Alexey Dobriyan , Andrew Morton , Andy Lutomirski , Calvin Owens , Casey Schaufler , David Howells , Eric Dumazet , Eric Paris , Greg Kroah-Hartman , James Morris , Jann Horn , Jiri Slaby , Joe Perches , John Johansen , Jonathan Corbet , Kees Cook , Lukasz Pawelczyk , Mauro Carvalho Chehab , NeilBrown , Paul Moore , Serge Hallyn , Stephen Smalley , Tejun Heo , Tetsuo Handa , containers@lists.linuxfoundation.org, linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@tycho.nsa.gov Cc: Lukasz Pawelczyk Subject: [PATCH v4 02/11] lsm: /proc/$PID/attr/label_map file and getprocattr_seq hook Date: Wed, 14 Oct 2015 14:41:56 +0200 Message-id: <1444826525-9758-3-git-send-email-l.pawelczyk@samsung.com> X-Mailer: git-send-email 2.4.3 In-reply-to: <1444826525-9758-1-git-send-email-l.pawelczyk@samsung.com> References: <1444826525-9758-1-git-send-email-l.pawelczyk@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrPIsWRmVeSWpSXmKPExsVy+t/xK7qbfOXCDF7P17OY3uhlMWf9GjaL 9QvkLe5t+8VmcfrfCnaLJwfaGS3mnG9hsXjX9JvF4v+2FnaLp8cesVt0PjzLbNG8eD2bxf/X OhZ9j4MsTjx7ymox+/5jFosTX1rZLKZs+MBkcaY71+LMpIVMFgvblrBY7Nl7ksXi8q45bBYf eh6xWZzftZbVYvWzCou98xtYLG5Pms5iMbvlHavF4d2LmS0mPznEYnGu8TmLxfkL59gtfi0/ ymhx/u9xVgdlj1kNvWwesxsusnhsWXmTyWNi8zt2j52z7rJ7LNhU6nFtd6THzrWrmDw2repk 8zgx4zeLx/65a9g9fv+YzOixuG8yq8fHp7eAOvuB6s9+jQqQieKySUnNySxLLdK3S+DKWLBz BUvBHueKyYeeszYwzjbvYuTkkBAwkVh25DM7hC0mceHeerYuRi4OIYGljBITXzyFchqZJFb3 nAGrYhMwkPh+YS8zSEJEYAKXRMuEK2wgCWYBdYmls5tZQGxhgQiJ/78WgNksAqoSNw6sBqvh FXCTWHVgK9Q6OYlz678A1XBwcAq4S2xptQUJCwGV7J9wl2UCI+8CRoZVjKKppckFxUnpuYZ6 xYm5xaV56XrJ+bmbGCHR/GUH4+JjVocYBTgYlXh4M1bLhgmxJpYVV+YeYpTgYFYS4f1jIBcm xJuSWFmVWpQfX1Sak1p8iFGag0VJnHfurvchQgLpiSWp2ampBalFMFkmDk6pBsaA+dr37gf7 Pwg8Z5dZICqYYh0TKzRp/6/SSy5WV62exeyJcd2Vlq7aWjRDZ+eZFUJxh7oE198tz/L5lKh5 1Xty/eW9vdMPJLQ4Fuy85y45fQ4Xu/lhfv9nz0/MZHGeHxiy2KZ2mdPVbye5DxoWqvSYfmqz dNaa9uV4bZ7pQ92AMJ6riYYN7EosxRmJhlrMRcWJAHrAKFTiAgAA Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This commit adds a new proc attribute, label_map that is required by an upcoming Smack namespace. In general it can be used to hold a map of labels, e.g. to be used in namespaces. Due to the nature of this file, the standard getprocattr hook might not be enough to handle it. The map's output can in principle be greater than page size to which the aforementioned hook is limited. To handle this properly a getprocattr_seq LSM hook has been added that makes it possible to handle any chosen proc attr by seq operations. See the documentation in the patch below for the details about how to use the hook. Signed-off-by: Lukasz Pawelczyk Acked-by: Serge Hallyn Acked-by: Casey Schaufler --- fs/proc/base.c | 81 +++++++++++++++++++++++++++++++++++++++++++---- include/linux/lsm_hooks.h | 15 +++++++++ include/linux/security.h | 9 ++++++ security/security.c | 8 +++++ 4 files changed, 107 insertions(+), 6 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index b25eee4..9ec88b8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2327,20 +2327,77 @@ out: } #ifdef CONFIG_SECURITY +static int proc_pid_attr_open(struct inode *inode, struct file *file) +{ + const char *name = file->f_path.dentry->d_name.name; + const struct seq_operations *ops; + struct task_struct *task; + struct seq_file *seq; + int ret; + + file->private_data = NULL; + + task = get_proc_task(inode); + if (!task) + return -ESRCH; + + /* don't use seq_ops if they are not provided by LSM */ + ret = security_getprocattr_seq(task, name, &ops); + if (ret == -EOPNOTSUPP) { + ret = 0; + goto put_task; + } + if (ret) + goto put_task; + + ret = seq_open(file, ops); + if (ret) + goto put_task; + + seq = file->private_data; + seq->private = task; + + return 0; + +put_task: + put_task_struct(task); + return ret; +} + +static int proc_pid_attr_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + struct task_struct *task; + + /* don't use seq_ops if they were not provided by LSM */ + if (file->private_data == NULL) + return 0; + + seq = file->private_data; + task = seq->private; + put_task_struct(task); + + return seq_release(inode, file); +} + static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file_inode(file); + struct inode *inode = file_inode(file); + const char *name = file->f_path.dentry->d_name.name; char *p = NULL; ssize_t length; - struct task_struct *task = get_proc_task(inode); + struct task_struct *task; + /* use seq_ops if they were provided by LSM */ + if (file->private_data) + return seq_read(file, buf, count, ppos); + + task = get_proc_task(inode); if (!task) return -ESRCH; - length = security_getprocattr(task, - (char*)file->f_path.dentry->d_name.name, - &p); + length = security_getprocattr(task, (char *)name, &p); put_task_struct(task); if (length > 0) length = simple_read_from_buffer(buf, count, ppos, p, length); @@ -2348,6 +2405,15 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, return length; } +static loff_t proc_pid_attr_lseek(struct file *file, loff_t offset, int whence) +{ + /* use seq_ops if they were provided by LSM */ + if (file->private_data) + return seq_lseek(file, offset, whence); + + return generic_file_llseek(file, offset, whence); +} + static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { @@ -2394,9 +2460,11 @@ out_no_task: } static const struct file_operations proc_pid_attr_operations = { + .open = proc_pid_attr_open, + .release = proc_pid_attr_release, .read = proc_pid_attr_read, + .llseek = proc_pid_attr_lseek, .write = proc_pid_attr_write, - .llseek = generic_file_llseek, }; static const struct pid_entry attr_dir_stuff[] = { @@ -2406,6 +2474,7 @@ static const struct pid_entry attr_dir_stuff[] = { 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), + REG("label_map", S_IRUGO|S_IWUGO, proc_pid_attr_operations), }; static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 18c9160..7049db0 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1208,6 +1208,18 @@ * @name full extended attribute name to check against * LSM as a MAC label. * + * @getprocattr_seq: + * An alternative to the getprocattr, that makes it possible for an attr + * file to be handled by seq operations. If this function returns valid + * @ops for a specific @name, those operations will be used and + * getprocattr will not be called. + * A proper task for the file is then passed in seq_file->private. + * @p a task associated with the proc file. + * @name name of the attr file under /proc/$PID/attr/ to be handled. + * @ops (out) seq_operations to be used for @name. + * Return 0 if @name is to be handled by seq, EOPNOTSUPP if getprocattr() + * should be used. Other errors will be passed to user-space. + * * @secid_to_secctx: * Convert secid to security context. If secdata is NULL the length of * the result will be returned in seclen, but no secdata will be returned. @@ -1525,6 +1537,8 @@ union security_list_options { void (*d_instantiate)(struct dentry *dentry, struct inode *inode); + int (*getprocattr_seq)(struct task_struct *p, const char *name, + const struct seq_operations **ops); int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); @@ -1774,6 +1788,7 @@ struct security_hook_heads { struct list_head sem_semop; struct list_head netlink_send; struct list_head d_instantiate; + struct list_head getprocattr_seq; struct list_head getprocattr; struct list_head setprocattr; struct list_head ismaclabel; diff --git a/include/linux/security.h b/include/linux/security.h index 91ffba2..dddea2f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -345,6 +345,8 @@ 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_seq(struct task_struct *p, const char *name, + const struct seq_operations **ops); int security_getprocattr(struct task_struct *p, char *name, char **value); int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); int security_netlink_send(struct sock *sk, struct sk_buff *skb); @@ -1057,6 +1059,13 @@ static inline int security_sem_semop(struct sem_array *sma, static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode) { } +static inline int security_getprocattr_seq(struct task_struct *p, + const char *name, + const struct seq_operations **ops) +{ + return -EOPNOTSUPP; +} + static inline int security_getprocattr(struct task_struct *p, char *name, char **value) { return -EINVAL; diff --git a/security/security.c b/security/security.c index e571127..da2bcd4 100644 --- a/security/security.c +++ b/security/security.c @@ -1121,6 +1121,12 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) } EXPORT_SYMBOL(security_d_instantiate); +int security_getprocattr_seq(struct task_struct *p, const char *name, + const struct seq_operations **ops) +{ + return call_int_hook(getprocattr_seq, -EOPNOTSUPP, p, name, ops); +} + int security_getprocattr(struct task_struct *p, char *name, char **value) { return call_int_hook(getprocattr, -EINVAL, p, name, value); @@ -1774,6 +1780,8 @@ struct security_hook_heads security_hook_heads = { .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send), .d_instantiate = LIST_HEAD_INIT(security_hook_heads.d_instantiate), + .getprocattr_seq = + LIST_HEAD_INIT(security_hook_heads.getprocattr_seq), .getprocattr = LIST_HEAD_INIT(security_hook_heads.getprocattr), .setprocattr = LIST_HEAD_INIT(security_hook_heads.setprocattr), .ismaclabel = LIST_HEAD_INIT(security_hook_heads.ismaclabel),