blob: e951d8bee98a98de5a53b4a33ecca068d4e1c5ed [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/security.h>
33#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore3ac7b8d2013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma60063492011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
64#include <linux/netlink.h>
65#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Amir Samuelov6a22e462014-05-26 11:44:06 +030086#include <linux/pft.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88#include "avc.h"
89#include "objsec.h"
90#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050091#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040092#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080093#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050094#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020095#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100096#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
David P. Quigley11689d42009-01-16 09:22:03 -050098#define NUM_SEL_MNT_OPTS 5
Eric Parisc9180a52007-11-30 13:00:35 -050099
James Morris20510f22007-10-16 23:31:32 -0700100extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Paul Moored621d352008-01-29 08:43:36 -0500102/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000103static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400106int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
108static int __init enforcing_setup(char *str)
109{
Eric Parisf5269712008-05-14 11:27:45 -0400110 unsigned long enforcing;
111 if (!strict_strtoul(str, 0, &enforcing))
112 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 return 1;
114}
115__setup("enforcing=", enforcing_setup);
116#endif
117
118#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
119int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
120
121static int __init selinux_enabled_setup(char *str)
122{
Eric Parisf5269712008-05-14 11:27:45 -0400123 unsigned long enabled;
124 if (!strict_strtoul(str, 0, &enabled))
125 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return 1;
127}
128__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400129#else
130int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131#endif
132
Christoph Lametere18b8902006-12-06 20:33:20 -0800133static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800134
Paul Moored621d352008-01-29 08:43:36 -0500135/**
136 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
137 *
138 * Description:
139 * This function checks the SECMARK reference counter to see if any SECMARK
140 * targets are currently configured, if the reference counter is greater than
141 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
142 * enabled, false (0) if SECMARK is disabled.
143 *
144 */
145static int selinux_secmark_enabled(void)
146{
147 return (atomic_read(&selinux_secmark_refcount) > 0);
148}
149
David Howellsd84f4f92008-11-14 10:39:23 +1100150/*
151 * initialise the security for the init task
152 */
153static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
David Howells3b11a1d2008-11-14 10:39:26 +1100155 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 struct task_security_struct *tsec;
157
James Morris89d155e2005-10-30 14:59:21 -0800158 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100160 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
David Howellsd84f4f92008-11-14 10:39:23 +1100162 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100163 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164}
165
David Howells275bb412008-11-14 10:39:19 +1100166/*
David Howells88e67f32008-11-14 10:39:21 +1100167 * get the security ID of a set of credentials
168 */
169static inline u32 cred_sid(const struct cred *cred)
170{
171 const struct task_security_struct *tsec;
172
173 tsec = cred->security;
174 return tsec->sid;
175}
176
177/*
David Howells3b11a1d2008-11-14 10:39:26 +1100178 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100179 */
180static inline u32 task_sid(const struct task_struct *task)
181{
David Howells275bb412008-11-14 10:39:19 +1100182 u32 sid;
183
184 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100185 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100186 rcu_read_unlock();
187 return sid;
188}
189
190/*
David Howells3b11a1d2008-11-14 10:39:26 +1100191 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100192 */
193static inline u32 current_sid(void)
194{
Paul Moore5fb49872010-04-22 14:46:19 -0400195 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100196
197 return tsec->sid;
198}
199
David Howells88e67f32008-11-14 10:39:21 +1100200/* Allocate and free functions for each kind of security blob. */
201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202static int inode_alloc_security(struct inode *inode)
203{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100205 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Josef Bacika02fe132008-04-04 09:35:05 +1100207 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 if (!isec)
209 return -ENOMEM;
210
Eric Paris23970742006-09-25 23:32:01 -0700211 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 isec->inode = inode;
214 isec->sid = SECINITSID_UNLABELED;
215 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100216 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 inode->i_security = isec;
218
219 return 0;
220}
221
222static void inode_free_security(struct inode *inode)
223{
224 struct inode_security_struct *isec = inode->i_security;
225 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 spin_lock(&sbsec->isec_lock);
228 if (!list_empty(&isec->list))
229 list_del_init(&isec->list);
230 spin_unlock(&sbsec->isec_lock);
231
232 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800233 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
236static int file_alloc_security(struct file *file)
237{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100239 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800241 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 if (!fsec)
243 return -ENOMEM;
244
David Howells275bb412008-11-14 10:39:19 +1100245 fsec->sid = sid;
246 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 file->f_security = fsec;
248
249 return 0;
250}
251
252static void file_free_security(struct file *file)
253{
254 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 file->f_security = NULL;
256 kfree(fsec);
257}
258
259static int superblock_alloc_security(struct super_block *sb)
260{
261 struct superblock_security_struct *sbsec;
262
James Morris89d155e2005-10-30 14:59:21 -0800263 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 if (!sbsec)
265 return -ENOMEM;
266
Eric Parisbc7e9822006-09-25 23:32:02 -0700267 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 INIT_LIST_HEAD(&sbsec->isec_head);
269 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 sbsec->sb = sb;
271 sbsec->sid = SECINITSID_UNLABELED;
272 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700273 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 sb->s_security = sbsec;
275
276 return 0;
277}
278
279static void superblock_free_security(struct super_block *sb)
280{
281 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 sb->s_security = NULL;
283 kfree(sbsec);
284}
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286/* The file system's label must be initialized prior to use. */
287
Stephen Hemminger634a5392010-03-04 21:59:03 -0800288static const char *labeling_behaviors[6] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 "uses xattr",
290 "uses transition SIDs",
291 "uses task SIDs",
292 "uses genfs_contexts",
293 "not configured for labeling",
294 "uses mountpoint labeling",
295};
296
297static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
298
299static inline int inode_doinit(struct inode *inode)
300{
301 return inode_doinit_with_dentry(inode, NULL);
302}
303
304enum {
Eric Paris31e87932007-09-19 17:19:12 -0400305 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 Opt_context = 1,
307 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500308 Opt_defcontext = 3,
309 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500310 Opt_labelsupport = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311};
312
Steven Whitehousea447c092008-10-13 10:46:57 +0100313static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400314 {Opt_context, CONTEXT_STR "%s"},
315 {Opt_fscontext, FSCONTEXT_STR "%s"},
316 {Opt_defcontext, DEFCONTEXT_STR "%s"},
317 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500318 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400319 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320};
321
322#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
323
Eric Parisc312feb2006-07-10 04:43:53 -0700324static int may_context_mount_sb_relabel(u32 sid,
325 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100326 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700327{
David Howells275bb412008-11-14 10:39:19 +1100328 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700329 int rc;
330
331 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
332 FILESYSTEM__RELABELFROM, NULL);
333 if (rc)
334 return rc;
335
336 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
337 FILESYSTEM__RELABELTO, NULL);
338 return rc;
339}
340
Eric Paris08089252006-07-10 04:43:55 -0700341static int may_context_mount_inode_relabel(u32 sid,
342 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100343 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700344{
David Howells275bb412008-11-14 10:39:19 +1100345 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700346 int rc;
347 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
348 FILESYSTEM__RELABELFROM, NULL);
349 if (rc)
350 return rc;
351
352 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
353 FILESYSTEM__ASSOCIATE, NULL);
354 return rc;
355}
356
Eric Parisc9180a52007-11-30 13:00:35 -0500357static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
359 struct superblock_security_struct *sbsec = sb->s_security;
360 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500361 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 int rc = 0;
363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
365 /* Make sure that the xattr handler exists and that no
366 error other than -ENODATA is returned by getxattr on
367 the root directory. -ENODATA is ok, as this may be
368 the first boot of the SELinux kernel before we have
369 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500370 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
372 "xattr support\n", sb->s_id, sb->s_type->name);
373 rc = -EOPNOTSUPP;
374 goto out;
375 }
Eric Parisc9180a52007-11-30 13:00:35 -0500376 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (rc < 0 && rc != -ENODATA) {
378 if (rc == -EOPNOTSUPP)
379 printk(KERN_WARNING "SELinux: (dev %s, type "
380 "%s) has no security xattr handler\n",
381 sb->s_id, sb->s_type->name);
382 else
383 printk(KERN_WARNING "SELinux: (dev %s, type "
384 "%s) getxattr errno %d\n", sb->s_id,
385 sb->s_type->name, -rc);
386 goto out;
387 }
388 }
389
David P. Quigley11689d42009-01-16 09:22:03 -0500390 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Eric Parisc9180a52007-11-30 13:00:35 -0500392 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500393 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500395 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500396 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 sb->s_id, sb->s_type->name,
398 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
David P. Quigley11689d42009-01-16 09:22:03 -0500400 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
401 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
402 sbsec->behavior == SECURITY_FS_USE_NONE ||
403 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
404 sbsec->flags &= ~SE_SBLABELSUPP;
405
Mark Salyzyn2c088052015-01-07 09:27:15 -0800406 /* Special handling. Is genfs but also has in-core setxattr handler*/
407 if (!strcmp(sb->s_type->name, "sysfs") ||
408 !strcmp(sb->s_type->name, "pstore") ||
409 !strcmp(sb->s_type->name, "debugfs") ||
410 !strcmp(sb->s_type->name, "rootfs"))
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400411 sbsec->flags |= SE_SBLABELSUPP;
412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500414 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 /* Initialize any other inodes associated with the superblock, e.g.
417 inodes created prior to initial policy load or inodes created
418 during get_sb by a pseudo filesystem that directly
419 populates itself. */
420 spin_lock(&sbsec->isec_lock);
421next_inode:
422 if (!list_empty(&sbsec->isec_head)) {
423 struct inode_security_struct *isec =
424 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500425 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 struct inode *inode = isec->inode;
427 spin_unlock(&sbsec->isec_lock);
428 inode = igrab(inode);
429 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500430 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 inode_doinit(inode);
432 iput(inode);
433 }
434 spin_lock(&sbsec->isec_lock);
435 list_del_init(&isec->list);
436 goto next_inode;
437 }
438 spin_unlock(&sbsec->isec_lock);
439out:
Eric Parisc9180a52007-11-30 13:00:35 -0500440 return rc;
441}
442
443/*
444 * This function should allow an FS to ask what it's mount security
445 * options were so it can use those later for submounts, displaying
446 * mount options, or whatever.
447 */
448static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500449 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500450{
451 int rc = 0, i;
452 struct superblock_security_struct *sbsec = sb->s_security;
453 char *context = NULL;
454 u32 len;
455 char tmp;
456
Eric Parise0007522008-03-05 10:31:54 -0500457 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500458
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500459 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500460 return -EINVAL;
461
462 if (!ss_initialized)
463 return -EINVAL;
464
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500465 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500466 /* count the number of mount options for this sb */
467 for (i = 0; i < 8; i++) {
468 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500469 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500470 tmp >>= 1;
471 }
David P. Quigley11689d42009-01-16 09:22:03 -0500472 /* Check if the Label support flag is set */
473 if (sbsec->flags & SE_SBLABELSUPP)
474 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500475
Eric Parise0007522008-03-05 10:31:54 -0500476 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
477 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500478 rc = -ENOMEM;
479 goto out_free;
480 }
481
Eric Parise0007522008-03-05 10:31:54 -0500482 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
483 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500484 rc = -ENOMEM;
485 goto out_free;
486 }
487
488 i = 0;
489 if (sbsec->flags & FSCONTEXT_MNT) {
490 rc = security_sid_to_context(sbsec->sid, &context, &len);
491 if (rc)
492 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500493 opts->mnt_opts[i] = context;
494 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500495 }
496 if (sbsec->flags & CONTEXT_MNT) {
497 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
498 if (rc)
499 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500500 opts->mnt_opts[i] = context;
501 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500502 }
503 if (sbsec->flags & DEFCONTEXT_MNT) {
504 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
505 if (rc)
506 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500507 opts->mnt_opts[i] = context;
508 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500509 }
510 if (sbsec->flags & ROOTCONTEXT_MNT) {
511 struct inode *root = sbsec->sb->s_root->d_inode;
512 struct inode_security_struct *isec = root->i_security;
513
514 rc = security_sid_to_context(isec->sid, &context, &len);
515 if (rc)
516 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500517 opts->mnt_opts[i] = context;
518 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500519 }
David P. Quigley11689d42009-01-16 09:22:03 -0500520 if (sbsec->flags & SE_SBLABELSUPP) {
521 opts->mnt_opts[i] = NULL;
522 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
523 }
Eric Parisc9180a52007-11-30 13:00:35 -0500524
Eric Parise0007522008-03-05 10:31:54 -0500525 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500526
527 return 0;
528
529out_free:
Eric Parise0007522008-03-05 10:31:54 -0500530 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500531 return rc;
532}
533
534static int bad_option(struct superblock_security_struct *sbsec, char flag,
535 u32 old_sid, u32 new_sid)
536{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500537 char mnt_flags = sbsec->flags & SE_MNTMASK;
538
Eric Parisc9180a52007-11-30 13:00:35 -0500539 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500540 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500541 if (!(sbsec->flags & flag) ||
542 (old_sid != new_sid))
543 return 1;
544
545 /* check if we were passed the same options twice,
546 * aka someone passed context=a,context=b
547 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500548 if (!(sbsec->flags & SE_SBINITIALIZED))
549 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500550 return 1;
551 return 0;
552}
Eric Parise0007522008-03-05 10:31:54 -0500553
Eric Parisc9180a52007-11-30 13:00:35 -0500554/*
555 * Allow filesystems with binary mount data to explicitly set mount point
556 * labeling information.
557 */
Eric Parise0007522008-03-05 10:31:54 -0500558static int selinux_set_mnt_opts(struct super_block *sb,
559 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500560{
David Howells275bb412008-11-14 10:39:19 +1100561 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500562 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500563 struct superblock_security_struct *sbsec = sb->s_security;
564 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000565 struct inode *inode = sbsec->sb->s_root->d_inode;
566 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500567 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
568 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500569 char **mount_options = opts->mnt_opts;
570 int *flags = opts->mnt_opts_flags;
571 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500572
573 mutex_lock(&sbsec->lock);
574
575 if (!ss_initialized) {
576 if (!num_opts) {
577 /* Defer initialization until selinux_complete_init,
578 after the initial policy is loaded and the security
579 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500580 goto out;
581 }
582 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400583 printk(KERN_WARNING "SELinux: Unable to set superblock options "
584 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500585 goto out;
586 }
587
588 /*
Eric Parise0007522008-03-05 10:31:54 -0500589 * Binary mount data FS will come through this function twice. Once
590 * from an explicit call and once from the generic calls from the vfs.
591 * Since the generic VFS calls will not contain any security mount data
592 * we need to skip the double mount verification.
593 *
594 * This does open a hole in which we will not notice if the first
595 * mount using this sb set explict options and a second mount using
596 * this sb does not set any security options. (The first options
597 * will be used for both mounts)
598 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500599 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500600 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400601 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500602
603 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500604 * parse the mount options, check if they are valid sids.
605 * also check if someone is trying to mount the same sb more
606 * than once with different security options.
607 */
608 for (i = 0; i < num_opts; i++) {
609 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500610
611 if (flags[i] == SE_SBLABELSUPP)
612 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500613 rc = security_context_to_sid(mount_options[i],
614 strlen(mount_options[i]), &sid);
615 if (rc) {
616 printk(KERN_WARNING "SELinux: security_context_to_sid"
617 "(%s) failed for (dev %s, type %s) errno=%d\n",
618 mount_options[i], sb->s_id, name, rc);
619 goto out;
620 }
621 switch (flags[i]) {
622 case FSCONTEXT_MNT:
623 fscontext_sid = sid;
624
625 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
626 fscontext_sid))
627 goto out_double_mount;
628
629 sbsec->flags |= FSCONTEXT_MNT;
630 break;
631 case CONTEXT_MNT:
632 context_sid = sid;
633
634 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
635 context_sid))
636 goto out_double_mount;
637
638 sbsec->flags |= CONTEXT_MNT;
639 break;
640 case ROOTCONTEXT_MNT:
641 rootcontext_sid = sid;
642
643 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
644 rootcontext_sid))
645 goto out_double_mount;
646
647 sbsec->flags |= ROOTCONTEXT_MNT;
648
649 break;
650 case DEFCONTEXT_MNT:
651 defcontext_sid = sid;
652
653 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
654 defcontext_sid))
655 goto out_double_mount;
656
657 sbsec->flags |= DEFCONTEXT_MNT;
658
659 break;
660 default:
661 rc = -EINVAL;
662 goto out;
663 }
664 }
665
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500666 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500667 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500668 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500669 goto out_double_mount;
670 rc = 0;
671 goto out;
672 }
673
James Morris089be432008-07-15 18:32:49 +1000674 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400675 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
676
Stephen Smalley043ab942015-05-20 12:33:16 -0400677 if (!strcmp(sb->s_type->name, "debugfs") ||
678 !strcmp(sb->s_type->name, "sysfs") ||
679 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400680 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500681
682 /* Determine the labeling behavior to use for this filesystem type. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500683 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500684 if (rc) {
685 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000686 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500687 goto out;
688 }
689
690 /* sets the context of the superblock for the fs being mounted. */
691 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100692 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500693 if (rc)
694 goto out;
695
696 sbsec->sid = fscontext_sid;
697 }
698
699 /*
700 * Switch to using mount point labeling behavior.
701 * sets the label used on all file below the mountpoint, and will set
702 * the superblock context if not already set.
703 */
704 if (context_sid) {
705 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100706 rc = may_context_mount_sb_relabel(context_sid, sbsec,
707 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500708 if (rc)
709 goto out;
710 sbsec->sid = context_sid;
711 } else {
David Howells275bb412008-11-14 10:39:19 +1100712 rc = may_context_mount_inode_relabel(context_sid, sbsec,
713 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500714 if (rc)
715 goto out;
716 }
717 if (!rootcontext_sid)
718 rootcontext_sid = context_sid;
719
720 sbsec->mntpoint_sid = context_sid;
721 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
722 }
723
724 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100725 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
726 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500727 if (rc)
728 goto out;
729
730 root_isec->sid = rootcontext_sid;
731 root_isec->initialized = 1;
732 }
733
734 if (defcontext_sid) {
735 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
736 rc = -EINVAL;
737 printk(KERN_WARNING "SELinux: defcontext option is "
738 "invalid for this filesystem type\n");
739 goto out;
740 }
741
742 if (defcontext_sid != sbsec->def_sid) {
743 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100744 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500745 if (rc)
746 goto out;
747 }
748
749 sbsec->def_sid = defcontext_sid;
750 }
751
752 rc = sb_finish_set_opts(sb);
753out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700754 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500756out_double_mount:
757 rc = -EINVAL;
758 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
759 "security settings for (dev %s, type %s)\n", sb->s_id, name);
760 goto out;
761}
762
763static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
764 struct super_block *newsb)
765{
766 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
767 struct superblock_security_struct *newsbsec = newsb->s_security;
768
769 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
770 int set_context = (oldsbsec->flags & CONTEXT_MNT);
771 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
772
Eric Paris0f5e6422008-04-21 16:24:11 -0400773 /*
774 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400775 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400776 */
Al Viroe8c26252010-03-23 06:36:54 -0400777 if (!ss_initialized)
Eric Paris0f5e6422008-04-21 16:24:11 -0400778 return;
Eric Parisc9180a52007-11-30 13:00:35 -0500779
Eric Parisc9180a52007-11-30 13:00:35 -0500780 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500781 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500782
Eric Paris5a552612008-04-09 14:08:35 -0400783 /* if fs is reusing a sb, just let its options stand... */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500784 if (newsbsec->flags & SE_SBINITIALIZED)
Eric Paris5a552612008-04-09 14:08:35 -0400785 return;
786
Eric Parisc9180a52007-11-30 13:00:35 -0500787 mutex_lock(&newsbsec->lock);
788
789 newsbsec->flags = oldsbsec->flags;
790
791 newsbsec->sid = oldsbsec->sid;
792 newsbsec->def_sid = oldsbsec->def_sid;
793 newsbsec->behavior = oldsbsec->behavior;
794
795 if (set_context) {
796 u32 sid = oldsbsec->mntpoint_sid;
797
798 if (!set_fscontext)
799 newsbsec->sid = sid;
800 if (!set_rootcontext) {
801 struct inode *newinode = newsb->s_root->d_inode;
802 struct inode_security_struct *newisec = newinode->i_security;
803 newisec->sid = sid;
804 }
805 newsbsec->mntpoint_sid = sid;
806 }
807 if (set_rootcontext) {
808 const struct inode *oldinode = oldsb->s_root->d_inode;
809 const struct inode_security_struct *oldisec = oldinode->i_security;
810 struct inode *newinode = newsb->s_root->d_inode;
811 struct inode_security_struct *newisec = newinode->i_security;
812
813 newisec->sid = oldisec->sid;
814 }
815
816 sb_finish_set_opts(newsb);
817 mutex_unlock(&newsbsec->lock);
818}
819
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200820static int selinux_parse_opts_str(char *options,
821 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500822{
Eric Parise0007522008-03-05 10:31:54 -0500823 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500824 char *context = NULL, *defcontext = NULL;
825 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500826 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500827
Eric Parise0007522008-03-05 10:31:54 -0500828 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500829
830 /* Standard string-based options. */
831 while ((p = strsep(&options, "|")) != NULL) {
832 int token;
833 substring_t args[MAX_OPT_ARGS];
834
835 if (!*p)
836 continue;
837
838 token = match_token(p, tokens, args);
839
840 switch (token) {
841 case Opt_context:
842 if (context || defcontext) {
843 rc = -EINVAL;
844 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
845 goto out_err;
846 }
847 context = match_strdup(&args[0]);
848 if (!context) {
849 rc = -ENOMEM;
850 goto out_err;
851 }
852 break;
853
854 case Opt_fscontext:
855 if (fscontext) {
856 rc = -EINVAL;
857 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
858 goto out_err;
859 }
860 fscontext = match_strdup(&args[0]);
861 if (!fscontext) {
862 rc = -ENOMEM;
863 goto out_err;
864 }
865 break;
866
867 case Opt_rootcontext:
868 if (rootcontext) {
869 rc = -EINVAL;
870 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
871 goto out_err;
872 }
873 rootcontext = match_strdup(&args[0]);
874 if (!rootcontext) {
875 rc = -ENOMEM;
876 goto out_err;
877 }
878 break;
879
880 case Opt_defcontext:
881 if (context || defcontext) {
882 rc = -EINVAL;
883 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
884 goto out_err;
885 }
886 defcontext = match_strdup(&args[0]);
887 if (!defcontext) {
888 rc = -ENOMEM;
889 goto out_err;
890 }
891 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500892 case Opt_labelsupport:
893 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500894 default:
895 rc = -EINVAL;
896 printk(KERN_WARNING "SELinux: unknown mount option\n");
897 goto out_err;
898
899 }
900 }
901
Eric Parise0007522008-03-05 10:31:54 -0500902 rc = -ENOMEM;
903 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
904 if (!opts->mnt_opts)
905 goto out_err;
906
907 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
908 if (!opts->mnt_opts_flags) {
909 kfree(opts->mnt_opts);
910 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500911 }
912
Eric Parise0007522008-03-05 10:31:54 -0500913 if (fscontext) {
914 opts->mnt_opts[num_mnt_opts] = fscontext;
915 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
916 }
917 if (context) {
918 opts->mnt_opts[num_mnt_opts] = context;
919 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
920 }
921 if (rootcontext) {
922 opts->mnt_opts[num_mnt_opts] = rootcontext;
923 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
924 }
925 if (defcontext) {
926 opts->mnt_opts[num_mnt_opts] = defcontext;
927 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
928 }
929
930 opts->num_mnt_opts = num_mnt_opts;
931 return 0;
932
Eric Parisc9180a52007-11-30 13:00:35 -0500933out_err:
934 kfree(context);
935 kfree(defcontext);
936 kfree(fscontext);
937 kfree(rootcontext);
938 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939}
Eric Parise0007522008-03-05 10:31:54 -0500940/*
941 * string mount options parsing and call set the sbsec
942 */
943static int superblock_doinit(struct super_block *sb, void *data)
944{
945 int rc = 0;
946 char *options = data;
947 struct security_mnt_opts opts;
948
949 security_init_mnt_opts(&opts);
950
951 if (!data)
952 goto out;
953
954 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
955
956 rc = selinux_parse_opts_str(options, &opts);
957 if (rc)
958 goto out_err;
959
960out:
961 rc = selinux_set_mnt_opts(sb, &opts);
962
963out_err:
964 security_free_mnt_opts(&opts);
965 return rc;
966}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Adrian Bunk3583a712008-07-22 20:21:23 +0300968static void selinux_write_opts(struct seq_file *m,
969 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000970{
971 int i;
972 char *prefix;
973
974 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -0500975 char *has_comma;
976
977 if (opts->mnt_opts[i])
978 has_comma = strchr(opts->mnt_opts[i], ',');
979 else
980 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +1000981
982 switch (opts->mnt_opts_flags[i]) {
983 case CONTEXT_MNT:
984 prefix = CONTEXT_STR;
985 break;
986 case FSCONTEXT_MNT:
987 prefix = FSCONTEXT_STR;
988 break;
989 case ROOTCONTEXT_MNT:
990 prefix = ROOTCONTEXT_STR;
991 break;
992 case DEFCONTEXT_MNT:
993 prefix = DEFCONTEXT_STR;
994 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500995 case SE_SBLABELSUPP:
996 seq_putc(m, ',');
997 seq_puts(m, LABELSUPP_STR);
998 continue;
Eric Paris2069f452008-07-04 09:47:13 +1000999 default:
1000 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001001 return;
Eric Paris2069f452008-07-04 09:47:13 +10001002 };
1003 /* we need a comma before each option */
1004 seq_putc(m, ',');
1005 seq_puts(m, prefix);
1006 if (has_comma)
1007 seq_putc(m, '\"');
1008 seq_puts(m, opts->mnt_opts[i]);
1009 if (has_comma)
1010 seq_putc(m, '\"');
1011 }
1012}
1013
1014static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1015{
1016 struct security_mnt_opts opts;
1017 int rc;
1018
1019 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001020 if (rc) {
1021 /* before policy load we may get EINVAL, don't show anything */
1022 if (rc == -EINVAL)
1023 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001024 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001025 }
Eric Paris2069f452008-07-04 09:47:13 +10001026
1027 selinux_write_opts(m, &opts);
1028
1029 security_free_mnt_opts(&opts);
1030
1031 return rc;
1032}
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034static inline u16 inode_mode_to_security_class(umode_t mode)
1035{
1036 switch (mode & S_IFMT) {
1037 case S_IFSOCK:
1038 return SECCLASS_SOCK_FILE;
1039 case S_IFLNK:
1040 return SECCLASS_LNK_FILE;
1041 case S_IFREG:
1042 return SECCLASS_FILE;
1043 case S_IFBLK:
1044 return SECCLASS_BLK_FILE;
1045 case S_IFDIR:
1046 return SECCLASS_DIR;
1047 case S_IFCHR:
1048 return SECCLASS_CHR_FILE;
1049 case S_IFIFO:
1050 return SECCLASS_FIFO_FILE;
1051
1052 }
1053
1054 return SECCLASS_FILE;
1055}
1056
James Morris13402582005-09-30 14:24:34 -04001057static inline int default_protocol_stream(int protocol)
1058{
1059 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1060}
1061
1062static inline int default_protocol_dgram(int protocol)
1063{
1064 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1065}
1066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1068{
1069 switch (family) {
1070 case PF_UNIX:
1071 switch (type) {
1072 case SOCK_STREAM:
1073 case SOCK_SEQPACKET:
1074 return SECCLASS_UNIX_STREAM_SOCKET;
1075 case SOCK_DGRAM:
1076 return SECCLASS_UNIX_DGRAM_SOCKET;
1077 }
1078 break;
1079 case PF_INET:
1080 case PF_INET6:
1081 switch (type) {
1082 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001083 if (default_protocol_stream(protocol))
1084 return SECCLASS_TCP_SOCKET;
1085 else
1086 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001088 if (default_protocol_dgram(protocol))
1089 return SECCLASS_UDP_SOCKET;
1090 else
1091 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001092 case SOCK_DCCP:
1093 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001094 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 return SECCLASS_RAWIP_SOCKET;
1096 }
1097 break;
1098 case PF_NETLINK:
1099 switch (protocol) {
1100 case NETLINK_ROUTE:
1101 return SECCLASS_NETLINK_ROUTE_SOCKET;
1102 case NETLINK_FIREWALL:
1103 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001104 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1106 case NETLINK_NFLOG:
1107 return SECCLASS_NETLINK_NFLOG_SOCKET;
1108 case NETLINK_XFRM:
1109 return SECCLASS_NETLINK_XFRM_SOCKET;
1110 case NETLINK_SELINUX:
1111 return SECCLASS_NETLINK_SELINUX_SOCKET;
1112 case NETLINK_AUDIT:
1113 return SECCLASS_NETLINK_AUDIT_SOCKET;
1114 case NETLINK_IP6_FW:
1115 return SECCLASS_NETLINK_IP6FW_SOCKET;
1116 case NETLINK_DNRTMSG:
1117 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001118 case NETLINK_KOBJECT_UEVENT:
1119 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 default:
1121 return SECCLASS_NETLINK_SOCKET;
1122 }
1123 case PF_PACKET:
1124 return SECCLASS_PACKET_SOCKET;
1125 case PF_KEY:
1126 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001127 case PF_APPLETALK:
1128 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 }
1130
1131 return SECCLASS_SOCKET;
1132}
1133
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001134static int selinux_genfs_get_sid(struct dentry *dentry,
1135 u16 tclass,
1136 u16 flags,
1137 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001139 int rc;
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001140 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001141 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Eric Paris828dfe12008-04-17 13:17:49 -04001143 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (!buffer)
1145 return -ENOMEM;
1146
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001147 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1148 if (IS_ERR(path))
1149 rc = PTR_ERR(path);
1150 else {
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001151 if (flags & SE_SBPROC) {
1152 /* each process gets a /proc/PID/ entry. Strip off the
1153 * PID part to get a valid selinux labeling.
1154 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1155 while (path[1] >= '0' && path[1] <= '9') {
1156 path[1] = '/';
1157 path++;
1158 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001159 }
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001160 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 free_page((unsigned long)buffer);
1163 return rc;
1164}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166/* The inode's security attributes must be initialized before first use. */
1167static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1168{
1169 struct superblock_security_struct *sbsec = NULL;
1170 struct inode_security_struct *isec = inode->i_security;
1171 u32 sid;
1172 struct dentry *dentry;
1173#define INITCONTEXTLEN 255
1174 char *context = NULL;
1175 unsigned len = 0;
1176 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 if (isec->initialized)
1179 goto out;
1180
Eric Paris23970742006-09-25 23:32:01 -07001181 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001183 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001186 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 /* Defer initialization until selinux_complete_init,
1188 after the initial policy is loaded and the security
1189 server is ready to handle calls. */
1190 spin_lock(&sbsec->isec_lock);
1191 if (list_empty(&isec->list))
1192 list_add(&isec->list, &sbsec->isec_head);
1193 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001194 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
1196
1197 switch (sbsec->behavior) {
1198 case SECURITY_FS_USE_XATTR:
1199 if (!inode->i_op->getxattr) {
1200 isec->sid = sbsec->def_sid;
1201 break;
1202 }
1203
1204 /* Need a dentry, since the xattr API requires one.
1205 Life would be simpler if we could just pass the inode. */
1206 if (opt_dentry) {
1207 /* Called from d_instantiate or d_splice_alias. */
1208 dentry = dget(opt_dentry);
1209 } else {
1210 /* Called from selinux_complete_init, try to find a dentry. */
1211 dentry = d_find_alias(inode);
1212 }
1213 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001214 /*
1215 * this is can be hit on boot when a file is accessed
1216 * before the policy is loaded. When we load policy we
1217 * may find inodes that have no dentry on the
1218 * sbsec->isec_head list. No reason to complain as these
1219 * will get fixed up the next time we go through
1220 * inode_doinit with a dentry, before these inodes could
1221 * be used again by userspace.
1222 */
Eric Paris23970742006-09-25 23:32:01 -07001223 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225
1226 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001227 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 if (!context) {
1229 rc = -ENOMEM;
1230 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001231 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001233 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1235 context, len);
1236 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001237 kfree(context);
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 /* Need a larger buffer. Query for the right size. */
1240 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1241 NULL, 0);
1242 if (rc < 0) {
1243 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001244 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001247 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if (!context) {
1249 rc = -ENOMEM;
1250 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001251 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001253 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 rc = inode->i_op->getxattr(dentry,
1255 XATTR_NAME_SELINUX,
1256 context, len);
1257 }
1258 dput(dentry);
1259 if (rc < 0) {
1260 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001261 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001262 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 -rc, inode->i_sb->s_id, inode->i_ino);
1264 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001265 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 }
1267 /* Map ENODATA to the default file SID */
1268 sid = sbsec->def_sid;
1269 rc = 0;
1270 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001271 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001272 sbsec->def_sid,
1273 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001275 char *dev = inode->i_sb->s_id;
1276 unsigned long ino = inode->i_ino;
1277
1278 if (rc == -EINVAL) {
1279 if (printk_ratelimit())
1280 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1281 "context=%s. This indicates you may need to relabel the inode or the "
1282 "filesystem in question.\n", ino, dev, context);
1283 } else {
1284 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1285 "returned %d for dev=%s ino=%ld\n",
1286 __func__, context, -rc, dev, ino);
1287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 kfree(context);
1289 /* Leave with the unlabeled SID */
1290 rc = 0;
1291 break;
1292 }
1293 }
1294 kfree(context);
1295 isec->sid = sid;
1296 break;
1297 case SECURITY_FS_USE_TASK:
1298 isec->sid = isec->task_sid;
1299 break;
1300 case SECURITY_FS_USE_TRANS:
1301 /* Default to the fs SID. */
1302 isec->sid = sbsec->sid;
1303
1304 /* Try to obtain a transition SID. */
1305 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001306 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1307 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001309 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 isec->sid = sid;
1311 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001312 case SECURITY_FS_USE_MNTPOINT:
1313 isec->sid = sbsec->mntpoint_sid;
1314 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001316 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 isec->sid = sbsec->sid;
1318
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001319 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Moore810be002014-03-19 16:46:18 -04001320 /* We must have a dentry to determine the label on
1321 * procfs inodes */
1322 if (opt_dentry)
1323 /* Called from d_instantiate or
1324 * d_splice_alias. */
1325 dentry = dget(opt_dentry);
1326 else
1327 /* Called from selinux_complete_init, try to
1328 * find a dentry. */
1329 dentry = d_find_alias(inode);
1330 /*
1331 * This can be hit on boot when a file is accessed
1332 * before the policy is loaded. When we load policy we
1333 * may find inodes that have no dentry on the
1334 * sbsec->isec_head list. No reason to complain as
1335 * these will get fixed up the next time we go through
1336 * inode_doinit() with a dentry, before these inodes
1337 * could be used again by userspace.
1338 */
1339 if (!dentry)
1340 goto out_unlock;
1341 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001342 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1343 sbsec->flags, &sid);
Paul Moore810be002014-03-19 16:46:18 -04001344 dput(dentry);
1345 if (rc)
1346 goto out_unlock;
1347 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 }
1349 break;
1350 }
1351
1352 isec->initialized = 1;
1353
Eric Paris23970742006-09-25 23:32:01 -07001354out_unlock:
1355 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356out:
1357 if (isec->sclass == SECCLASS_FILE)
1358 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 return rc;
1360}
1361
1362/* Convert a Linux signal to an access vector. */
1363static inline u32 signal_to_av(int sig)
1364{
1365 u32 perm = 0;
1366
1367 switch (sig) {
1368 case SIGCHLD:
1369 /* Commonly granted from child to parent. */
1370 perm = PROCESS__SIGCHLD;
1371 break;
1372 case SIGKILL:
1373 /* Cannot be caught or ignored */
1374 perm = PROCESS__SIGKILL;
1375 break;
1376 case SIGSTOP:
1377 /* Cannot be caught or ignored */
1378 perm = PROCESS__SIGSTOP;
1379 break;
1380 default:
1381 /* All other signals. */
1382 perm = PROCESS__SIGNAL;
1383 break;
1384 }
1385
1386 return perm;
1387}
1388
David Howells275bb412008-11-14 10:39:19 +11001389/*
David Howellsd84f4f92008-11-14 10:39:23 +11001390 * Check permission between a pair of credentials
1391 * fork check, ptrace check, etc.
1392 */
1393static int cred_has_perm(const struct cred *actor,
1394 const struct cred *target,
1395 u32 perms)
1396{
1397 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1398
1399 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1400}
1401
1402/*
David Howells88e67f32008-11-14 10:39:21 +11001403 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001404 * fork check, ptrace check, etc.
1405 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001406 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001407 */
1408static int task_has_perm(const struct task_struct *tsk1,
1409 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 u32 perms)
1411{
David Howells275bb412008-11-14 10:39:19 +11001412 const struct task_security_struct *__tsec1, *__tsec2;
1413 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
David Howells275bb412008-11-14 10:39:19 +11001415 rcu_read_lock();
1416 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1417 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1418 rcu_read_unlock();
1419 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420}
1421
David Howells3b11a1d2008-11-14 10:39:26 +11001422/*
1423 * Check permission between current and another task, e.g. signal checks,
1424 * fork check, ptrace check, etc.
1425 * current is the actor and tsk2 is the target
1426 * - this uses current's subjective creds
1427 */
1428static int current_has_perm(const struct task_struct *tsk,
1429 u32 perms)
1430{
1431 u32 sid, tsid;
1432
1433 sid = current_sid();
1434 tsid = task_sid(tsk);
1435 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1436}
1437
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001438#if CAP_LAST_CAP > 63
1439#error Fix SELinux to handle capabilities > 63.
1440#endif
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001443static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001444 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445{
Thomas Liu2bf49692009-07-14 12:14:09 -04001446 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001447 struct selinux_audit_data sad = {0,};
Eric Paris06112162008-11-11 22:02:50 +11001448 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001449 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001450 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001451 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001452 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Thomas Liu2bf49692009-07-14 12:14:09 -04001454 COMMON_AUDIT_DATA_INIT(&ad, CAP);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001455 ad.selinux_audit_data = &sad;
Eric Paris6a9de492012-01-03 12:25:14 -05001456 ad.tsk = current;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 ad.u.cap = cap;
1458
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001459 switch (CAP_TO_INDEX(cap)) {
1460 case 0:
1461 sclass = SECCLASS_CAPABILITY;
1462 break;
1463 case 1:
1464 sclass = SECCLASS_CAPABILITY2;
1465 break;
1466 default:
1467 printk(KERN_ERR
1468 "SELinux: out of range capability %d\n", cap);
1469 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001470 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001471 }
Eric Paris06112162008-11-11 22:02:50 +11001472
David Howells275bb412008-11-14 10:39:19 +11001473 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001474 if (audit == SECURITY_CAP_AUDIT) {
1475 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1476 if (rc2)
1477 return rc2;
1478 }
Eric Paris06112162008-11-11 22:02:50 +11001479 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480}
1481
1482/* Check whether a task is allowed to use a system operation. */
1483static int task_has_system(struct task_struct *tsk,
1484 u32 perms)
1485{
David Howells275bb412008-11-14 10:39:19 +11001486 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
David Howells275bb412008-11-14 10:39:19 +11001488 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 SECCLASS_SYSTEM, perms, NULL);
1490}
1491
1492/* Check whether a task has a particular permission to an inode.
1493 The 'adp' parameter is optional and allows other audit
1494 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001495static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 struct inode *inode,
1497 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001498 struct common_audit_data *adp,
1499 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001502 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
David Howellse0e81732009-09-02 09:13:40 +01001504 validate_creds(cred);
1505
Eric Paris828dfe12008-04-17 13:17:49 -04001506 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001507 return 0;
1508
David Howells88e67f32008-11-14 10:39:21 +11001509 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 isec = inode->i_security;
1511
Eric Paris9ade0cf2011-04-25 16:26:29 -04001512 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513}
1514
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001515static int inode_has_perm_noadp(const struct cred *cred,
1516 struct inode *inode,
1517 u32 perms,
1518 unsigned flags)
1519{
1520 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001521 struct selinux_audit_data sad = {0,};
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001522
1523 COMMON_AUDIT_DATA_INIT(&ad, INODE);
1524 ad.u.inode = inode;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001525 ad.selinux_audit_data = &sad;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001526 return inode_has_perm(cred, inode, perms, &ad, flags);
1527}
1528
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529/* Same as inode_has_perm, but pass explicit audit data containing
1530 the dentry to help the auditing code to more easily generate the
1531 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001532static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 struct dentry *dentry,
1534 u32 av)
1535{
1536 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001537 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001538 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001539
Eric Paris2875fa02011-04-28 16:04:24 -04001540 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1541 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001542 ad.selinux_audit_data = &sad;
Eric Paris2875fa02011-04-28 16:04:24 -04001543 return inode_has_perm(cred, inode, av, &ad, 0);
1544}
1545
1546/* Same as inode_has_perm, but pass explicit audit data containing
1547 the path to help the auditing code to more easily generate the
1548 pathname if needed. */
1549static inline int path_has_perm(const struct cred *cred,
1550 struct path *path,
1551 u32 av)
1552{
1553 struct inode *inode = path->dentry->d_inode;
1554 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001555 struct selinux_audit_data sad = {0,};
Eric Paris2875fa02011-04-28 16:04:24 -04001556
Eric Parisf48b7392011-04-25 12:54:27 -04001557 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris2875fa02011-04-28 16:04:24 -04001558 ad.u.path = *path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001559 ad.selinux_audit_data = &sad;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001560 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561}
1562
1563/* Check whether a task can use an open file descriptor to
1564 access an inode in a given way. Check access to the
1565 descriptor itself, and then use dentry_has_perm to
1566 check a particular permission to the file.
1567 Access to the descriptor is implicitly granted if it
1568 has the same SID as the process. If av is zero, then
1569 access to the file is not checked, e.g. for cases
1570 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001571static int file_has_perm(const struct cred *cred,
1572 struct file *file,
1573 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001576 struct inode *inode = file->f_path.dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001577 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001578 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001579 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 int rc;
1581
Eric Parisf48b7392011-04-25 12:54:27 -04001582 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1583 ad.u.path = file->f_path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001584 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
David Howells275bb412008-11-14 10:39:19 +11001586 if (sid != fsec->sid) {
1587 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 SECCLASS_FD,
1589 FD__USE,
1590 &ad);
1591 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001592 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 }
1594
1595 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001596 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001598 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
David Howells88e67f32008-11-14 10:39:21 +11001600out:
1601 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602}
1603
1604/* Check whether a task can create a file. */
1605static int may_create(struct inode *dir,
1606 struct dentry *dentry,
1607 u16 tclass)
1608{
Paul Moore5fb49872010-04-22 14:46:19 -04001609 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 struct inode_security_struct *dsec;
1611 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001612 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001613 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001614 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 int rc;
1616
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 dsec = dir->i_security;
1618 sbsec = dir->i_sb->s_security;
1619
David Howells275bb412008-11-14 10:39:19 +11001620 sid = tsec->sid;
1621 newsid = tsec->create_sid;
1622
Eric Parisa2694342011-04-25 13:10:27 -04001623 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1624 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001625 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
David Howells275bb412008-11-14 10:39:19 +11001627 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 DIR__ADD_NAME | DIR__SEARCH,
1629 &ad);
1630 if (rc)
1631 return rc;
1632
David P. Quigleycd895962009-01-16 09:22:04 -05001633 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001634 rc = security_transition_sid(sid, dsec->sid, tclass,
1635 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 if (rc)
1637 return rc;
1638 }
1639
David Howells275bb412008-11-14 10:39:19 +11001640 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 if (rc)
1642 return rc;
1643
Amir Samuelov6a22e462014-05-26 11:44:06 +03001644 rc = avc_has_perm(newsid, sbsec->sid,
1645 SECCLASS_FILESYSTEM,
1646 FILESYSTEM__ASSOCIATE, &ad);
1647 if (rc)
1648 return rc;
1649
1650 rc = pft_inode_mknod(dir, dentry, 0, 0);
1651
1652 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653}
1654
Michael LeMay4eb582c2006-06-26 00:24:57 -07001655/* Check whether a task can create a key. */
1656static int may_create_key(u32 ksid,
1657 struct task_struct *ctx)
1658{
David Howells275bb412008-11-14 10:39:19 +11001659 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001660
David Howells275bb412008-11-14 10:39:19 +11001661 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001662}
1663
Eric Paris828dfe12008-04-17 13:17:49 -04001664#define MAY_LINK 0
1665#define MAY_UNLINK 1
1666#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
1668/* Check whether a task can link, unlink, or rmdir a file/directory. */
1669static int may_link(struct inode *dir,
1670 struct dentry *dentry,
1671 int kind)
1672
1673{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001675 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001676 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001677 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 u32 av;
1679 int rc;
1680
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 dsec = dir->i_security;
1682 isec = dentry->d_inode->i_security;
1683
Eric Parisa2694342011-04-25 13:10:27 -04001684 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1685 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001686 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 av = DIR__SEARCH;
1689 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001690 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (rc)
1692 return rc;
1693
1694 switch (kind) {
1695 case MAY_LINK:
1696 av = FILE__LINK;
1697 break;
1698 case MAY_UNLINK:
1699 av = FILE__UNLINK;
1700 break;
1701 case MAY_RMDIR:
1702 av = DIR__RMDIR;
1703 break;
1704 default:
Eric Paris744ba352008-04-17 11:52:44 -04001705 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1706 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 return 0;
1708 }
1709
David Howells275bb412008-11-14 10:39:19 +11001710 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Amir Samuelov6a22e462014-05-26 11:44:06 +03001711 if (rc)
1712 return rc;
1713
1714 if (kind == MAY_UNLINK)
1715 rc = pft_inode_unlink(dir, dentry);
1716
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 return rc;
1718}
1719
1720static inline int may_rename(struct inode *old_dir,
1721 struct dentry *old_dentry,
1722 struct inode *new_dir,
1723 struct dentry *new_dentry)
1724{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001726 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001727 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001728 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 u32 av;
1730 int old_is_dir, new_is_dir;
1731 int rc;
1732
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 old_dsec = old_dir->i_security;
1734 old_isec = old_dentry->d_inode->i_security;
1735 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1736 new_dsec = new_dir->i_security;
1737
Eric Parisa2694342011-04-25 13:10:27 -04001738 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001739 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Eric Parisa2694342011-04-25 13:10:27 -04001741 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001742 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1744 if (rc)
1745 return rc;
David Howells275bb412008-11-14 10:39:19 +11001746 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 old_isec->sclass, FILE__RENAME, &ad);
1748 if (rc)
1749 return rc;
1750 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001751 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 old_isec->sclass, DIR__REPARENT, &ad);
1753 if (rc)
1754 return rc;
1755 }
1756
Eric Parisa2694342011-04-25 13:10:27 -04001757 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 av = DIR__ADD_NAME | DIR__SEARCH;
1759 if (new_dentry->d_inode)
1760 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001761 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 if (rc)
1763 return rc;
1764 if (new_dentry->d_inode) {
1765 new_isec = new_dentry->d_inode->i_security;
1766 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001767 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 new_isec->sclass,
1769 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1770 if (rc)
1771 return rc;
1772 }
1773
1774 return 0;
1775}
1776
1777/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001778static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 struct super_block *sb,
1780 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001781 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001784 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001787 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788}
1789
1790/* Convert a Linux mode and permission mask to an access vector. */
1791static inline u32 file_mask_to_av(int mode, int mask)
1792{
1793 u32 av = 0;
1794
Al Virodba19c62011-07-25 20:49:29 -04001795 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 if (mask & MAY_EXEC)
1797 av |= FILE__EXECUTE;
1798 if (mask & MAY_READ)
1799 av |= FILE__READ;
1800
1801 if (mask & MAY_APPEND)
1802 av |= FILE__APPEND;
1803 else if (mask & MAY_WRITE)
1804 av |= FILE__WRITE;
1805
1806 } else {
1807 if (mask & MAY_EXEC)
1808 av |= DIR__SEARCH;
1809 if (mask & MAY_WRITE)
1810 av |= DIR__WRITE;
1811 if (mask & MAY_READ)
1812 av |= DIR__READ;
1813 }
1814
1815 return av;
1816}
1817
1818/* Convert a Linux file to an access vector. */
1819static inline u32 file_to_av(struct file *file)
1820{
1821 u32 av = 0;
1822
1823 if (file->f_mode & FMODE_READ)
1824 av |= FILE__READ;
1825 if (file->f_mode & FMODE_WRITE) {
1826 if (file->f_flags & O_APPEND)
1827 av |= FILE__APPEND;
1828 else
1829 av |= FILE__WRITE;
1830 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001831 if (!av) {
1832 /*
1833 * Special file opened with flags 3 for ioctl-only use.
1834 */
1835 av = FILE__IOCTL;
1836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
1838 return av;
1839}
1840
Eric Paris8b6a5a32008-10-29 17:06:46 -04001841/*
1842 * Convert a file to an access vector and include the correct open
1843 * open permission.
1844 */
1845static inline u32 open_file_to_av(struct file *file)
1846{
1847 u32 av = file_to_av(file);
1848
Eric Paris49b7b8d2010-07-23 11:44:09 -04001849 if (selinux_policycap_openperm)
1850 av |= FILE__OPEN;
1851
Eric Paris8b6a5a32008-10-29 17:06:46 -04001852 return av;
1853}
1854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855/* Hook functions begin here. */
1856
Stephen Smalley48a23702012-11-05 08:15:34 -05001857static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1858{
1859 u32 mysid = current_sid();
1860 u32 mgrsid = task_sid(mgr);
1861
1862 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL);
1863}
1864
1865static int selinux_binder_transaction(struct task_struct *from, struct task_struct *to)
1866{
1867 u32 mysid = current_sid();
1868 u32 fromsid = task_sid(from);
1869 u32 tosid = task_sid(to);
1870 int rc;
1871
1872 if (mysid != fromsid) {
1873 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL);
1874 if (rc)
1875 return rc;
1876 }
1877
1878 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL);
1879}
1880
1881static int selinux_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
1882{
1883 u32 fromsid = task_sid(from);
1884 u32 tosid = task_sid(to);
1885 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, NULL);
1886}
1887
1888static int selinux_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
1889{
1890 u32 sid = task_sid(to);
1891 struct file_security_struct *fsec = file->f_security;
1892 struct inode *inode = file->f_path.dentry->d_inode;
1893 struct inode_security_struct *isec = inode->i_security;
1894 struct common_audit_data ad;
1895 struct selinux_audit_data sad = {0,};
1896 int rc;
1897
1898 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1899 ad.u.path = file->f_path;
1900 ad.selinux_audit_data = &sad;
1901
1902 if (sid != fsec->sid) {
1903 rc = avc_has_perm(sid, fsec->sid,
1904 SECCLASS_FD,
1905 FD__USE,
1906 &ad);
1907 if (rc)
1908 return rc;
1909 }
1910
1911 if (unlikely(IS_PRIVATE(inode)))
1912 return 0;
1913
1914 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
1915 &ad);
1916}
1917
Ingo Molnar9e488582009-05-07 19:26:19 +10001918static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001919 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 int rc;
1922
Ingo Molnar9e488582009-05-07 19:26:19 +10001923 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 if (rc)
1925 return rc;
1926
Eric Paris69f594a2012-01-03 12:25:15 -05001927 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001928 u32 sid = current_sid();
1929 u32 csid = task_sid(child);
1930 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001931 }
1932
David Howells3b11a1d2008-11-14 10:39:26 +11001933 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001934}
1935
1936static int selinux_ptrace_traceme(struct task_struct *parent)
1937{
1938 int rc;
1939
Eric Paris200ac532009-02-12 15:01:04 -05001940 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001941 if (rc)
1942 return rc;
1943
1944 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945}
1946
1947static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001948 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949{
1950 int error;
1951
David Howells3b11a1d2008-11-14 10:39:26 +11001952 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 if (error)
1954 return error;
1955
Eric Paris200ac532009-02-12 15:01:04 -05001956 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957}
1958
David Howellsd84f4f92008-11-14 10:39:23 +11001959static int selinux_capset(struct cred *new, const struct cred *old,
1960 const kernel_cap_t *effective,
1961 const kernel_cap_t *inheritable,
1962 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963{
1964 int error;
1965
Eric Paris200ac532009-02-12 15:01:04 -05001966 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001967 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 if (error)
1969 return error;
1970
David Howellsd84f4f92008-11-14 10:39:23 +11001971 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972}
1973
James Morris5626d3e2009-01-30 10:05:06 +11001974/*
1975 * (This comment used to live with the selinux_task_setuid hook,
1976 * which was removed).
1977 *
1978 * Since setuid only affects the current process, and since the SELinux
1979 * controls are not based on the Linux identity attributes, SELinux does not
1980 * need to control this operation. However, SELinux does control the use of
1981 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1982 */
1983
Eric Paris6a9de492012-01-03 12:25:14 -05001984static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1985 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986{
1987 int rc;
1988
Eric Paris6a9de492012-01-03 12:25:14 -05001989 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 if (rc)
1991 return rc;
1992
Eric Paris6a9de492012-01-03 12:25:14 -05001993 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994}
1995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1997{
David Howells88e67f32008-11-14 10:39:21 +11001998 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 int rc = 0;
2000
2001 if (!sb)
2002 return 0;
2003
2004 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002005 case Q_SYNC:
2006 case Q_QUOTAON:
2007 case Q_QUOTAOFF:
2008 case Q_SETINFO:
2009 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002010 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002011 break;
2012 case Q_GETFMT:
2013 case Q_GETINFO:
2014 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002015 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002016 break;
2017 default:
2018 rc = 0; /* let the kernel handle invalid cmds */
2019 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021 return rc;
2022}
2023
2024static int selinux_quota_on(struct dentry *dentry)
2025{
David Howells88e67f32008-11-14 10:39:21 +11002026 const struct cred *cred = current_cred();
2027
Eric Paris2875fa02011-04-28 16:04:24 -04002028 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
Eric Paris12b30522010-11-15 18:36:29 -05002031static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032{
2033 int rc;
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002036 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2037 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002038 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2039 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002040 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2041 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2042 /* Set level of messages printed to console */
2043 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002044 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2045 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002046 case SYSLOG_ACTION_CLOSE: /* Close log */
2047 case SYSLOG_ACTION_OPEN: /* Open log */
2048 case SYSLOG_ACTION_READ: /* Read from log */
2049 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2050 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002051 default:
2052 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2053 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 }
2055 return rc;
2056}
2057
2058/*
2059 * Check that a process has enough memory to allocate a new virtual
2060 * mapping. 0 means there is enough memory for the allocation to
2061 * succeed and -ENOMEM implies there is not.
2062 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 * Do not audit the selinux permission check, as this is applied to all
2064 * processes that allocate mappings.
2065 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002066static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067{
2068 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Eric Paris6a9de492012-01-03 12:25:14 -05002070 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002071 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 if (rc == 0)
2073 cap_sys_admin = 1;
2074
Alan Cox34b4e4a2007-08-22 14:01:28 -07002075 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076}
2077
2078/* binprm security operations */
2079
David Howellsa6f76f22008-11-14 10:39:24 +11002080static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
David Howellsa6f76f22008-11-14 10:39:24 +11002082 const struct task_security_struct *old_tsec;
2083 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002085 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002086 struct selinux_audit_data sad = {0,};
David Howellsa6f76f22008-11-14 10:39:24 +11002087 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 int rc;
2089
Eric Paris200ac532009-02-12 15:01:04 -05002090 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 if (rc)
2092 return rc;
2093
David Howellsa6f76f22008-11-14 10:39:24 +11002094 /* SELinux context only depends on initial program or script and not
2095 * the script interpreter */
2096 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 return 0;
2098
David Howellsa6f76f22008-11-14 10:39:24 +11002099 old_tsec = current_security();
2100 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 isec = inode->i_security;
2102
2103 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002104 new_tsec->sid = old_tsec->sid;
2105 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Michael LeMay28eba5b2006-06-27 02:53:42 -07002107 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002108 new_tsec->create_sid = 0;
2109 new_tsec->keycreate_sid = 0;
2110 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
David Howellsa6f76f22008-11-14 10:39:24 +11002112 if (old_tsec->exec_sid) {
2113 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002115 new_tsec->exec_sid = 0;
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002116
2117 /*
2118 * Minimize confusion: if no_new_privs and a transition is
2119 * explicitly requested, then fail the exec.
2120 */
2121 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2122 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 } else {
2124 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002125 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002126 SECCLASS_PROCESS, NULL,
2127 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (rc)
2129 return rc;
2130 }
2131
Eric Parisf48b7392011-04-25 12:54:27 -04002132 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002133 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002134 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002136 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2137 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002138 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
David Howellsa6f76f22008-11-14 10:39:24 +11002140 if (new_tsec->sid == old_tsec->sid) {
2141 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2143 if (rc)
2144 return rc;
2145 } else {
2146 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002147 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2149 if (rc)
2150 return rc;
2151
David Howellsa6f76f22008-11-14 10:39:24 +11002152 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2154 if (rc)
2155 return rc;
2156
David Howellsa6f76f22008-11-14 10:39:24 +11002157 /* Check for shared state */
2158 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2159 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2160 SECCLASS_PROCESS, PROCESS__SHARE,
2161 NULL);
2162 if (rc)
2163 return -EPERM;
2164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165
David Howellsa6f76f22008-11-14 10:39:24 +11002166 /* Make sure that anyone attempting to ptrace over a task that
2167 * changes its SID has the appropriate permit */
2168 if (bprm->unsafe &
2169 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2170 struct task_struct *tracer;
2171 struct task_security_struct *sec;
2172 u32 ptsid = 0;
2173
2174 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002175 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002176 if (likely(tracer != NULL)) {
2177 sec = __task_cred(tracer)->security;
2178 ptsid = sec->sid;
2179 }
2180 rcu_read_unlock();
2181
2182 if (ptsid != 0) {
2183 rc = avc_has_perm(ptsid, new_tsec->sid,
2184 SECCLASS_PROCESS,
2185 PROCESS__PTRACE, NULL);
2186 if (rc)
2187 return -EPERM;
2188 }
2189 }
2190
2191 /* Clear any possibly unsafe personality bits on exec: */
2192 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
2194
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return 0;
2196}
2197
Eric Paris828dfe12008-04-17 13:17:49 -04002198static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199{
Paul Moore5fb49872010-04-22 14:46:19 -04002200 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002201 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 int atsecure = 0;
2203
David Howells275bb412008-11-14 10:39:19 +11002204 sid = tsec->sid;
2205 osid = tsec->osid;
2206
2207 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 /* Enable secure mode for SIDs transitions unless
2209 the noatsecure permission is granted between
2210 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002211 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002212 SECCLASS_PROCESS,
2213 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215
Eric Paris200ac532009-02-12 15:01:04 -05002216 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217}
2218
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002220static inline void flush_unauthorized_files(const struct cred *cred,
2221 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222{
Thomas Liu2bf49692009-07-14 12:14:09 -04002223 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002224 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002226 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002227 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002229 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002231 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002233 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002234 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002235 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002236 struct inode *inode;
2237
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 /* Revalidate access to controlling tty.
2239 Use inode_has_perm on the tty inode directly rather
2240 than using file_has_perm, as this particular open
2241 file may belong to another process and we are only
2242 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002243 file_priv = list_first_entry(&tty->tty_files,
2244 struct tty_file_private, list);
2245 file = file_priv->file;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002246 inode = file->f_path.dentry->d_inode;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07002247 if (inode_has_perm_noadp(cred, inode,
2248 FILE__READ | FILE__WRITE, 0)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002249 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 }
2251 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002252 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002253 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002255 /* Reset controlling tty. */
2256 if (drop_tty)
2257 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 /* Revalidate access to inherited open files. */
2260
Eric Parisf48b7392011-04-25 12:54:27 -04002261 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002262 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
2264 spin_lock(&files->file_lock);
2265 for (;;) {
2266 unsigned long set, i;
2267 int fd;
2268
2269 j++;
Josh Boyerf17e9232012-07-25 10:40:34 -04002270 i = j * BITS_PER_LONG;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002271 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002272 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 break;
David Howells1fd36ad2012-02-16 17:49:54 +00002274 set = fdt->open_fds[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 if (!set)
2276 continue;
2277 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002278 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 if (set & 1) {
2280 file = fget(i);
2281 if (!file)
2282 continue;
David Howells88e67f32008-11-14 10:39:21 +11002283 if (file_has_perm(cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 file,
2285 file_to_av(file))) {
2286 sys_close(i);
2287 fd = get_unused_fd();
2288 if (fd != i) {
2289 if (fd >= 0)
2290 put_unused_fd(fd);
2291 fput(file);
2292 continue;
2293 }
2294 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002295 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 } else {
David Howells745ca242008-11-14 10:39:22 +11002297 devnull = dentry_open(
2298 dget(selinux_null),
2299 mntget(selinuxfs_mount),
2300 O_RDWR, cred);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002301 if (IS_ERR(devnull)) {
2302 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 put_unused_fd(fd);
2304 fput(file);
2305 continue;
2306 }
2307 }
2308 fd_install(fd, devnull);
2309 }
2310 fput(file);
2311 }
2312 }
2313 spin_lock(&files->file_lock);
2314
2315 }
2316 spin_unlock(&files->file_lock);
2317}
2318
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319/*
David Howellsa6f76f22008-11-14 10:39:24 +11002320 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 */
David Howellsa6f76f22008-11-14 10:39:24 +11002322static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323{
David Howellsa6f76f22008-11-14 10:39:24 +11002324 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 int rc, i;
2327
David Howellsa6f76f22008-11-14 10:39:24 +11002328 new_tsec = bprm->cred->security;
2329 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 return;
2331
2332 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002333 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
David Howellsa6f76f22008-11-14 10:39:24 +11002335 /* Always clear parent death signal on SID transitions. */
2336 current->pdeath_signal = 0;
2337
2338 /* Check whether the new SID can inherit resource limits from the old
2339 * SID. If not, reset all soft limits to the lower of the current
2340 * task's hard limit and the init task's soft limit.
2341 *
2342 * Note that the setting of hard limits (even to lower them) can be
2343 * controlled by the setrlimit check. The inclusion of the init task's
2344 * soft limit into the computation is to avoid resetting soft limits
2345 * higher than the default soft limit for cases where the default is
2346 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2347 */
2348 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2349 PROCESS__RLIMITINH, NULL);
2350 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002351 /* protect against do_prlimit() */
2352 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002353 for (i = 0; i < RLIM_NLIMITS; i++) {
2354 rlim = current->signal->rlim + i;
2355 initrlim = init_task.signal->rlim + i;
2356 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2357 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002358 task_unlock(current);
2359 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002360 }
2361}
2362
2363/*
2364 * Clean up the process immediately after the installation of new credentials
2365 * due to exec
2366 */
2367static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2368{
2369 const struct task_security_struct *tsec = current_security();
2370 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002371 u32 osid, sid;
2372 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002373
David Howellsa6f76f22008-11-14 10:39:24 +11002374 osid = tsec->osid;
2375 sid = tsec->sid;
2376
2377 if (sid == osid)
2378 return;
2379
2380 /* Check whether the new SID can inherit signal state from the old SID.
2381 * If not, clear itimers to avoid subsequent signal generation and
2382 * flush and unblock signals.
2383 *
2384 * This must occur _after_ the task SID has been updated so that any
2385 * kill done after the flush will be checked against the new SID.
2386 */
2387 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 if (rc) {
2389 memset(&itimer, 0, sizeof itimer);
2390 for (i = 0; i < 3; i++)
2391 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002393 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2394 __flush_signals(current);
2395 flush_signal_handlers(current, 1);
2396 sigemptyset(&current->blocked);
2397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 spin_unlock_irq(&current->sighand->siglock);
2399 }
2400
David Howellsa6f76f22008-11-14 10:39:24 +11002401 /* Wake up the parent if it is waiting so that it can recheck
2402 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002403 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002404 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002405 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406}
2407
2408/* superblock security operations */
2409
2410static int selinux_sb_alloc_security(struct super_block *sb)
2411{
2412 return superblock_alloc_security(sb);
2413}
2414
2415static void selinux_sb_free_security(struct super_block *sb)
2416{
2417 superblock_free_security(sb);
2418}
2419
2420static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2421{
2422 if (plen > olen)
2423 return 0;
2424
2425 return !memcmp(prefix, option, plen);
2426}
2427
2428static inline int selinux_option(char *option, int len)
2429{
Eric Paris832cbd92008-04-01 13:24:09 -04002430 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2431 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2432 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002433 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2434 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435}
2436
2437static inline void take_option(char **to, char *from, int *first, int len)
2438{
2439 if (!*first) {
2440 **to = ',';
2441 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002442 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 *first = 0;
2444 memcpy(*to, from, len);
2445 *to += len;
2446}
2447
Eric Paris828dfe12008-04-17 13:17:49 -04002448static inline void take_selinux_option(char **to, char *from, int *first,
2449 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002450{
2451 int current_size = 0;
2452
2453 if (!*first) {
2454 **to = '|';
2455 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002456 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002457 *first = 0;
2458
2459 while (current_size < len) {
2460 if (*from != '"') {
2461 **to = *from;
2462 *to += 1;
2463 }
2464 from += 1;
2465 current_size += 1;
2466 }
2467}
2468
Eric Parise0007522008-03-05 10:31:54 -05002469static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470{
2471 int fnosec, fsec, rc = 0;
2472 char *in_save, *in_curr, *in_end;
2473 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002474 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
2476 in_curr = orig;
2477 sec_curr = copy;
2478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2480 if (!nosec) {
2481 rc = -ENOMEM;
2482 goto out;
2483 }
2484
2485 nosec_save = nosec;
2486 fnosec = fsec = 1;
2487 in_save = in_end = orig;
2488
2489 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002490 if (*in_end == '"')
2491 open_quote = !open_quote;
2492 if ((*in_end == ',' && open_quote == 0) ||
2493 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 int len = in_end - in_curr;
2495
2496 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002497 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 else
2499 take_option(&nosec, in_curr, &fnosec, len);
2500
2501 in_curr = in_end + 1;
2502 }
2503 } while (*in_end++);
2504
Eric Paris6931dfc2005-06-30 02:58:51 -07002505 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002506 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507out:
2508 return rc;
2509}
2510
Eric Paris026eb162011-03-03 16:09:14 -05002511static int selinux_sb_remount(struct super_block *sb, void *data)
2512{
2513 int rc, i, *flags;
2514 struct security_mnt_opts opts;
2515 char *secdata, **mount_options;
2516 struct superblock_security_struct *sbsec = sb->s_security;
2517
2518 if (!(sbsec->flags & SE_SBINITIALIZED))
2519 return 0;
2520
2521 if (!data)
2522 return 0;
2523
2524 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2525 return 0;
2526
2527 security_init_mnt_opts(&opts);
2528 secdata = alloc_secdata();
2529 if (!secdata)
2530 return -ENOMEM;
2531 rc = selinux_sb_copy_data(data, secdata);
2532 if (rc)
2533 goto out_free_secdata;
2534
2535 rc = selinux_parse_opts_str(secdata, &opts);
2536 if (rc)
2537 goto out_free_secdata;
2538
2539 mount_options = opts.mnt_opts;
2540 flags = opts.mnt_opts_flags;
2541
2542 for (i = 0; i < opts.num_mnt_opts; i++) {
2543 u32 sid;
2544 size_t len;
2545
2546 if (flags[i] == SE_SBLABELSUPP)
2547 continue;
2548 len = strlen(mount_options[i]);
2549 rc = security_context_to_sid(mount_options[i], len, &sid);
2550 if (rc) {
2551 printk(KERN_WARNING "SELinux: security_context_to_sid"
2552 "(%s) failed for (dev %s, type %s) errno=%d\n",
2553 mount_options[i], sb->s_id, sb->s_type->name, rc);
2554 goto out_free_opts;
2555 }
2556 rc = -EINVAL;
2557 switch (flags[i]) {
2558 case FSCONTEXT_MNT:
2559 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2560 goto out_bad_option;
2561 break;
2562 case CONTEXT_MNT:
2563 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2564 goto out_bad_option;
2565 break;
2566 case ROOTCONTEXT_MNT: {
2567 struct inode_security_struct *root_isec;
2568 root_isec = sb->s_root->d_inode->i_security;
2569
2570 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2571 goto out_bad_option;
2572 break;
2573 }
2574 case DEFCONTEXT_MNT:
2575 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2576 goto out_bad_option;
2577 break;
2578 default:
2579 goto out_free_opts;
2580 }
2581 }
2582
2583 rc = 0;
2584out_free_opts:
2585 security_free_mnt_opts(&opts);
2586out_free_secdata:
2587 free_secdata(secdata);
2588 return rc;
2589out_bad_option:
2590 printk(KERN_WARNING "SELinux: unable to change security options "
2591 "during remount (dev %s, type=%s)\n", sb->s_id,
2592 sb->s_type->name);
2593 goto out_free_opts;
2594}
2595
James Morris12204e22008-12-19 10:44:42 +11002596static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597{
David Howells88e67f32008-11-14 10:39:21 +11002598 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002599 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002600 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 int rc;
2602
2603 rc = superblock_doinit(sb, data);
2604 if (rc)
2605 return rc;
2606
James Morris74192242008-12-19 11:41:10 +11002607 /* Allow all mounts performed by the kernel */
2608 if (flags & MS_KERNMOUNT)
2609 return 0;
2610
Eric Parisa2694342011-04-25 13:10:27 -04002611 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002612 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002613 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002614 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615}
2616
David Howells726c3342006-06-23 02:02:58 -07002617static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
David Howells88e67f32008-11-14 10:39:21 +11002619 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002620 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002621 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Eric Parisa2694342011-04-25 13:10:27 -04002623 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002624 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002625 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002626 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627}
2628
Al Viroddaa16d2012-10-11 11:42:01 -04002629static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002630 struct path *path,
Al Viroddaa16d2012-10-11 11:42:01 -04002631 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002632 unsigned long flags,
2633 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
David Howells88e67f32008-11-14 10:39:21 +11002635 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002638 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002639 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 else
Eric Paris2875fa02011-04-28 16:04:24 -04002641 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643
2644static int selinux_umount(struct vfsmount *mnt, int flags)
2645{
David Howells88e67f32008-11-14 10:39:21 +11002646 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
David Howells88e67f32008-11-14 10:39:21 +11002648 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002649 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650}
2651
2652/* inode security operations */
2653
2654static int selinux_inode_alloc_security(struct inode *inode)
2655{
2656 return inode_alloc_security(inode);
2657}
2658
2659static void selinux_inode_free_security(struct inode *inode)
2660{
2661 inode_free_security(inode);
2662}
2663
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002664static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002665 const struct qstr *qstr, char **name,
2666 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002667{
Paul Moore5fb49872010-04-22 14:46:19 -04002668 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002669 struct inode_security_struct *dsec;
2670 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002671 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002672 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002673 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002674
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002675 dsec = dir->i_security;
2676 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002677
David Howells275bb412008-11-14 10:39:19 +11002678 sid = tsec->sid;
2679 newsid = tsec->create_sid;
2680
Eric Paris415103f2010-12-02 16:13:40 -05002681 if ((sbsec->flags & SE_SBINITIALIZED) &&
2682 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2683 newsid = sbsec->mntpoint_sid;
2684 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002685 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002686 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002687 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002688 if (rc) {
2689 printk(KERN_WARNING "%s: "
2690 "security_transition_sid failed, rc=%d (dev=%s "
2691 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002692 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002693 -rc, inode->i_sb->s_id, inode->i_ino);
2694 return rc;
2695 }
2696 }
2697
Eric Paris296fddf2006-09-25 23:32:00 -07002698 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002699 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002700 struct inode_security_struct *isec = inode->i_security;
2701 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2702 isec->sid = newsid;
2703 isec->initialized = 1;
2704 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002705
David P. Quigleycd895962009-01-16 09:22:04 -05002706 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002707 return -EOPNOTSUPP;
2708
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002709 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002710 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002711 if (!namep)
2712 return -ENOMEM;
2713 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002714 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002715
2716 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002717 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002718 if (rc) {
2719 kfree(namep);
2720 return rc;
2721 }
2722 *value = context;
2723 *len = clen;
2724 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002725
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002726 return 0;
2727}
2728
Al Viro4acdaf22011-07-26 01:42:34 -04002729static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002731 int ret;
2732
2733 ret = pft_inode_create(dir, dentry, mode);
2734 if (ret < 0)
2735 return ret;
2736
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 return may_create(dir, dentry, SECCLASS_FILE);
2738}
2739
Amir Samuelov6a22e462014-05-26 11:44:06 +03002740static int selinux_inode_post_create(struct inode *dir, struct dentry *dentry,
2741 umode_t mode)
2742{
2743 int ret;
2744
2745 ret = pft_inode_post_create(dir, dentry, mode);
2746
2747 return ret;
2748}
2749
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2751{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 return may_link(dir, old_dentry, MAY_LINK);
2753}
2754
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2756{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return may_link(dir, dentry, MAY_UNLINK);
2758}
2759
2760static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2761{
2762 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2763}
2764
Al Viro18bb1db2011-07-26 01:41:39 -04002765static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766{
2767 return may_create(dir, dentry, SECCLASS_DIR);
2768}
2769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2771{
2772 return may_link(dir, dentry, MAY_RMDIR);
2773}
2774
Al Viro1a67aaf2011-07-26 01:52:52 -04002775static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2778}
2779
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002781 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002783 int rc;
2784
2785 rc = pft_inode_rename(old_inode, old_dentry, new_inode, new_dentry);
2786 if (rc)
2787 return rc;
2788
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2790}
2791
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792static int selinux_inode_readlink(struct dentry *dentry)
2793{
David Howells88e67f32008-11-14 10:39:21 +11002794 const struct cred *cred = current_cred();
2795
Eric Paris2875fa02011-04-28 16:04:24 -04002796 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797}
2798
2799static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2800{
David Howells88e67f32008-11-14 10:39:21 +11002801 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
Eric Paris2875fa02011-04-28 16:04:24 -04002803 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804}
2805
Al Viroe74f71e2011-06-20 19:38:15 -04002806static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
David Howells88e67f32008-11-14 10:39:21 +11002808 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002809 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002810 struct selinux_audit_data sad = {0,};
Eric Parisb782e0a2010-07-23 11:44:03 -04002811 u32 perms;
2812 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002813 unsigned flags = mask & MAY_NOT_BLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Eric Parisb782e0a2010-07-23 11:44:03 -04002815 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002816 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2817
Eric Parisb782e0a2010-07-23 11:44:03 -04002818 /* No permission to check. Existence test. */
2819 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
Eric Parisf48b7392011-04-25 12:54:27 -04002822 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002823 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002824 ad.u.inode = inode;
Eric Parisb782e0a2010-07-23 11:44:03 -04002825
2826 if (from_access)
Eric Paris3b3b0e42012-04-03 09:37:02 -07002827 ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
Eric Parisb782e0a2010-07-23 11:44:03 -04002828
2829 perms = file_mask_to_av(inode->i_mode, mask);
2830
Eric Paris9ade0cf2011-04-25 16:26:29 -04002831 return inode_has_perm(cred, inode, perms, &ad, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832}
2833
2834static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2835{
David Howells88e67f32008-11-14 10:39:21 +11002836 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002837 unsigned int ia_valid = iattr->ia_valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002839 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2840 if (ia_valid & ATTR_FORCE) {
2841 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2842 ATTR_FORCE);
2843 if (!ia_valid)
2844 return 0;
2845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002847 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2848 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002849 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
Eric Paris2875fa02011-04-28 16:04:24 -04002851 return dentry_has_perm(cred, dentry, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852}
2853
2854static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2855{
David Howells88e67f32008-11-14 10:39:21 +11002856 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002857 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002858
Eric Paris2875fa02011-04-28 16:04:24 -04002859 path.dentry = dentry;
2860 path.mnt = mnt;
2861
2862 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863}
2864
David Howells8f0cfa52008-04-29 00:59:41 -07002865static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002866{
David Howells88e67f32008-11-14 10:39:21 +11002867 const struct cred *cred = current_cred();
2868
Amir Samuelov6a22e462014-05-26 11:44:06 +03002869 if (pft_inode_set_xattr(dentry, name) < 0)
2870 return -EACCES;
2871
2872
Serge E. Hallynb5376772007-10-16 23:31:36 -07002873 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2874 sizeof XATTR_SECURITY_PREFIX - 1)) {
2875 if (!strcmp(name, XATTR_NAME_CAPS)) {
2876 if (!capable(CAP_SETFCAP))
2877 return -EPERM;
2878 } else if (!capable(CAP_SYS_ADMIN)) {
2879 /* A different attribute in the security namespace.
2880 Restrict to administrator. */
2881 return -EPERM;
2882 }
2883 }
2884
2885 /* Not an attribute we recognize, so just check the
2886 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002887 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002888}
2889
David Howells8f0cfa52008-04-29 00:59:41 -07002890static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2891 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 struct inode *inode = dentry->d_inode;
2894 struct inode_security_struct *isec = inode->i_security;
2895 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002896 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002897 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11002898 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 int rc = 0;
2900
Serge E. Hallynb5376772007-10-16 23:31:36 -07002901 if (strcmp(name, XATTR_NAME_SELINUX))
2902 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903
2904 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002905 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 return -EOPNOTSUPP;
2907
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002908 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 return -EPERM;
2910
Eric Parisa2694342011-04-25 13:10:27 -04002911 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002912 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002913 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
David Howells275bb412008-11-14 10:39:19 +11002915 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 FILE__RELABELFROM, &ad);
2917 if (rc)
2918 return rc;
2919
2920 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002921 if (rc == -EINVAL) {
2922 if (!capable(CAP_MAC_ADMIN))
2923 return rc;
2924 rc = security_context_to_sid_force(value, size, &newsid);
2925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 if (rc)
2927 return rc;
2928
David Howells275bb412008-11-14 10:39:19 +11002929 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 FILE__RELABELTO, &ad);
2931 if (rc)
2932 return rc;
2933
David Howells275bb412008-11-14 10:39:19 +11002934 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002935 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 if (rc)
2937 return rc;
2938
2939 return avc_has_perm(newsid,
2940 sbsec->sid,
2941 SECCLASS_FILESYSTEM,
2942 FILESYSTEM__ASSOCIATE,
2943 &ad);
2944}
2945
David Howells8f0cfa52008-04-29 00:59:41 -07002946static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002947 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002948 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949{
2950 struct inode *inode = dentry->d_inode;
2951 struct inode_security_struct *isec = inode->i_security;
2952 u32 newsid;
2953 int rc;
2954
2955 if (strcmp(name, XATTR_NAME_SELINUX)) {
2956 /* Not an attribute we recognize, so nothing to do. */
2957 return;
2958 }
2959
Stephen Smalley12b29f32008-05-07 13:03:20 -04002960 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002962 printk(KERN_ERR "SELinux: unable to map context to SID"
2963 "for (%s, %lu), rc=%d\n",
2964 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 return;
2966 }
2967
2968 isec->sid = newsid;
2969 return;
2970}
2971
David Howells8f0cfa52008-04-29 00:59:41 -07002972static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973{
David Howells88e67f32008-11-14 10:39:21 +11002974 const struct cred *cred = current_cred();
2975
Eric Paris2875fa02011-04-28 16:04:24 -04002976 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977}
2978
Eric Paris828dfe12008-04-17 13:17:49 -04002979static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980{
David Howells88e67f32008-11-14 10:39:21 +11002981 const struct cred *cred = current_cred();
2982
Eric Paris2875fa02011-04-28 16:04:24 -04002983 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984}
2985
David Howells8f0cfa52008-04-29 00:59:41 -07002986static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002988 if (strcmp(name, XATTR_NAME_SELINUX))
2989 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
2991 /* No one is allowed to remove a SELinux security label.
2992 You can change the label, but all data must be labeled. */
2993 return -EACCES;
2994}
2995
James Morrisd381d8a2005-10-30 14:59:22 -08002996/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002997 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002998 *
2999 * Permission check is handled by selinux_inode_getxattr hook.
3000 */
David P. Quigley42492592008-02-04 22:29:39 -08003001static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002{
David P. Quigley42492592008-02-04 22:29:39 -08003003 u32 size;
3004 int error;
3005 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003008 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3009 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003011 /*
3012 * If the caller has CAP_MAC_ADMIN, then get the raw context
3013 * value even if it is not defined by current policy; otherwise,
3014 * use the in-core value under current policy.
3015 * Use the non-auditing forms of the permission checks since
3016 * getxattr may be called by unprivileged processes commonly
3017 * and lack of permission just means that we fall back to the
3018 * in-core context value, not a denial.
3019 */
Eric Paris6a9de492012-01-03 12:25:14 -05003020 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00003021 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003022 if (!error)
3023 error = security_sid_to_context_force(isec->sid, &context,
3024 &size);
3025 else
3026 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003027 if (error)
3028 return error;
3029 error = size;
3030 if (alloc) {
3031 *buffer = context;
3032 goto out_nofree;
3033 }
3034 kfree(context);
3035out_nofree:
3036 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037}
3038
3039static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003040 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
3042 struct inode_security_struct *isec = inode->i_security;
3043 u32 newsid;
3044 int rc;
3045
3046 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3047 return -EOPNOTSUPP;
3048
3049 if (!value || !size)
3050 return -EACCES;
3051
Eric Paris828dfe12008-04-17 13:17:49 -04003052 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 if (rc)
3054 return rc;
3055
3056 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003057 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 return 0;
3059}
3060
3061static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3062{
3063 const int len = sizeof(XATTR_NAME_SELINUX);
3064 if (buffer && len <= buffer_size)
3065 memcpy(buffer, XATTR_NAME_SELINUX, len);
3066 return len;
3067}
3068
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003069static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3070{
3071 struct inode_security_struct *isec = inode->i_security;
3072 *secid = isec->sid;
3073}
3074
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075/* file security operations */
3076
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003077static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078{
David Howells88e67f32008-11-14 10:39:21 +11003079 const struct cred *cred = current_cred();
Josef Sipek3d5ff522006-12-08 02:37:38 -08003080 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3083 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3084 mask |= MAY_APPEND;
3085
Paul Moore389fb802009-03-27 17:10:34 -04003086 return file_has_perm(cred, file,
3087 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088}
3089
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003090static int selinux_file_permission(struct file *file, int mask)
3091{
Stephen Smalley20dda182009-06-22 14:54:53 -04003092 struct inode *inode = file->f_path.dentry->d_inode;
3093 struct file_security_struct *fsec = file->f_security;
3094 struct inode_security_struct *isec = inode->i_security;
3095 u32 sid = current_sid();
Amir Samuelov6a22e462014-05-26 11:44:06 +03003096 int ret;
Stephen Smalley20dda182009-06-22 14:54:53 -04003097
Paul Moore389fb802009-03-27 17:10:34 -04003098 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003099 /* No permission to check. Existence test. */
3100 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003101
Amir Samuelov6a22e462014-05-26 11:44:06 +03003102 ret = pft_file_permission(file, mask);
3103 if (ret < 0)
3104 return ret;
3105
Stephen Smalley20dda182009-06-22 14:54:53 -04003106 if (sid == fsec->sid && fsec->isid == isec->sid &&
3107 fsec->pseqno == avc_policy_seqno())
3108 /* No change since dentry_open check. */
3109 return 0;
3110
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003111 return selinux_revalidate_file_permission(file, mask);
3112}
3113
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114static int selinux_file_alloc_security(struct file *file)
3115{
3116 return file_alloc_security(file);
3117}
3118
3119static void selinux_file_free_security(struct file *file)
3120{
3121 file_free_security(file);
3122}
3123
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003124/*
3125 * Check whether a task has the ioctl permission and cmd
3126 * operation to an inode.
3127 */
3128int ioctl_has_perm(const struct cred *cred, struct file *file,
3129 u32 requested, u16 cmd)
3130{
3131 struct common_audit_data ad;
3132 struct file_security_struct *fsec = file->f_security;
3133 struct inode *inode = file->f_path.dentry->d_inode;
3134 struct inode_security_struct *isec = inode->i_security;
3135 struct lsm_ioctlop_audit ioctl;
3136 u32 ssid = cred_sid(cred);
3137 struct selinux_audit_data sad = {0,};
3138 int rc;
3139 u8 driver = cmd >> 8;
3140 u8 xperm = cmd & 0xff;
3141
3142 COMMON_AUDIT_DATA_INIT(&ad, IOCTL_OP);
3143 ad.u.op = &ioctl;
3144 ad.u.op->cmd = cmd;
3145 ad.selinux_audit_data = &sad;
3146 ad.u.op->path = file->f_path;
3147
3148 if (ssid != fsec->sid) {
3149 rc = avc_has_perm(ssid, fsec->sid,
3150 SECCLASS_FD,
3151 FD__USE,
3152 &ad);
3153 if (rc)
3154 goto out;
3155 }
3156
3157 if (unlikely(IS_PRIVATE(inode)))
3158 return 0;
3159
3160 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3161 requested, driver, xperm, &ad);
3162out:
3163 return rc;
3164}
3165
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3167 unsigned long arg)
3168{
David Howells88e67f32008-11-14 10:39:21 +11003169 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003170 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171
Eric Paris0b24dcb2011-02-25 15:39:20 -05003172 switch (cmd) {
3173 case FIONREAD:
3174 /* fall through */
3175 case FIBMAP:
3176 /* fall through */
3177 case FIGETBSZ:
3178 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003179 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003180 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003181 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003182 error = file_has_perm(cred, file, FILE__GETATTR);
3183 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Al Viro2f99c362012-03-23 16:04:05 -04003185 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003186 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003187 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003188 error = file_has_perm(cred, file, FILE__SETATTR);
3189 break;
3190
3191 /* sys_ioctl() checks */
3192 case FIONBIO:
3193 /* fall through */
3194 case FIOASYNC:
3195 error = file_has_perm(cred, file, 0);
3196 break;
3197
3198 case KDSKBENT:
3199 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003200 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3201 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003202 break;
3203
3204 /* default case assumes that the command will go
3205 * to the file's ioctl() function.
3206 */
3207 default:
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003208 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003209 }
3210 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211}
3212
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003213static int default_noexec;
3214
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3216{
David Howells88e67f32008-11-14 10:39:21 +11003217 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003218 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003219
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003220 if (default_noexec &&
3221 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 /*
3223 * We are making executable an anonymous mapping or a
3224 * private file mapping that will also be writable.
3225 * This has an additional check.
3226 */
David Howellsd84f4f92008-11-14 10:39:23 +11003227 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003229 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
3232 if (file) {
3233 /* read access is always possible with a mapping */
3234 u32 av = FILE__READ;
3235
3236 /* write access only matters if the mapping is shared */
3237 if (shared && (prot & PROT_WRITE))
3238 av |= FILE__WRITE;
3239
3240 if (prot & PROT_EXEC)
3241 av |= FILE__EXECUTE;
3242
David Howells88e67f32008-11-14 10:39:21 +11003243 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 }
David Howellsd84f4f92008-11-14 10:39:23 +11003245
3246error:
3247 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248}
3249
3250static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04003251 unsigned long prot, unsigned long flags,
3252 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253{
Eric Parised032182007-06-28 15:55:21 -04003254 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003255 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256
Eric Paris84336d1a2009-07-31 12:54:05 -04003257 /*
3258 * notice that we are intentionally putting the SELinux check before
3259 * the secondary cap_file_mmap check. This is such a likely attempt
3260 * at bad behaviour/exploit that we always want to get the AVC, even
3261 * if DAC would have also denied the operation.
3262 */
Eric Parisa2551df2009-07-31 12:54:11 -04003263 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003264 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3265 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003266 if (rc)
3267 return rc;
3268 }
3269
3270 /* do DAC check on address space usage */
3271 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
Eric Parised032182007-06-28 15:55:21 -04003272 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 return rc;
3274
3275 if (selinux_checkreqprot)
3276 prot = reqprot;
3277
3278 return file_map_prot_check(file, prot,
3279 (flags & MAP_TYPE) == MAP_SHARED);
3280}
3281
3282static int selinux_file_mprotect(struct vm_area_struct *vma,
3283 unsigned long reqprot,
3284 unsigned long prot)
3285{
David Howells88e67f32008-11-14 10:39:21 +11003286 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
3288 if (selinux_checkreqprot)
3289 prot = reqprot;
3290
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003291 if (default_noexec &&
3292 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003293 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003294 if (vma->vm_start >= vma->vm_mm->start_brk &&
3295 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003296 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003297 } else if (!vma->vm_file &&
3298 vma->vm_start <= vma->vm_mm->start_stack &&
3299 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003300 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003301 } else if (vma->vm_file && vma->anon_vma) {
3302 /*
3303 * We are making executable a file mapping that has
3304 * had some COW done. Since pages might have been
3305 * written, check ability to execute the possibly
3306 * modified content. This typically should only
3307 * occur for text relocations.
3308 */
David Howellsd84f4f92008-11-14 10:39:23 +11003309 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003310 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003311 if (rc)
3312 return rc;
3313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
3315 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3316}
3317
3318static int selinux_file_lock(struct file *file, unsigned int cmd)
3319{
David Howells88e67f32008-11-14 10:39:21 +11003320 const struct cred *cred = current_cred();
3321
3322 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323}
3324
3325static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3326 unsigned long arg)
3327{
David Howells88e67f32008-11-14 10:39:21 +11003328 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329 int err = 0;
3330
3331 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003332 case F_SETFL:
3333 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3334 err = -EINVAL;
3335 break;
3336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337
Eric Paris828dfe12008-04-17 13:17:49 -04003338 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003339 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003341 }
3342 /* fall through */
3343 case F_SETOWN:
3344 case F_SETSIG:
3345 case F_GETFL:
3346 case F_GETOWN:
3347 case F_GETSIG:
3348 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003349 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003350 break;
3351 case F_GETLK:
3352 case F_SETLK:
3353 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003355 case F_GETLK64:
3356 case F_SETLK64:
3357 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003359 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3360 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003362 }
David Howells88e67f32008-11-14 10:39:21 +11003363 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003364 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 }
3366
3367 return err;
3368}
3369
3370static int selinux_file_set_fowner(struct file *file)
3371{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 struct file_security_struct *fsec;
3373
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003375 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
3377 return 0;
3378}
3379
3380static int selinux_file_send_sigiotask(struct task_struct *tsk,
3381 struct fown_struct *fown, int signum)
3382{
Eric Paris828dfe12008-04-17 13:17:49 -04003383 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003384 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 struct file_security_struct *fsec;
3387
3388 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003389 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 fsec = file->f_security;
3392
3393 if (!signum)
3394 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3395 else
3396 perm = signal_to_av(signum);
3397
David Howells275bb412008-11-14 10:39:19 +11003398 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 SECCLASS_PROCESS, perm, NULL);
3400}
3401
3402static int selinux_file_receive(struct file *file)
3403{
David Howells88e67f32008-11-14 10:39:21 +11003404 const struct cred *cred = current_cred();
3405
3406 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407}
3408
David Howells745ca242008-11-14 10:39:22 +11003409static int selinux_dentry_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003410{
3411 struct file_security_struct *fsec;
3412 struct inode *inode;
3413 struct inode_security_struct *isec;
Amir Samuelov6a22e462014-05-26 11:44:06 +03003414 int ret;
3415
3416 ret = pft_file_open(file, cred);
3417 if (ret < 0)
3418 return ret;
David Howellsd84f4f92008-11-14 10:39:23 +11003419
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003420 inode = file->f_path.dentry->d_inode;
3421 fsec = file->f_security;
3422 isec = inode->i_security;
3423 /*
3424 * Save inode label and policy sequence number
3425 * at open-time so that selinux_file_permission
3426 * can determine whether revalidation is necessary.
3427 * Task label is already saved in the file security
3428 * struct as its SID.
3429 */
3430 fsec->isid = isec->sid;
3431 fsec->pseqno = avc_policy_seqno();
3432 /*
3433 * Since the inode label or policy seqno may have changed
3434 * between the selinux_inode_permission check and the saving
3435 * of state above, recheck that access is still permitted.
3436 * Otherwise, access might never be revalidated against the
3437 * new inode label or new policy.
3438 * This check is not redundant - do not remove.
3439 */
Linus Torvalds95f4efb2011-06-08 15:11:56 -07003440 return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003441}
3442
Amir Samuelov6a22e462014-05-26 11:44:06 +03003443static int selinux_file_close(struct file *file)
3444{
3445 return pft_file_close(file);
3446}
3447
3448static bool selinux_allow_merge_bio(struct bio *bio1, struct bio *bio2)
3449{
3450 return pft_allow_merge_bio(bio1, bio2);
3451}
3452
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453/* task security operations */
3454
3455static int selinux_task_create(unsigned long clone_flags)
3456{
David Howells3b11a1d2008-11-14 10:39:26 +11003457 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458}
3459
David Howellsf1752ee2008-11-14 10:39:17 +11003460/*
David Howellsee18d642009-09-02 09:14:21 +01003461 * allocate the SELinux part of blank credentials
3462 */
3463static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3464{
3465 struct task_security_struct *tsec;
3466
3467 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3468 if (!tsec)
3469 return -ENOMEM;
3470
3471 cred->security = tsec;
3472 return 0;
3473}
3474
3475/*
David Howellsf1752ee2008-11-14 10:39:17 +11003476 * detach and free the LSM part of a set of credentials
3477 */
3478static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479{
David Howellsf1752ee2008-11-14 10:39:17 +11003480 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003481
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003482 /*
3483 * cred->security == NULL if security_cred_alloc_blank() or
3484 * security_prepare_creds() returned an error.
3485 */
3486 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003487 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003488 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489}
3490
David Howellsd84f4f92008-11-14 10:39:23 +11003491/*
3492 * prepare a new set of credentials for modification
3493 */
3494static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3495 gfp_t gfp)
3496{
3497 const struct task_security_struct *old_tsec;
3498 struct task_security_struct *tsec;
3499
3500 old_tsec = old->security;
3501
3502 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3503 if (!tsec)
3504 return -ENOMEM;
3505
3506 new->security = tsec;
3507 return 0;
3508}
3509
3510/*
David Howellsee18d642009-09-02 09:14:21 +01003511 * transfer the SELinux data to a blank set of creds
3512 */
3513static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3514{
3515 const struct task_security_struct *old_tsec = old->security;
3516 struct task_security_struct *tsec = new->security;
3517
3518 *tsec = *old_tsec;
3519}
3520
3521/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003522 * set the security data for a kernel service
3523 * - all the creation contexts are set to unlabelled
3524 */
3525static int selinux_kernel_act_as(struct cred *new, u32 secid)
3526{
3527 struct task_security_struct *tsec = new->security;
3528 u32 sid = current_sid();
3529 int ret;
3530
3531 ret = avc_has_perm(sid, secid,
3532 SECCLASS_KERNEL_SERVICE,
3533 KERNEL_SERVICE__USE_AS_OVERRIDE,
3534 NULL);
3535 if (ret == 0) {
3536 tsec->sid = secid;
3537 tsec->create_sid = 0;
3538 tsec->keycreate_sid = 0;
3539 tsec->sockcreate_sid = 0;
3540 }
3541 return ret;
3542}
3543
3544/*
3545 * set the file creation context in a security record to the same as the
3546 * objective context of the specified inode
3547 */
3548static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3549{
3550 struct inode_security_struct *isec = inode->i_security;
3551 struct task_security_struct *tsec = new->security;
3552 u32 sid = current_sid();
3553 int ret;
3554
3555 ret = avc_has_perm(sid, isec->sid,
3556 SECCLASS_KERNEL_SERVICE,
3557 KERNEL_SERVICE__CREATE_FILES_AS,
3558 NULL);
3559
3560 if (ret == 0)
3561 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003562 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003563}
3564
Eric Parisdd8dbf22009-11-03 16:35:32 +11003565static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003566{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003567 u32 sid;
3568 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003569 struct selinux_audit_data sad = {0,};
Eric Parisdd8dbf22009-11-03 16:35:32 +11003570
3571 sid = task_sid(current);
3572
3573 COMMON_AUDIT_DATA_INIT(&ad, KMOD);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003574 ad.selinux_audit_data = &sad;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003575 ad.u.kmod_name = kmod_name;
3576
3577 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3578 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003579}
3580
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3582{
David Howells3b11a1d2008-11-14 10:39:26 +11003583 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584}
3585
3586static int selinux_task_getpgid(struct task_struct *p)
3587{
David Howells3b11a1d2008-11-14 10:39:26 +11003588 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589}
3590
3591static int selinux_task_getsid(struct task_struct *p)
3592{
David Howells3b11a1d2008-11-14 10:39:26 +11003593 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594}
3595
David Quigleyf9008e42006-06-30 01:55:46 -07003596static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3597{
David Howells275bb412008-11-14 10:39:19 +11003598 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003599}
3600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601static int selinux_task_setnice(struct task_struct *p, int nice)
3602{
3603 int rc;
3604
Eric Paris200ac532009-02-12 15:01:04 -05003605 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 if (rc)
3607 return rc;
3608
David Howells3b11a1d2008-11-14 10:39:26 +11003609 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610}
3611
James Morris03e68062006-06-23 02:03:58 -07003612static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3613{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003614 int rc;
3615
Eric Paris200ac532009-02-12 15:01:04 -05003616 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003617 if (rc)
3618 return rc;
3619
David Howells3b11a1d2008-11-14 10:39:26 +11003620 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003621}
3622
David Quigleya1836a42006-06-30 01:55:49 -07003623static int selinux_task_getioprio(struct task_struct *p)
3624{
David Howells3b11a1d2008-11-14 10:39:26 +11003625 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003626}
3627
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003628static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3629 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003631 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
3633 /* Control the ability to change the hard limit (whether
3634 lowering or raising it), so that the hard limit can
3635 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003636 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003638 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
3640 return 0;
3641}
3642
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003643static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003645 int rc;
3646
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003647 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003648 if (rc)
3649 return rc;
3650
David Howells3b11a1d2008-11-14 10:39:26 +11003651 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652}
3653
3654static int selinux_task_getscheduler(struct task_struct *p)
3655{
David Howells3b11a1d2008-11-14 10:39:26 +11003656 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657}
3658
David Quigley35601542006-06-23 02:04:01 -07003659static int selinux_task_movememory(struct task_struct *p)
3660{
David Howells3b11a1d2008-11-14 10:39:26 +11003661 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003662}
3663
David Quigleyf9008e42006-06-30 01:55:46 -07003664static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3665 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666{
3667 u32 perm;
3668 int rc;
3669
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 if (!sig)
3671 perm = PROCESS__SIGNULL; /* null signal; existence test */
3672 else
3673 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003674 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003675 rc = avc_has_perm(secid, task_sid(p),
3676 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003677 else
David Howells3b11a1d2008-11-14 10:39:26 +11003678 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003679 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680}
3681
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682static int selinux_task_wait(struct task_struct *p)
3683{
Eric Paris8a535142007-10-22 16:10:31 -04003684 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685}
3686
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687static void selinux_task_to_inode(struct task_struct *p,
3688 struct inode *inode)
3689{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003691 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
David Howells275bb412008-11-14 10:39:19 +11003693 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695}
3696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003698static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003699 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700{
3701 int offset, ihlen, ret = -EINVAL;
3702 struct iphdr _iph, *ih;
3703
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003704 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3706 if (ih == NULL)
3707 goto out;
3708
3709 ihlen = ih->ihl * 4;
3710 if (ihlen < sizeof(_iph))
3711 goto out;
3712
Eric Paris48c62af2012-04-02 13:15:44 -04003713 ad->u.net->v4info.saddr = ih->saddr;
3714 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 ret = 0;
3716
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003717 if (proto)
3718 *proto = ih->protocol;
3719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003721 case IPPROTO_TCP: {
3722 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Eric Paris828dfe12008-04-17 13:17:49 -04003724 if (ntohs(ih->frag_off) & IP_OFFSET)
3725 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726
3727 offset += ihlen;
3728 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3729 if (th == NULL)
3730 break;
3731
Eric Paris48c62af2012-04-02 13:15:44 -04003732 ad->u.net->sport = th->source;
3733 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003735 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
Eric Paris828dfe12008-04-17 13:17:49 -04003737 case IPPROTO_UDP: {
3738 struct udphdr _udph, *uh;
3739
3740 if (ntohs(ih->frag_off) & IP_OFFSET)
3741 break;
3742
3743 offset += ihlen;
3744 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3745 if (uh == NULL)
3746 break;
3747
Eric Paris48c62af2012-04-02 13:15:44 -04003748 ad->u.net->sport = uh->source;
3749 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003750 break;
3751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
James Morris2ee92d42006-11-13 16:09:01 -08003753 case IPPROTO_DCCP: {
3754 struct dccp_hdr _dccph, *dh;
3755
3756 if (ntohs(ih->frag_off) & IP_OFFSET)
3757 break;
3758
3759 offset += ihlen;
3760 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3761 if (dh == NULL)
3762 break;
3763
Eric Paris48c62af2012-04-02 13:15:44 -04003764 ad->u.net->sport = dh->dccph_sport;
3765 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003766 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003767 }
James Morris2ee92d42006-11-13 16:09:01 -08003768
Eric Paris828dfe12008-04-17 13:17:49 -04003769 default:
3770 break;
3771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772out:
3773 return ret;
3774}
3775
3776#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3777
3778/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003779static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003780 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781{
3782 u8 nexthdr;
3783 int ret = -EINVAL, offset;
3784 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003785 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003787 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3789 if (ip6 == NULL)
3790 goto out;
3791
Eric Paris48c62af2012-04-02 13:15:44 -04003792 ad->u.net->v6info.saddr = ip6->saddr;
3793 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 ret = 0;
3795
3796 nexthdr = ip6->nexthdr;
3797 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003798 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 if (offset < 0)
3800 goto out;
3801
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003802 if (proto)
3803 *proto = nexthdr;
3804
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 switch (nexthdr) {
3806 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003807 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
3809 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3810 if (th == NULL)
3811 break;
3812
Eric Paris48c62af2012-04-02 13:15:44 -04003813 ad->u.net->sport = th->source;
3814 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 break;
3816 }
3817
3818 case IPPROTO_UDP: {
3819 struct udphdr _udph, *uh;
3820
3821 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3822 if (uh == NULL)
3823 break;
3824
Eric Paris48c62af2012-04-02 13:15:44 -04003825 ad->u.net->sport = uh->source;
3826 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 break;
3828 }
3829
James Morris2ee92d42006-11-13 16:09:01 -08003830 case IPPROTO_DCCP: {
3831 struct dccp_hdr _dccph, *dh;
3832
3833 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3834 if (dh == NULL)
3835 break;
3836
Eric Paris48c62af2012-04-02 13:15:44 -04003837 ad->u.net->sport = dh->dccph_sport;
3838 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003839 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003840 }
James Morris2ee92d42006-11-13 16:09:01 -08003841
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 /* includes fragments */
3843 default:
3844 break;
3845 }
3846out:
3847 return ret;
3848}
3849
3850#endif /* IPV6 */
3851
Thomas Liu2bf49692009-07-14 12:14:09 -04003852static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003853 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854{
David Howellscf9481e2008-07-27 21:31:07 +10003855 char *addrp;
3856 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
Eric Paris48c62af2012-04-02 13:15:44 -04003858 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003860 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003861 if (ret)
3862 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003863 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3864 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003865 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
3867#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3868 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003869 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003870 if (ret)
3871 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003872 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3873 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003874 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875#endif /* IPV6 */
3876 default:
David Howellscf9481e2008-07-27 21:31:07 +10003877 addrp = NULL;
3878 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 }
3880
David Howellscf9481e2008-07-27 21:31:07 +10003881parse_error:
3882 printk(KERN_WARNING
3883 "SELinux: failure in selinux_parse_skb(),"
3884 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003886
3887okay:
3888 if (_addrp)
3889 *_addrp = addrp;
3890 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891}
3892
Paul Moore4f6a9932007-03-01 14:35:22 -05003893/**
Paul Moore220deb92008-01-29 08:38:23 -05003894 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003895 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003896 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003897 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003898 *
3899 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003900 * Check the various different forms of network peer labeling and determine
3901 * the peer label/SID for the packet; most of the magic actually occurs in
3902 * the security server function security_net_peersid_cmp(). The function
3903 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3904 * or -EACCES if @sid is invalid due to inconsistencies with the different
3905 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003906 *
3907 */
Paul Moore220deb92008-01-29 08:38:23 -05003908static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003909{
Paul Moore71f1cb02008-01-29 08:51:16 -05003910 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003911 u32 xfrm_sid;
3912 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003913 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003914
Paul Moorec09348c2013-12-10 14:57:54 -05003915 selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003916 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003917
Paul Moore71f1cb02008-01-29 08:51:16 -05003918 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3919 if (unlikely(err)) {
3920 printk(KERN_WARNING
3921 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3922 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003923 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003924 }
Paul Moore220deb92008-01-29 08:38:23 -05003925
3926 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003927}
3928
Paul Moore96d2c172013-12-04 16:10:51 -05003929/**
3930 * selinux_conn_sid - Determine the child socket label for a connection
3931 * @sk_sid: the parent socket's SID
3932 * @skb_sid: the packet's SID
3933 * @conn_sid: the resulting connection SID
3934 *
3935 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3936 * combined with the MLS information from @skb_sid in order to create
3937 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3938 * of @sk_sid. Returns zero on success, negative values on failure.
3939 *
3940 */
3941static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3942{
3943 int err = 0;
3944
3945 if (skb_sid != SECSID_NULL)
3946 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3947 else
3948 *conn_sid = sk_sid;
3949
3950 return err;
3951}
3952
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003954
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003955static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3956 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003957{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003958 if (tsec->sockcreate_sid > SECSID_NULL) {
3959 *socksid = tsec->sockcreate_sid;
3960 return 0;
3961 }
3962
3963 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3964 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003965}
3966
Paul Moore253bfae2010-04-22 14:46:19 -04003967static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968{
Paul Moore253bfae2010-04-22 14:46:19 -04003969 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003970 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003971 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04003972 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003973 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Satya Durga Srinivasu Prabhala90280652013-09-24 15:23:48 -07003975 if (unlikely(!sksec)) {
3976 pr_warn("SELinux: sksec is NULL, socket is already freed\n");
3977 return -EINVAL;
3978 }
3979
Paul Moore253bfae2010-04-22 14:46:19 -04003980 if (sksec->sid == SECINITSID_KERNEL)
3981 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Thomas Liu2bf49692009-07-14 12:14:09 -04003983 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003984 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04003985 ad.u.net = &net;
3986 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Paul Moore253bfae2010-04-22 14:46:19 -04003988 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989}
3990
3991static int selinux_socket_create(int family, int type,
3992 int protocol, int kern)
3993{
Paul Moore5fb49872010-04-22 14:46:19 -04003994 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003995 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003996 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003997 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
3999 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004000 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001
David Howells275bb412008-11-14 10:39:19 +11004002 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004003 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4004 if (rc)
4005 return rc;
4006
Paul Moored4f2d972010-04-22 14:46:18 -04004007 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008}
4009
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004010static int selinux_socket_post_create(struct socket *sock, int family,
4011 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012{
Paul Moore5fb49872010-04-22 14:46:19 -04004013 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004014 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004015 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004016 int err = 0;
4017
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004018 isec->sclass = socket_type_to_security_class(family, type, protocol);
4019
David Howells275bb412008-11-14 10:39:19 +11004020 if (kern)
4021 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004022 else {
4023 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4024 if (err)
4025 return err;
4026 }
David Howells275bb412008-11-14 10:39:19 +11004027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 isec->initialized = 1;
4029
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004030 if (sock->sk) {
4031 sksec = sock->sk->sk_security;
4032 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004033 sksec->sclass = isec->sclass;
Paul Moore389fb802009-03-27 17:10:34 -04004034 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004035 }
4036
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004037 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038}
4039
4040/* Range of port numbers used to automatically bind.
4041 Need to determine whether we should perform a name_bind
4042 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
4044static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4045{
Paul Moore253bfae2010-04-22 14:46:19 -04004046 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 u16 family;
4048 int err;
4049
Paul Moore253bfae2010-04-22 14:46:19 -04004050 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 if (err)
4052 goto out;
4053
4054 /*
4055 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004056 * Multiple address binding for SCTP is not supported yet: we just
4057 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 */
Paul Moore253bfae2010-04-22 14:46:19 -04004059 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (family == PF_INET || family == PF_INET6) {
4061 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004062 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004063 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004064 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004065 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 struct sockaddr_in *addr4 = NULL;
4067 struct sockaddr_in6 *addr6 = NULL;
4068 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004069 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 if (family == PF_INET) {
4072 addr4 = (struct sockaddr_in *)address;
4073 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 addrp = (char *)&addr4->sin_addr.s_addr;
4075 } else {
4076 addr6 = (struct sockaddr_in6 *)address;
4077 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 addrp = (char *)&addr6->sin6_addr.s6_addr;
4079 }
4080
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004081 if (snum) {
4082 int low, high;
4083
4084 inet_get_local_port_range(&low, &high);
4085
4086 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004087 err = sel_netport_sid(sk->sk_protocol,
4088 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004089 if (err)
4090 goto out;
Thomas Liu2bf49692009-07-14 12:14:09 -04004091 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004092 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004093 ad.u.net = &net;
4094 ad.u.net->sport = htons(snum);
4095 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004096 err = avc_has_perm(sksec->sid, sid,
4097 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004098 SOCKET__NAME_BIND, &ad);
4099 if (err)
4100 goto out;
4101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 }
Eric Paris828dfe12008-04-17 13:17:49 -04004103
Paul Moore253bfae2010-04-22 14:46:19 -04004104 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004105 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 node_perm = TCP_SOCKET__NODE_BIND;
4107 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004108
James Morris13402582005-09-30 14:24:34 -04004109 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 node_perm = UDP_SOCKET__NODE_BIND;
4111 break;
James Morris2ee92d42006-11-13 16:09:01 -08004112
4113 case SECCLASS_DCCP_SOCKET:
4114 node_perm = DCCP_SOCKET__NODE_BIND;
4115 break;
4116
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 default:
4118 node_perm = RAWIP_SOCKET__NODE_BIND;
4119 break;
4120 }
Eric Paris828dfe12008-04-17 13:17:49 -04004121
Paul Moore224dfbd2008-01-29 08:38:13 -05004122 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 if (err)
4124 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004125
Thomas Liu2bf49692009-07-14 12:14:09 -04004126 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004127 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004128 ad.u.net = &net;
4129 ad.u.net->sport = htons(snum);
4130 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
4132 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004133 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 else
Eric Paris48c62af2012-04-02 13:15:44 -04004135 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Paul Moore253bfae2010-04-22 14:46:19 -04004137 err = avc_has_perm(sksec->sid, sid,
4138 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 if (err)
4140 goto out;
4141 }
4142out:
4143 return err;
4144}
4145
4146static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4147{
Paul Moore014ab192008-10-10 10:16:33 -04004148 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004149 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 int err;
4151
Paul Moore253bfae2010-04-22 14:46:19 -04004152 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 if (err)
4154 return err;
4155
4156 /*
James Morris2ee92d42006-11-13 16:09:01 -08004157 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 */
Paul Moore253bfae2010-04-22 14:46:19 -04004159 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4160 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004161 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004162 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004163 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 struct sockaddr_in *addr4 = NULL;
4165 struct sockaddr_in6 *addr6 = NULL;
4166 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004167 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 if (sk->sk_family == PF_INET) {
4170 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004171 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 return -EINVAL;
4173 snum = ntohs(addr4->sin_port);
4174 } else {
4175 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004176 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 return -EINVAL;
4178 snum = ntohs(addr6->sin6_port);
4179 }
4180
Paul Moore3e112172008-04-10 10:48:14 -04004181 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 if (err)
4183 goto out;
4184
Paul Moore253bfae2010-04-22 14:46:19 -04004185 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004186 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4187
Thomas Liu2bf49692009-07-14 12:14:09 -04004188 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004189 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004190 ad.u.net = &net;
4191 ad.u.net->dport = htons(snum);
4192 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004193 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 if (err)
4195 goto out;
4196 }
4197
Paul Moore014ab192008-10-10 10:16:33 -04004198 err = selinux_netlbl_socket_connect(sk, address);
4199
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200out:
4201 return err;
4202}
4203
4204static int selinux_socket_listen(struct socket *sock, int backlog)
4205{
Paul Moore253bfae2010-04-22 14:46:19 -04004206 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207}
4208
4209static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4210{
4211 int err;
4212 struct inode_security_struct *isec;
4213 struct inode_security_struct *newisec;
4214
Paul Moore253bfae2010-04-22 14:46:19 -04004215 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216 if (err)
4217 return err;
4218
4219 newisec = SOCK_INODE(newsock)->i_security;
4220
4221 isec = SOCK_INODE(sock)->i_security;
4222 newisec->sclass = isec->sclass;
4223 newisec->sid = isec->sid;
4224 newisec->initialized = 1;
4225
4226 return 0;
4227}
4228
4229static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004230 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231{
Paul Moore253bfae2010-04-22 14:46:19 -04004232 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233}
4234
4235static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4236 int size, int flags)
4237{
Paul Moore253bfae2010-04-22 14:46:19 -04004238 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239}
4240
4241static int selinux_socket_getsockname(struct socket *sock)
4242{
Paul Moore253bfae2010-04-22 14:46:19 -04004243 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244}
4245
4246static int selinux_socket_getpeername(struct socket *sock)
4247{
Paul Moore253bfae2010-04-22 14:46:19 -04004248 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249}
4250
Eric Paris828dfe12008-04-17 13:17:49 -04004251static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252{
Paul Mooref8687af2006-10-30 15:22:15 -08004253 int err;
4254
Paul Moore253bfae2010-04-22 14:46:19 -04004255 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004256 if (err)
4257 return err;
4258
4259 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262static int selinux_socket_getsockopt(struct socket *sock, int level,
4263 int optname)
4264{
Paul Moore253bfae2010-04-22 14:46:19 -04004265 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266}
4267
4268static int selinux_socket_shutdown(struct socket *sock, int how)
4269{
Paul Moore253bfae2010-04-22 14:46:19 -04004270 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
David S. Miller3610cda2011-01-05 15:38:53 -08004273static int selinux_socket_unix_stream_connect(struct sock *sock,
4274 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 struct sock *newsk)
4276{
David S. Miller3610cda2011-01-05 15:38:53 -08004277 struct sk_security_struct *sksec_sock = sock->sk_security;
4278 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004279 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004280 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004281 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004282 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 int err;
4284
Thomas Liu2bf49692009-07-14 12:14:09 -04004285 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004286 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004287 ad.u.net = &net;
4288 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289
Paul Moore4d1e2452010-04-22 14:46:18 -04004290 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4291 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4293 if (err)
4294 return err;
4295
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004297 sksec_new->peer_sid = sksec_sock->sid;
4298 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4299 &sksec_new->sid);
4300 if (err)
4301 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004302
Paul Moore4d1e2452010-04-22 14:46:18 -04004303 /* connecting socket */
4304 sksec_sock->peer_sid = sksec_new->sid;
4305
4306 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307}
4308
4309static int selinux_socket_unix_may_send(struct socket *sock,
4310 struct socket *other)
4311{
Paul Moore253bfae2010-04-22 14:46:19 -04004312 struct sk_security_struct *ssec = sock->sk->sk_security;
4313 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004314 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004315 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004316 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Thomas Liu2bf49692009-07-14 12:14:09 -04004318 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004319 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004320 ad.u.net = &net;
4321 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Paul Moore253bfae2010-04-22 14:46:19 -04004323 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4324 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325}
4326
Paul Mooreeffad8d2008-01-29 08:49:27 -05004327static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4328 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004329 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004330{
4331 int err;
4332 u32 if_sid;
4333 u32 node_sid;
4334
4335 err = sel_netif_sid(ifindex, &if_sid);
4336 if (err)
4337 return err;
4338 err = avc_has_perm(peer_sid, if_sid,
4339 SECCLASS_NETIF, NETIF__INGRESS, ad);
4340 if (err)
4341 return err;
4342
4343 err = sel_netnode_sid(addrp, family, &node_sid);
4344 if (err)
4345 return err;
4346 return avc_has_perm(peer_sid, node_sid,
4347 SECCLASS_NODE, NODE__RECVFROM, ad);
4348}
4349
Paul Moore220deb92008-01-29 08:38:23 -05004350static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004351 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004352{
Paul Moore277d3422008-12-31 12:54:11 -05004353 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004354 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004355 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004356 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004357 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004358 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004359 char *addrp;
4360
Thomas Liu2bf49692009-07-14 12:14:09 -04004361 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004362 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004363 ad.u.net = &net;
4364 ad.u.net->netif = skb->skb_iif;
4365 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004366 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4367 if (err)
4368 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004369
Paul Moore58bfbb52009-03-27 17:10:41 -04004370 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004371 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004372 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004373 if (err)
4374 return err;
4375 }
Paul Moore220deb92008-01-29 08:38:23 -05004376
Steffen Klassertb9679a72011-02-23 12:55:21 +01004377 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4378 if (err)
4379 return err;
4380 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004381
James Morris4e5ab4c2006-06-09 00:33:33 -07004382 return err;
4383}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004384
James Morris4e5ab4c2006-06-09 00:33:33 -07004385static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4386{
Paul Moore220deb92008-01-29 08:38:23 -05004387 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004388 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004389 u16 family = sk->sk_family;
4390 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004391 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004392 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004393 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004394 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004395 u8 secmark_active;
4396 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004397
James Morris4e5ab4c2006-06-09 00:33:33 -07004398 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004399 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004400
4401 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004402 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004403 family = PF_INET;
4404
Paul Moored8395c82008-10-10 10:16:30 -04004405 /* If any sort of compatibility mode is enabled then handoff processing
4406 * to the selinux_sock_rcv_skb_compat() function to deal with the
4407 * special handling. We do this in an attempt to keep this function
4408 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004409 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004410 return selinux_sock_rcv_skb_compat(sk, skb, family);
4411
4412 secmark_active = selinux_secmark_enabled();
4413 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4414 if (!secmark_active && !peerlbl_active)
4415 return 0;
4416
Thomas Liu2bf49692009-07-14 12:14:09 -04004417 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004418 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004419 ad.u.net = &net;
4420 ad.u.net->netif = skb->skb_iif;
4421 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004422 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004423 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004424 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004425
Paul Moored8395c82008-10-10 10:16:30 -04004426 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004427 u32 peer_sid;
4428
4429 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4430 if (err)
4431 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004432 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004433 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004434 if (err) {
4435 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004436 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004437 }
Paul Moored621d352008-01-29 08:43:36 -05004438 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4439 PEER__RECV, &ad);
Chad Hanson619af682013-12-23 17:45:01 -05004440 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004441 selinux_netlbl_err(skb, err, 0);
Chad Hanson619af682013-12-23 17:45:01 -05004442 return err;
4443 }
Paul Moored621d352008-01-29 08:43:36 -05004444 }
4445
Paul Moored8395c82008-10-10 10:16:30 -04004446 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004447 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4448 PACKET__RECV, &ad);
4449 if (err)
4450 return err;
4451 }
4452
Paul Moored621d352008-01-29 08:43:36 -05004453 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454}
4455
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004456static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4457 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458{
4459 int err = 0;
4460 char *scontext;
4461 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004462 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004463 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Paul Moore253bfae2010-04-22 14:46:19 -04004465 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4466 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004467 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004468 if (peer_sid == SECSID_NULL)
4469 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004471 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004473 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474
4475 if (scontext_len > len) {
4476 err = -ERANGE;
4477 goto out_len;
4478 }
4479
4480 if (copy_to_user(optval, scontext, scontext_len))
4481 err = -EFAULT;
4482
4483out_len:
4484 if (put_user(scontext_len, optlen))
4485 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 return err;
4488}
4489
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004490static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004491{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004492 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004493 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004494
Paul Mooreaa862902008-10-10 10:16:29 -04004495 if (skb && skb->protocol == htons(ETH_P_IP))
4496 family = PF_INET;
4497 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4498 family = PF_INET6;
4499 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004500 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004501 else
4502 goto out;
4503
4504 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004505 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004506 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004507 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004508
Paul Moore75e22912008-01-29 08:38:04 -05004509out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004510 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004511 if (peer_secid == SECSID_NULL)
4512 return -EINVAL;
4513 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004514}
4515
Al Viro7d877f32005-10-21 03:20:43 -04004516static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517{
Paul Moore84914b72010-04-22 14:46:18 -04004518 struct sk_security_struct *sksec;
4519
4520 sksec = kzalloc(sizeof(*sksec), priority);
4521 if (!sksec)
4522 return -ENOMEM;
4523
4524 sksec->peer_sid = SECINITSID_UNLABELED;
4525 sksec->sid = SECINITSID_UNLABELED;
4526 selinux_netlbl_sk_security_reset(sksec);
4527 sk->sk_security = sksec;
4528
4529 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530}
4531
4532static void selinux_sk_free_security(struct sock *sk)
4533{
Paul Moore84914b72010-04-22 14:46:18 -04004534 struct sk_security_struct *sksec = sk->sk_security;
4535
4536 sk->sk_security = NULL;
4537 selinux_netlbl_sk_security_free(sksec);
4538 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539}
4540
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004541static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4542{
Eric Parisdd3e7832010-04-07 15:08:46 -04004543 struct sk_security_struct *sksec = sk->sk_security;
4544 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004545
Eric Parisdd3e7832010-04-07 15:08:46 -04004546 newsksec->sid = sksec->sid;
4547 newsksec->peer_sid = sksec->peer_sid;
4548 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004549
Eric Parisdd3e7832010-04-07 15:08:46 -04004550 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004551}
4552
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004553static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004554{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004555 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004556 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004557 else {
4558 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004559
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004560 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004561 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004562}
4563
Eric Paris828dfe12008-04-17 13:17:49 -04004564static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004565{
4566 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4567 struct sk_security_struct *sksec = sk->sk_security;
4568
David Woodhouse2148ccc2006-09-29 15:50:25 -07004569 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4570 sk->sk_family == PF_UNIX)
4571 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004572 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004573}
4574
Adrian Bunk9a673e52006-08-15 00:03:53 -07004575static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4576 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004577{
4578 struct sk_security_struct *sksec = sk->sk_security;
4579 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004580 u16 family = sk->sk_family;
Paul Moore96d2c172013-12-04 16:10:51 -05004581 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004582 u32 peersid;
4583
Paul Mooreaa862902008-10-10 10:16:29 -04004584 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4585 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4586 family = PF_INET;
4587
4588 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004589 if (err)
4590 return err;
Paul Moore96d2c172013-12-04 16:10:51 -05004591 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4592 if (err)
4593 return err;
4594 req->secid = connsid;
4595 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004596
Paul Moore389fb802009-03-27 17:10:34 -04004597 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004598}
4599
Adrian Bunk9a673e52006-08-15 00:03:53 -07004600static void selinux_inet_csk_clone(struct sock *newsk,
4601 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004602{
4603 struct sk_security_struct *newsksec = newsk->sk_security;
4604
4605 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004606 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004607 /* NOTE: Ideally, we should also get the isec->sid for the
4608 new socket in sync, but we don't have the isec available yet.
4609 So we will wait until sock_graft to do it, by which
4610 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004611
Paul Moore9f2ad662006-11-17 17:38:53 -05004612 /* We don't need to take any sort of lock here as we are the only
4613 * thread with access to newsksec */
Paul Moore389fb802009-03-27 17:10:34 -04004614 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004615}
4616
Paul Moore014ab192008-10-10 10:16:33 -04004617static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004618{
Paul Mooreaa862902008-10-10 10:16:29 -04004619 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004620 struct sk_security_struct *sksec = sk->sk_security;
4621
Paul Mooreaa862902008-10-10 10:16:29 -04004622 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4623 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4624 family = PF_INET;
4625
4626 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004627}
4628
Eric Paris2606fd12010-10-13 16:24:41 -04004629static int selinux_secmark_relabel_packet(u32 sid)
4630{
4631 const struct task_security_struct *__tsec;
4632 u32 tsid;
4633
4634 __tsec = current_security();
4635 tsid = __tsec->sid;
4636
4637 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4638}
4639
4640static void selinux_secmark_refcount_inc(void)
4641{
4642 atomic_inc(&selinux_secmark_refcount);
4643}
4644
4645static void selinux_secmark_refcount_dec(void)
4646{
4647 atomic_dec(&selinux_secmark_refcount);
4648}
4649
Adrian Bunk9a673e52006-08-15 00:03:53 -07004650static void selinux_req_classify_flow(const struct request_sock *req,
4651 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004652{
David S. Miller1d28f422011-03-12 00:29:39 -05004653 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004654}
4655
Paul Mooreed6d76e2009-08-28 18:12:49 -04004656static int selinux_tun_dev_create(void)
4657{
4658 u32 sid = current_sid();
4659
4660 /* we aren't taking into account the "sockcreate" SID since the socket
4661 * that is being created here is not a socket in the traditional sense,
4662 * instead it is a private sock, accessible only to the kernel, and
4663 * representing a wide range of network traffic spanning multiple
4664 * connections unlike traditional sockets - check the TUN driver to
4665 * get a better understanding of why this socket is special */
4666
4667 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4668 NULL);
4669}
4670
4671static void selinux_tun_dev_post_create(struct sock *sk)
4672{
4673 struct sk_security_struct *sksec = sk->sk_security;
4674
4675 /* we don't currently perform any NetLabel based labeling here and it
4676 * isn't clear that we would want to do so anyway; while we could apply
4677 * labeling without the support of the TUN user the resulting labeled
4678 * traffic from the other end of the connection would almost certainly
4679 * cause confusion to the TUN user that had no idea network labeling
4680 * protocols were being used */
4681
4682 /* see the comments in selinux_tun_dev_create() about why we don't use
4683 * the sockcreate SID here */
4684
4685 sksec->sid = current_sid();
4686 sksec->sclass = SECCLASS_TUN_SOCKET;
4687}
4688
4689static int selinux_tun_dev_attach(struct sock *sk)
4690{
4691 struct sk_security_struct *sksec = sk->sk_security;
4692 u32 sid = current_sid();
4693 int err;
4694
4695 err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
4696 TUN_SOCKET__RELABELFROM, NULL);
4697 if (err)
4698 return err;
4699 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4700 TUN_SOCKET__RELABELTO, NULL);
4701 if (err)
4702 return err;
4703
4704 sksec->sid = sid;
4705
4706 return 0;
4707}
4708
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4710{
4711 int err = 0;
4712 u32 perm;
4713 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004714 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004715
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716 if (skb->len < NLMSG_SPACE(0)) {
4717 err = -EINVAL;
4718 goto out;
4719 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004720 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004721
Paul Moore253bfae2010-04-22 14:46:19 -04004722 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723 if (err) {
4724 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004725 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 "SELinux: unrecognized netlink message"
4727 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004728 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004729 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004730 err = 0;
4731 }
4732
4733 /* Ignore */
4734 if (err == -ENOENT)
4735 err = 0;
4736 goto out;
4737 }
4738
Paul Moore253bfae2010-04-22 14:46:19 -04004739 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740out:
4741 return err;
4742}
4743
4744#ifdef CONFIG_NETFILTER
4745
Paul Mooreeffad8d2008-01-29 08:49:27 -05004746static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4747 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748{
Paul Mooredfaebe92008-10-10 10:16:31 -04004749 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004750 char *addrp;
4751 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004752 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004753 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004754 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004755 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004756 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004757 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004758
Paul Mooreeffad8d2008-01-29 08:49:27 -05004759 if (!selinux_policycap_netpeer)
4760 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004761
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004763 netlbl_active = netlbl_enabled();
4764 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004765 if (!secmark_active && !peerlbl_active)
4766 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004767
Paul Moored8395c82008-10-10 10:16:30 -04004768 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4769 return NF_DROP;
4770
Thomas Liu2bf49692009-07-14 12:14:09 -04004771 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004772 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004773 ad.u.net = &net;
4774 ad.u.net->netif = ifindex;
4775 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004776 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4777 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778
Paul Mooredfaebe92008-10-10 10:16:31 -04004779 if (peerlbl_active) {
4780 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4781 peer_sid, &ad);
4782 if (err) {
4783 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004784 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004785 }
4786 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004787
4788 if (secmark_active)
4789 if (avc_has_perm(peer_sid, skb->secmark,
4790 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4791 return NF_DROP;
4792
Paul Moore948bf852008-10-10 10:16:32 -04004793 if (netlbl_active)
4794 /* we do this in the FORWARD path and not the POST_ROUTING
4795 * path because we want to make sure we apply the necessary
4796 * labeling before IPsec is applied so we can leverage AH
4797 * protection */
4798 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4799 return NF_DROP;
4800
Paul Mooreeffad8d2008-01-29 08:49:27 -05004801 return NF_ACCEPT;
4802}
4803
4804static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4805 struct sk_buff *skb,
4806 const struct net_device *in,
4807 const struct net_device *out,
4808 int (*okfn)(struct sk_buff *))
4809{
4810 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4811}
4812
4813#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4814static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4815 struct sk_buff *skb,
4816 const struct net_device *in,
4817 const struct net_device *out,
4818 int (*okfn)(struct sk_buff *))
4819{
4820 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4821}
4822#endif /* IPV6 */
4823
Paul Moore948bf852008-10-10 10:16:32 -04004824static unsigned int selinux_ip_output(struct sk_buff *skb,
4825 u16 family)
4826{
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004827 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004828 u32 sid;
4829
4830 if (!netlbl_enabled())
4831 return NF_ACCEPT;
4832
4833 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4834 * because we want to make sure we apply the necessary labeling
4835 * before IPsec is applied so we can leverage AH protection */
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004836 sk = skb->sk;
4837 if (sk) {
4838 struct sk_security_struct *sksec;
4839
4840 if (sk->sk_state == TCP_LISTEN)
4841 /* if the socket is the listening state then this
4842 * packet is a SYN-ACK packet which means it needs to
4843 * be labeled based on the connection/request_sock and
4844 * not the parent socket. unfortunately, we can't
4845 * lookup the request_sock yet as it isn't queued on
4846 * the parent socket until after the SYN-ACK is sent.
4847 * the "solution" is to simply pass the packet as-is
4848 * as any IP option based labeling should be copied
4849 * from the initial connection request (in the IP
4850 * layer). it is far from ideal, but until we get a
4851 * security label in the packet itself this is the
4852 * best we can do. */
4853 return NF_ACCEPT;
4854
4855 /* standard practice, label using the parent socket */
4856 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004857 sid = sksec->sid;
4858 } else
4859 sid = SECINITSID_KERNEL;
4860 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4861 return NF_DROP;
4862
4863 return NF_ACCEPT;
4864}
4865
4866static unsigned int selinux_ipv4_output(unsigned int hooknum,
4867 struct sk_buff *skb,
4868 const struct net_device *in,
4869 const struct net_device *out,
4870 int (*okfn)(struct sk_buff *))
4871{
4872 return selinux_ip_output(skb, PF_INET);
4873}
4874
Paul Mooreeffad8d2008-01-29 08:49:27 -05004875static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4876 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004877 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004878{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004879 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004880 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004881 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004882 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004883 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004884 char *addrp;
4885 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004886
Paul Mooreeffad8d2008-01-29 08:49:27 -05004887 if (sk == NULL)
4888 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004889 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004890
Thomas Liu2bf49692009-07-14 12:14:09 -04004891 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004892 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004893 ad.u.net = &net;
4894 ad.u.net->netif = ifindex;
4895 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004896 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4897 return NF_DROP;
4898
Paul Moore58bfbb52009-03-27 17:10:41 -04004899 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004900 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004901 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004902 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004903
Steffen Klassertb9679a72011-02-23 12:55:21 +01004904 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4905 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004906
Paul Mooreeffad8d2008-01-29 08:49:27 -05004907 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908}
4909
Paul Mooreeffad8d2008-01-29 08:49:27 -05004910static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4911 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004913 u32 secmark_perm;
4914 u32 peer_sid;
4915 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004916 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004917 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004918 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004919 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004920 u8 secmark_active;
4921 u8 peerlbl_active;
4922
Paul Mooreeffad8d2008-01-29 08:49:27 -05004923 /* If any sort of compatibility mode is enabled then handoff processing
4924 * to the selinux_ip_postroute_compat() function to deal with the
4925 * special handling. We do this in an attempt to keep this function
4926 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004927 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004928 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004929#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004930 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4931 * packet transformation so allow the packet to pass without any checks
4932 * since we'll have another chance to perform access control checks
4933 * when the packet is on it's final way out.
4934 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4935 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004936 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004937 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004938#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004939 secmark_active = selinux_secmark_enabled();
4940 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4941 if (!secmark_active && !peerlbl_active)
4942 return NF_ACCEPT;
4943
Paul Mooreeffad8d2008-01-29 08:49:27 -05004944 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004945 if (sk == NULL) {
Paul Moore96d2c172013-12-04 16:10:51 -05004946 /* Without an associated socket the packet is either coming
4947 * from the kernel or it is being forwarded; check the packet
4948 * to determine which and if the packet is being forwarded
4949 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004950 if (skb->skb_iif) {
4951 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004952 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004953 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004954 } else {
4955 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004956 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004957 }
Paul Moore96d2c172013-12-04 16:10:51 -05004958 } else if (sk->sk_state == TCP_LISTEN) {
4959 /* Locally generated packet but the associated socket is in the
4960 * listening state which means this is a SYN-ACK packet. In
4961 * this particular case the correct security label is assigned
4962 * to the connection/request_sock but unfortunately we can't
4963 * query the request_sock as it isn't queued on the parent
4964 * socket until after the SYN-ACK packet is sent; the only
4965 * viable choice is to regenerate the label like we do in
4966 * selinux_inet_conn_request(). See also selinux_ip_output()
4967 * for similar problems. */
4968 u32 skb_sid;
4969 struct sk_security_struct *sksec = sk->sk_security;
4970 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4971 return NF_DROP;
4972 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4973 return NF_DROP;
4974 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004975 } else {
Paul Moore96d2c172013-12-04 16:10:51 -05004976 /* Locally generated packet, fetch the security label from the
4977 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004978 struct sk_security_struct *sksec = sk->sk_security;
4979 peer_sid = sksec->sid;
4980 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004981 }
4982
Thomas Liu2bf49692009-07-14 12:14:09 -04004983 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004984 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004985 ad.u.net = &net;
4986 ad.u.net->netif = ifindex;
4987 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004988 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004989 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004990
Paul Mooreeffad8d2008-01-29 08:49:27 -05004991 if (secmark_active)
4992 if (avc_has_perm(peer_sid, skb->secmark,
4993 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004994 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004995
4996 if (peerlbl_active) {
4997 u32 if_sid;
4998 u32 node_sid;
4999
5000 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005001 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005002 if (avc_has_perm(peer_sid, if_sid,
5003 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005004 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005005
5006 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005007 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005008 if (avc_has_perm(peer_sid, node_sid,
5009 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005010 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005011 }
5012
5013 return NF_ACCEPT;
5014}
5015
5016static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
5017 struct sk_buff *skb,
5018 const struct net_device *in,
5019 const struct net_device *out,
5020 int (*okfn)(struct sk_buff *))
5021{
5022 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023}
5024
5025#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005026static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
5027 struct sk_buff *skb,
5028 const struct net_device *in,
5029 const struct net_device *out,
5030 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005032 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034#endif /* IPV6 */
5035
5036#endif /* CONFIG_NETFILTER */
5037
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5039{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 int err;
5041
Eric Paris200ac532009-02-12 15:01:04 -05005042 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 if (err)
5044 return err;
5045
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005046 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047}
5048
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049static int ipc_alloc_security(struct task_struct *task,
5050 struct kern_ipc_perm *perm,
5051 u16 sclass)
5052{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005054 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
James Morris89d155e2005-10-30 14:59:21 -08005056 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057 if (!isec)
5058 return -ENOMEM;
5059
David Howells275bb412008-11-14 10:39:19 +11005060 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005062 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 perm->security = isec;
5064
5065 return 0;
5066}
5067
5068static void ipc_free_security(struct kern_ipc_perm *perm)
5069{
5070 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 perm->security = NULL;
5072 kfree(isec);
5073}
5074
5075static int msg_msg_alloc_security(struct msg_msg *msg)
5076{
5077 struct msg_security_struct *msec;
5078
James Morris89d155e2005-10-30 14:59:21 -08005079 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080 if (!msec)
5081 return -ENOMEM;
5082
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083 msec->sid = SECINITSID_UNLABELED;
5084 msg->security = msec;
5085
5086 return 0;
5087}
5088
5089static void msg_msg_free_security(struct msg_msg *msg)
5090{
5091 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092
5093 msg->security = NULL;
5094 kfree(msec);
5095}
5096
5097static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005098 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005101 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005102 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005103 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105 isec = ipc_perms->security;
5106
Thomas Liu2bf49692009-07-14 12:14:09 -04005107 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005108 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 ad.u.ipc_id = ipc_perms->key;
5110
David Howells275bb412008-11-14 10:39:19 +11005111 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112}
5113
5114static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5115{
5116 return msg_msg_alloc_security(msg);
5117}
5118
5119static void selinux_msg_msg_free_security(struct msg_msg *msg)
5120{
5121 msg_msg_free_security(msg);
5122}
5123
5124/* message queue security operations */
5125static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5126{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005128 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005129 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005130 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131 int rc;
5132
5133 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5134 if (rc)
5135 return rc;
5136
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137 isec = msq->q_perm.security;
5138
Thomas Liu2bf49692009-07-14 12:14:09 -04005139 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005140 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005141 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
David Howells275bb412008-11-14 10:39:19 +11005143 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144 MSGQ__CREATE, &ad);
5145 if (rc) {
5146 ipc_free_security(&msq->q_perm);
5147 return rc;
5148 }
5149 return 0;
5150}
5151
5152static void selinux_msg_queue_free_security(struct msg_queue *msq)
5153{
5154 ipc_free_security(&msq->q_perm);
5155}
5156
5157static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5158{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005160 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005161 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005162 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164 isec = msq->q_perm.security;
5165
Thomas Liu2bf49692009-07-14 12:14:09 -04005166 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005167 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168 ad.u.ipc_id = msq->q_perm.key;
5169
David Howells275bb412008-11-14 10:39:19 +11005170 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171 MSGQ__ASSOCIATE, &ad);
5172}
5173
5174static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5175{
5176 int err;
5177 int perms;
5178
Eric Paris828dfe12008-04-17 13:17:49 -04005179 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 case IPC_INFO:
5181 case MSG_INFO:
5182 /* No specific object, just general system-wide information. */
5183 return task_has_system(current, SYSTEM__IPC_INFO);
5184 case IPC_STAT:
5185 case MSG_STAT:
5186 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5187 break;
5188 case IPC_SET:
5189 perms = MSGQ__SETATTR;
5190 break;
5191 case IPC_RMID:
5192 perms = MSGQ__DESTROY;
5193 break;
5194 default:
5195 return 0;
5196 }
5197
Stephen Smalley6af963f2005-05-01 08:58:39 -07005198 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199 return err;
5200}
5201
5202static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5203{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 struct ipc_security_struct *isec;
5205 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005206 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005207 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005208 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 int rc;
5210
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211 isec = msq->q_perm.security;
5212 msec = msg->security;
5213
5214 /*
5215 * First time through, need to assign label to the message
5216 */
5217 if (msec->sid == SECINITSID_UNLABELED) {
5218 /*
5219 * Compute new sid based on current process and
5220 * message queue this message will be stored in
5221 */
David Howells275bb412008-11-14 10:39:19 +11005222 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005223 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 if (rc)
5225 return rc;
5226 }
5227
Thomas Liu2bf49692009-07-14 12:14:09 -04005228 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005229 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230 ad.u.ipc_id = msq->q_perm.key;
5231
5232 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005233 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234 MSGQ__WRITE, &ad);
5235 if (!rc)
5236 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005237 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5238 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 if (!rc)
5240 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005241 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5242 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005243
5244 return rc;
5245}
5246
5247static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5248 struct task_struct *target,
5249 long type, int mode)
5250{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 struct ipc_security_struct *isec;
5252 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005253 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005254 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005255 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 int rc;
5257
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 isec = msq->q_perm.security;
5259 msec = msg->security;
5260
Thomas Liu2bf49692009-07-14 12:14:09 -04005261 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005262 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005263 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264
David Howells275bb412008-11-14 10:39:19 +11005265 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 SECCLASS_MSGQ, MSGQ__READ, &ad);
5267 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005268 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 SECCLASS_MSG, MSG__RECEIVE, &ad);
5270 return rc;
5271}
5272
5273/* Shared Memory security operations */
5274static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5275{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005277 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005278 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005279 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 int rc;
5281
5282 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5283 if (rc)
5284 return rc;
5285
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286 isec = shp->shm_perm.security;
5287
Thomas Liu2bf49692009-07-14 12:14:09 -04005288 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005289 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005290 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291
David Howells275bb412008-11-14 10:39:19 +11005292 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293 SHM__CREATE, &ad);
5294 if (rc) {
5295 ipc_free_security(&shp->shm_perm);
5296 return rc;
5297 }
5298 return 0;
5299}
5300
5301static void selinux_shm_free_security(struct shmid_kernel *shp)
5302{
5303 ipc_free_security(&shp->shm_perm);
5304}
5305
5306static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5307{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005309 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005310 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005311 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313 isec = shp->shm_perm.security;
5314
Thomas Liu2bf49692009-07-14 12:14:09 -04005315 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005316 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317 ad.u.ipc_id = shp->shm_perm.key;
5318
David Howells275bb412008-11-14 10:39:19 +11005319 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320 SHM__ASSOCIATE, &ad);
5321}
5322
5323/* Note, at this point, shp is locked down */
5324static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5325{
5326 int perms;
5327 int err;
5328
Eric Paris828dfe12008-04-17 13:17:49 -04005329 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330 case IPC_INFO:
5331 case SHM_INFO:
5332 /* No specific object, just general system-wide information. */
5333 return task_has_system(current, SYSTEM__IPC_INFO);
5334 case IPC_STAT:
5335 case SHM_STAT:
5336 perms = SHM__GETATTR | SHM__ASSOCIATE;
5337 break;
5338 case IPC_SET:
5339 perms = SHM__SETATTR;
5340 break;
5341 case SHM_LOCK:
5342 case SHM_UNLOCK:
5343 perms = SHM__LOCK;
5344 break;
5345 case IPC_RMID:
5346 perms = SHM__DESTROY;
5347 break;
5348 default:
5349 return 0;
5350 }
5351
Stephen Smalley6af963f2005-05-01 08:58:39 -07005352 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353 return err;
5354}
5355
5356static int selinux_shm_shmat(struct shmid_kernel *shp,
5357 char __user *shmaddr, int shmflg)
5358{
5359 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005360
5361 if (shmflg & SHM_RDONLY)
5362 perms = SHM__READ;
5363 else
5364 perms = SHM__READ | SHM__WRITE;
5365
Stephen Smalley6af963f2005-05-01 08:58:39 -07005366 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367}
5368
5369/* Semaphore security operations */
5370static int selinux_sem_alloc_security(struct sem_array *sma)
5371{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005373 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005374 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005375 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 int rc;
5377
5378 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5379 if (rc)
5380 return rc;
5381
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 isec = sma->sem_perm.security;
5383
Thomas Liu2bf49692009-07-14 12:14:09 -04005384 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005385 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005386 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387
David Howells275bb412008-11-14 10:39:19 +11005388 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389 SEM__CREATE, &ad);
5390 if (rc) {
5391 ipc_free_security(&sma->sem_perm);
5392 return rc;
5393 }
5394 return 0;
5395}
5396
5397static void selinux_sem_free_security(struct sem_array *sma)
5398{
5399 ipc_free_security(&sma->sem_perm);
5400}
5401
5402static int selinux_sem_associate(struct sem_array *sma, int semflg)
5403{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005405 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005406 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005407 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409 isec = sma->sem_perm.security;
5410
Thomas Liu2bf49692009-07-14 12:14:09 -04005411 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005412 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413 ad.u.ipc_id = sma->sem_perm.key;
5414
David Howells275bb412008-11-14 10:39:19 +11005415 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416 SEM__ASSOCIATE, &ad);
5417}
5418
5419/* Note, at this point, sma is locked down */
5420static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5421{
5422 int err;
5423 u32 perms;
5424
Eric Paris828dfe12008-04-17 13:17:49 -04005425 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426 case IPC_INFO:
5427 case SEM_INFO:
5428 /* No specific object, just general system-wide information. */
5429 return task_has_system(current, SYSTEM__IPC_INFO);
5430 case GETPID:
5431 case GETNCNT:
5432 case GETZCNT:
5433 perms = SEM__GETATTR;
5434 break;
5435 case GETVAL:
5436 case GETALL:
5437 perms = SEM__READ;
5438 break;
5439 case SETVAL:
5440 case SETALL:
5441 perms = SEM__WRITE;
5442 break;
5443 case IPC_RMID:
5444 perms = SEM__DESTROY;
5445 break;
5446 case IPC_SET:
5447 perms = SEM__SETATTR;
5448 break;
5449 case IPC_STAT:
5450 case SEM_STAT:
5451 perms = SEM__GETATTR | SEM__ASSOCIATE;
5452 break;
5453 default:
5454 return 0;
5455 }
5456
Stephen Smalley6af963f2005-05-01 08:58:39 -07005457 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458 return err;
5459}
5460
5461static int selinux_sem_semop(struct sem_array *sma,
5462 struct sembuf *sops, unsigned nsops, int alter)
5463{
5464 u32 perms;
5465
5466 if (alter)
5467 perms = SEM__READ | SEM__WRITE;
5468 else
5469 perms = SEM__READ;
5470
Stephen Smalley6af963f2005-05-01 08:58:39 -07005471 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472}
5473
5474static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5475{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 u32 av = 0;
5477
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478 av = 0;
5479 if (flag & S_IRUGO)
5480 av |= IPC__UNIX_READ;
5481 if (flag & S_IWUGO)
5482 av |= IPC__UNIX_WRITE;
5483
5484 if (av == 0)
5485 return 0;
5486
Stephen Smalley6af963f2005-05-01 08:58:39 -07005487 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488}
5489
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005490static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5491{
5492 struct ipc_security_struct *isec = ipcp->security;
5493 *secid = isec->sid;
5494}
5495
Eric Paris828dfe12008-04-17 13:17:49 -04005496static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497{
5498 if (inode)
5499 inode_doinit_with_dentry(inode, dentry);
5500}
5501
5502static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005503 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504{
David Howells275bb412008-11-14 10:39:19 +11005505 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005506 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005508 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509
5510 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005511 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 if (error)
5513 return error;
5514 }
5515
David Howells275bb412008-11-14 10:39:19 +11005516 rcu_read_lock();
5517 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518
5519 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005520 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005522 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005524 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005526 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005527 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005528 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005529 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005530 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531 else
David Howells275bb412008-11-14 10:39:19 +11005532 goto invalid;
5533 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534
5535 if (!sid)
5536 return 0;
5537
Al Viro04ff9702007-03-12 16:17:58 +00005538 error = security_sid_to_context(sid, value, &len);
5539 if (error)
5540 return error;
5541 return len;
David Howells275bb412008-11-14 10:39:19 +11005542
5543invalid:
5544 rcu_read_unlock();
5545 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546}
5547
5548static int selinux_setprocattr(struct task_struct *p,
5549 char *name, void *value, size_t size)
5550{
5551 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005552 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005553 struct cred *new;
5554 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 int error;
5556 char *str = value;
5557
5558 if (current != p) {
5559 /* SELinux only allows a process to change its own
5560 security attributes. */
5561 return -EACCES;
5562 }
5563
5564 /*
5565 * Basic control over ability to set these attributes at all.
5566 * current == p, but we'll pass them separately in case the
5567 * above restriction is ever removed.
5568 */
5569 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005570 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005571 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005572 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005573 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005574 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005575 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005576 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005578 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579 else
5580 error = -EINVAL;
5581 if (error)
5582 return error;
5583
5584 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleye44b57e2017-01-31 11:54:04 -05005585 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 if (str[size-1] == '\n') {
5587 str[size-1] = 0;
5588 size--;
5589 }
5590 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005591 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5592 if (!capable(CAP_MAC_ADMIN))
5593 return error;
5594 error = security_context_to_sid_force(value, size,
5595 &sid);
5596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597 if (error)
5598 return error;
5599 }
5600
David Howellsd84f4f92008-11-14 10:39:23 +11005601 new = prepare_creds();
5602 if (!new)
5603 return -ENOMEM;
5604
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605 /* Permission checking based on the specified context is
5606 performed during the actual operation (execve,
5607 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005608 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 checks and may_create for the file creation checks. The
5610 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005611 tsec = new->security;
5612 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005614 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005616 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005617 error = may_create_key(sid, p);
5618 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005619 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005620 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005621 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005622 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005623 } else if (!strcmp(name, "current")) {
5624 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005626 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005627
David Howellsd84f4f92008-11-14 10:39:23 +11005628 /* Only allow single threaded processes to change context */
5629 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005630 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005631 error = security_bounded_transition(tsec->sid, sid);
5632 if (error)
5633 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
5636 /* Check permissions for the transition. */
5637 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005638 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005640 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641
5642 /* Check for ptracing, and update the task SID if ok.
5643 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005644 ptsid = 0;
Oleg Nesterovcdeb0b02013-12-23 17:45:01 -05005645 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005646 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005647 if (tracer)
5648 ptsid = task_sid(tracer);
Oleg Nesterovcdeb0b02013-12-23 17:45:01 -05005649 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650
David Howellsd84f4f92008-11-14 10:39:23 +11005651 if (tracer) {
5652 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5653 PROCESS__PTRACE, NULL);
5654 if (error)
5655 goto abort_change;
5656 }
5657
5658 tsec->sid = sid;
5659 } else {
5660 error = -EINVAL;
5661 goto abort_change;
5662 }
5663
5664 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005666
5667abort_change:
5668 abort_creds(new);
5669 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670}
5671
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005672static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5673{
5674 return security_sid_to_context(secid, secdata, seclen);
5675}
5676
David Howells7bf570d2008-04-29 20:52:51 +01005677static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005678{
5679 return security_context_to_sid(secdata, seclen, secid);
5680}
5681
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005682static void selinux_release_secctx(char *secdata, u32 seclen)
5683{
Paul Moore088999e2007-08-01 11:12:58 -04005684 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005685}
5686
David P. Quigley1ee65e32009-09-03 14:25:57 -04005687/*
5688 * called with inode->i_mutex locked
5689 */
5690static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5691{
5692 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5693}
5694
5695/*
5696 * called with inode->i_mutex locked
5697 */
5698static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5699{
5700 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5701}
5702
5703static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5704{
5705 int len = 0;
5706 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5707 ctx, true);
5708 if (len < 0)
5709 return len;
5710 *ctxlen = len;
5711 return 0;
5712}
Michael LeMayd7200242006-06-22 14:47:17 -07005713#ifdef CONFIG_KEYS
5714
David Howellsd84f4f92008-11-14 10:39:23 +11005715static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005716 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005717{
David Howellsd84f4f92008-11-14 10:39:23 +11005718 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005719 struct key_security_struct *ksec;
5720
5721 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5722 if (!ksec)
5723 return -ENOMEM;
5724
David Howellsd84f4f92008-11-14 10:39:23 +11005725 tsec = cred->security;
5726 if (tsec->keycreate_sid)
5727 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005728 else
David Howellsd84f4f92008-11-14 10:39:23 +11005729 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005730
David Howells275bb412008-11-14 10:39:19 +11005731 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005732 return 0;
5733}
5734
5735static void selinux_key_free(struct key *k)
5736{
5737 struct key_security_struct *ksec = k->security;
5738
5739 k->security = NULL;
5740 kfree(ksec);
5741}
5742
5743static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005744 const struct cred *cred,
5745 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005746{
5747 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005748 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005749 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005750
5751 /* if no specific permissions are requested, we skip the
5752 permission check. No serious, additional covert channels
5753 appear to be created. */
5754 if (perm == 0)
5755 return 0;
5756
David Howellsd84f4f92008-11-14 10:39:23 +11005757 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005758
5759 key = key_ref_to_ptr(key_ref);
5760 ksec = key->security;
5761
5762 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005763}
5764
David Howells70a5bb72008-04-29 01:01:26 -07005765static int selinux_key_getsecurity(struct key *key, char **_buffer)
5766{
5767 struct key_security_struct *ksec = key->security;
5768 char *context = NULL;
5769 unsigned len;
5770 int rc;
5771
5772 rc = security_sid_to_context(ksec->sid, &context, &len);
5773 if (!rc)
5774 rc = len;
5775 *_buffer = context;
5776 return rc;
5777}
5778
Michael LeMayd7200242006-06-22 14:47:17 -07005779#endif
5780
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005782 .name = "selinux",
5783
Stephen Smalley48a23702012-11-05 08:15:34 -05005784 .binder_set_context_mgr = selinux_binder_set_context_mgr,
5785 .binder_transaction = selinux_binder_transaction,
5786 .binder_transfer_binder = selinux_binder_transfer_binder,
5787 .binder_transfer_file = selinux_binder_transfer_file,
5788
Ingo Molnar9e488582009-05-07 19:26:19 +10005789 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005790 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005792 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793 .capable = selinux_capable,
5794 .quotactl = selinux_quotactl,
5795 .quota_on = selinux_quota_on,
5796 .syslog = selinux_syslog,
5797 .vm_enough_memory = selinux_vm_enough_memory,
5798
5799 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800
David Howellsa6f76f22008-11-14 10:39:24 +11005801 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005802 .bprm_committing_creds = selinux_bprm_committing_creds,
5803 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804 .bprm_secureexec = selinux_bprm_secureexec,
5805
5806 .sb_alloc_security = selinux_sb_alloc_security,
5807 .sb_free_security = selinux_sb_free_security,
5808 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005809 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005810 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005811 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812 .sb_statfs = selinux_sb_statfs,
5813 .sb_mount = selinux_mount,
5814 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005815 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005816 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005817 .sb_parse_opts_str = selinux_parse_opts_str,
5818
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
5820 .inode_alloc_security = selinux_inode_alloc_security,
5821 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005822 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823 .inode_create = selinux_inode_create,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005824 .inode_post_create = selinux_inode_post_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005825 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 .inode_unlink = selinux_inode_unlink,
5827 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005828 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829 .inode_rmdir = selinux_inode_rmdir,
5830 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005831 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832 .inode_readlink = selinux_inode_readlink,
5833 .inode_follow_link = selinux_inode_follow_link,
5834 .inode_permission = selinux_inode_permission,
5835 .inode_setattr = selinux_inode_setattr,
5836 .inode_getattr = selinux_inode_getattr,
5837 .inode_setxattr = selinux_inode_setxattr,
5838 .inode_post_setxattr = selinux_inode_post_setxattr,
5839 .inode_getxattr = selinux_inode_getxattr,
5840 .inode_listxattr = selinux_inode_listxattr,
5841 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005842 .inode_getsecurity = selinux_inode_getsecurity,
5843 .inode_setsecurity = selinux_inode_setsecurity,
5844 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005845 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846
5847 .file_permission = selinux_file_permission,
5848 .file_alloc_security = selinux_file_alloc_security,
5849 .file_free_security = selinux_file_free_security,
5850 .file_ioctl = selinux_file_ioctl,
5851 .file_mmap = selinux_file_mmap,
5852 .file_mprotect = selinux_file_mprotect,
5853 .file_lock = selinux_file_lock,
5854 .file_fcntl = selinux_file_fcntl,
5855 .file_set_fowner = selinux_file_set_fowner,
5856 .file_send_sigiotask = selinux_file_send_sigiotask,
5857 .file_receive = selinux_file_receive,
5858
Eric Paris828dfe12008-04-17 13:17:49 -04005859 .dentry_open = selinux_dentry_open,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005860 .file_close = selinux_file_close,
5861 .allow_merge_bio = selinux_allow_merge_bio,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005862
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005864 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005865 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005866 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005867 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005868 .kernel_act_as = selinux_kernel_act_as,
5869 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005870 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871 .task_setpgid = selinux_task_setpgid,
5872 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005873 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005874 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005876 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005877 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878 .task_setrlimit = selinux_task_setrlimit,
5879 .task_setscheduler = selinux_task_setscheduler,
5880 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005881 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882 .task_kill = selinux_task_kill,
5883 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005884 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885
5886 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005887 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
5889 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5890 .msg_msg_free_security = selinux_msg_msg_free_security,
5891
5892 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5893 .msg_queue_free_security = selinux_msg_queue_free_security,
5894 .msg_queue_associate = selinux_msg_queue_associate,
5895 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5896 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5897 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5898
5899 .shm_alloc_security = selinux_shm_alloc_security,
5900 .shm_free_security = selinux_shm_free_security,
5901 .shm_associate = selinux_shm_associate,
5902 .shm_shmctl = selinux_shm_shmctl,
5903 .shm_shmat = selinux_shm_shmat,
5904
Eric Paris828dfe12008-04-17 13:17:49 -04005905 .sem_alloc_security = selinux_sem_alloc_security,
5906 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907 .sem_associate = selinux_sem_associate,
5908 .sem_semctl = selinux_sem_semctl,
5909 .sem_semop = selinux_sem_semop,
5910
Eric Paris828dfe12008-04-17 13:17:49 -04005911 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Eric Paris828dfe12008-04-17 13:17:49 -04005913 .getprocattr = selinux_getprocattr,
5914 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005916 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005917 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005918 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005919 .inode_notifysecctx = selinux_inode_notifysecctx,
5920 .inode_setsecctx = selinux_inode_setsecctx,
5921 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005922
Eric Paris828dfe12008-04-17 13:17:49 -04005923 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924 .unix_may_send = selinux_socket_unix_may_send,
5925
5926 .socket_create = selinux_socket_create,
5927 .socket_post_create = selinux_socket_post_create,
5928 .socket_bind = selinux_socket_bind,
5929 .socket_connect = selinux_socket_connect,
5930 .socket_listen = selinux_socket_listen,
5931 .socket_accept = selinux_socket_accept,
5932 .socket_sendmsg = selinux_socket_sendmsg,
5933 .socket_recvmsg = selinux_socket_recvmsg,
5934 .socket_getsockname = selinux_socket_getsockname,
5935 .socket_getpeername = selinux_socket_getpeername,
5936 .socket_getsockopt = selinux_socket_getsockopt,
5937 .socket_setsockopt = selinux_socket_setsockopt,
5938 .socket_shutdown = selinux_socket_shutdown,
5939 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005940 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5941 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 .sk_alloc_security = selinux_sk_alloc_security,
5943 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005944 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005945 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005946 .sock_graft = selinux_sock_graft,
5947 .inet_conn_request = selinux_inet_conn_request,
5948 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005949 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005950 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5951 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5952 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005953 .req_classify_flow = selinux_req_classify_flow,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005954 .tun_dev_create = selinux_tun_dev_create,
5955 .tun_dev_post_create = selinux_tun_dev_post_create,
5956 .tun_dev_attach = selinux_tun_dev_attach,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005957
5958#ifdef CONFIG_SECURITY_NETWORK_XFRM
5959 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5960 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5961 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005962 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005963 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5964 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005965 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005966 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005967 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005968 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005970
5971#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005972 .key_alloc = selinux_key_alloc,
5973 .key_free = selinux_key_free,
5974 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005975 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005976#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005977
5978#ifdef CONFIG_AUDIT
5979 .audit_rule_init = selinux_audit_rule_init,
5980 .audit_rule_known = selinux_audit_rule_known,
5981 .audit_rule_match = selinux_audit_rule_match,
5982 .audit_rule_free = selinux_audit_rule_free,
5983#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984};
5985
5986static __init int selinux_init(void)
5987{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005988 if (!security_module_enable(&selinux_ops)) {
5989 selinux_enabled = 0;
5990 return 0;
5991 }
5992
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993 if (!selinux_enabled) {
5994 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5995 return 0;
5996 }
5997
5998 printk(KERN_INFO "SELinux: Initializing.\n");
5999
6000 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006001 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006003 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6004
James Morris7cae7e22006-03-22 00:09:22 -08006005 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6006 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006007 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008 avc_init();
6009
Eric Paris828dfe12008-04-17 13:17:49 -04006010 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011 panic("SELinux: Unable to register with kernel.\n");
6012
Eric Paris828dfe12008-04-17 13:17:49 -04006013 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006014 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006015 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006016 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006017
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 return 0;
6019}
6020
Al Viroe8c26252010-03-23 06:36:54 -04006021static void delayed_superblock_init(struct super_block *sb, void *unused)
6022{
6023 superblock_doinit(sb, NULL);
6024}
6025
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026void selinux_complete_init(void)
6027{
Eric Parisfadcdb42007-02-22 18:11:31 -05006028 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029
6030 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006031 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006032 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033}
6034
6035/* SELinux requires early initialization in order to label
6036 all processes and objects when they are created. */
6037security_initcall(selinux_init);
6038
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006039#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Paul Mooreeffad8d2008-01-29 08:49:27 -05006041static struct nf_hook_ops selinux_ipv4_ops[] = {
6042 {
6043 .hook = selinux_ipv4_postroute,
6044 .owner = THIS_MODULE,
6045 .pf = PF_INET,
6046 .hooknum = NF_INET_POST_ROUTING,
6047 .priority = NF_IP_PRI_SELINUX_LAST,
6048 },
6049 {
6050 .hook = selinux_ipv4_forward,
6051 .owner = THIS_MODULE,
6052 .pf = PF_INET,
6053 .hooknum = NF_INET_FORWARD,
6054 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006055 },
6056 {
6057 .hook = selinux_ipv4_output,
6058 .owner = THIS_MODULE,
6059 .pf = PF_INET,
6060 .hooknum = NF_INET_LOCAL_OUT,
6061 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063};
6064
6065#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
6066
Paul Mooreeffad8d2008-01-29 08:49:27 -05006067static struct nf_hook_ops selinux_ipv6_ops[] = {
6068 {
6069 .hook = selinux_ipv6_postroute,
6070 .owner = THIS_MODULE,
6071 .pf = PF_INET6,
6072 .hooknum = NF_INET_POST_ROUTING,
6073 .priority = NF_IP6_PRI_SELINUX_LAST,
6074 },
6075 {
6076 .hook = selinux_ipv6_forward,
6077 .owner = THIS_MODULE,
6078 .pf = PF_INET6,
6079 .hooknum = NF_INET_FORWARD,
6080 .priority = NF_IP6_PRI_SELINUX_FIRST,
6081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082};
6083
6084#endif /* IPV6 */
6085
6086static int __init selinux_nf_ip_init(void)
6087{
6088 int err = 0;
6089
6090 if (!selinux_enabled)
6091 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05006092
6093 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6094
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006095 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
6096 if (err)
6097 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098
6099#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006100 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
6101 if (err)
6102 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006104
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105out:
6106 return err;
6107}
6108
6109__initcall(selinux_nf_ip_init);
6110
6111#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6112static void selinux_nf_ip_exit(void)
6113{
Eric Parisfadcdb42007-02-22 18:11:31 -05006114 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006116 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006118 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119#endif /* IPV6 */
6120}
6121#endif
6122
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006123#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124
6125#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6126#define selinux_nf_ip_exit()
6127#endif
6128
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006129#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130
6131#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006132static int selinux_disabled;
6133
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134int selinux_disable(void)
6135{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136 if (ss_initialized) {
6137 /* Not permitted after initial policy load. */
6138 return -EINVAL;
6139 }
6140
6141 if (selinux_disabled) {
6142 /* Only do this once. */
6143 return -EINVAL;
6144 }
6145
6146 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6147
6148 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006149 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006151 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152
Eric Parisaf8ff042009-09-20 21:23:01 -04006153 /* Try to destroy the avc node cache */
6154 avc_disable();
6155
Linus Torvalds1da177e2005-04-16 15:20:36 -07006156 /* Unregister netfilter hooks. */
6157 selinux_nf_ip_exit();
6158
6159 /* Unregister selinuxfs. */
6160 exit_sel_fs();
6161
6162 return 0;
6163}
6164#endif