blob: 87266619b1dd7b7bad1a5639e4754bd1a59fe355 [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
3915 selinux_skb_xfrm_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
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003930
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003931static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3932 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003933{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003934 if (tsec->sockcreate_sid > SECSID_NULL) {
3935 *socksid = tsec->sockcreate_sid;
3936 return 0;
3937 }
3938
3939 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3940 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003941}
3942
Paul Moore253bfae2010-04-22 14:46:19 -04003943static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944{
Paul Moore253bfae2010-04-22 14:46:19 -04003945 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003946 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003947 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04003948 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003949 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Satya Durga Srinivasu Prabhala90280652013-09-24 15:23:48 -07003951 if (unlikely(!sksec)) {
3952 pr_warn("SELinux: sksec is NULL, socket is already freed\n");
3953 return -EINVAL;
3954 }
3955
Paul Moore253bfae2010-04-22 14:46:19 -04003956 if (sksec->sid == SECINITSID_KERNEL)
3957 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
Thomas Liu2bf49692009-07-14 12:14:09 -04003959 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003960 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04003961 ad.u.net = &net;
3962 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
Paul Moore253bfae2010-04-22 14:46:19 -04003964 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965}
3966
3967static int selinux_socket_create(int family, int type,
3968 int protocol, int kern)
3969{
Paul Moore5fb49872010-04-22 14:46:19 -04003970 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003971 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003972 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003973 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
3975 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
David Howells275bb412008-11-14 10:39:19 +11003978 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003979 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3980 if (rc)
3981 return rc;
3982
Paul Moored4f2d972010-04-22 14:46:18 -04003983 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984}
3985
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003986static int selinux_socket_post_create(struct socket *sock, int family,
3987 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988{
Paul Moore5fb49872010-04-22 14:46:19 -04003989 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003990 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003991 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003992 int err = 0;
3993
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003994 isec->sclass = socket_type_to_security_class(family, type, protocol);
3995
David Howells275bb412008-11-14 10:39:19 +11003996 if (kern)
3997 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003998 else {
3999 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4000 if (err)
4001 return err;
4002 }
David Howells275bb412008-11-14 10:39:19 +11004003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 isec->initialized = 1;
4005
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004006 if (sock->sk) {
4007 sksec = sock->sk->sk_security;
4008 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004009 sksec->sclass = isec->sclass;
Paul Moore389fb802009-03-27 17:10:34 -04004010 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004011 }
4012
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004013 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014}
4015
4016/* Range of port numbers used to automatically bind.
4017 Need to determine whether we should perform a name_bind
4018 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4021{
Paul Moore253bfae2010-04-22 14:46:19 -04004022 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 u16 family;
4024 int err;
4025
Paul Moore253bfae2010-04-22 14:46:19 -04004026 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 if (err)
4028 goto out;
4029
4030 /*
4031 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004032 * Multiple address binding for SCTP is not supported yet: we just
4033 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 */
Paul Moore253bfae2010-04-22 14:46:19 -04004035 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 if (family == PF_INET || family == PF_INET6) {
4037 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004038 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004039 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004040 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004041 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 struct sockaddr_in *addr4 = NULL;
4043 struct sockaddr_in6 *addr6 = NULL;
4044 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004045 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 if (family == PF_INET) {
4048 addr4 = (struct sockaddr_in *)address;
4049 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 addrp = (char *)&addr4->sin_addr.s_addr;
4051 } else {
4052 addr6 = (struct sockaddr_in6 *)address;
4053 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 addrp = (char *)&addr6->sin6_addr.s6_addr;
4055 }
4056
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004057 if (snum) {
4058 int low, high;
4059
4060 inet_get_local_port_range(&low, &high);
4061
4062 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004063 err = sel_netport_sid(sk->sk_protocol,
4064 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004065 if (err)
4066 goto out;
Thomas Liu2bf49692009-07-14 12:14:09 -04004067 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004068 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004069 ad.u.net = &net;
4070 ad.u.net->sport = htons(snum);
4071 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004072 err = avc_has_perm(sksec->sid, sid,
4073 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004074 SOCKET__NAME_BIND, &ad);
4075 if (err)
4076 goto out;
4077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 }
Eric Paris828dfe12008-04-17 13:17:49 -04004079
Paul Moore253bfae2010-04-22 14:46:19 -04004080 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004081 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 node_perm = TCP_SOCKET__NODE_BIND;
4083 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004084
James Morris13402582005-09-30 14:24:34 -04004085 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 node_perm = UDP_SOCKET__NODE_BIND;
4087 break;
James Morris2ee92d42006-11-13 16:09:01 -08004088
4089 case SECCLASS_DCCP_SOCKET:
4090 node_perm = DCCP_SOCKET__NODE_BIND;
4091 break;
4092
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 default:
4094 node_perm = RAWIP_SOCKET__NODE_BIND;
4095 break;
4096 }
Eric Paris828dfe12008-04-17 13:17:49 -04004097
Paul Moore224dfbd2008-01-29 08:38:13 -05004098 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 if (err)
4100 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004101
Thomas Liu2bf49692009-07-14 12:14:09 -04004102 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004103 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004104 ad.u.net = &net;
4105 ad.u.net->sport = htons(snum);
4106 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
4108 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004109 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 else
Eric Paris48c62af2012-04-02 13:15:44 -04004111 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Paul Moore253bfae2010-04-22 14:46:19 -04004113 err = avc_has_perm(sksec->sid, sid,
4114 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 if (err)
4116 goto out;
4117 }
4118out:
4119 return err;
4120}
4121
4122static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4123{
Paul Moore014ab192008-10-10 10:16:33 -04004124 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004125 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 int err;
4127
Paul Moore253bfae2010-04-22 14:46:19 -04004128 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 if (err)
4130 return err;
4131
4132 /*
James Morris2ee92d42006-11-13 16:09:01 -08004133 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 */
Paul Moore253bfae2010-04-22 14:46:19 -04004135 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4136 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004137 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004138 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004139 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140 struct sockaddr_in *addr4 = NULL;
4141 struct sockaddr_in6 *addr6 = NULL;
4142 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004143 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
4145 if (sk->sk_family == PF_INET) {
4146 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004147 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 return -EINVAL;
4149 snum = ntohs(addr4->sin_port);
4150 } else {
4151 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004152 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 return -EINVAL;
4154 snum = ntohs(addr6->sin6_port);
4155 }
4156
Paul Moore3e112172008-04-10 10:48:14 -04004157 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 if (err)
4159 goto out;
4160
Paul Moore253bfae2010-04-22 14:46:19 -04004161 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004162 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4163
Thomas Liu2bf49692009-07-14 12:14:09 -04004164 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004165 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004166 ad.u.net = &net;
4167 ad.u.net->dport = htons(snum);
4168 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004169 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 if (err)
4171 goto out;
4172 }
4173
Paul Moore014ab192008-10-10 10:16:33 -04004174 err = selinux_netlbl_socket_connect(sk, address);
4175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176out:
4177 return err;
4178}
4179
4180static int selinux_socket_listen(struct socket *sock, int backlog)
4181{
Paul Moore253bfae2010-04-22 14:46:19 -04004182 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183}
4184
4185static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4186{
4187 int err;
4188 struct inode_security_struct *isec;
4189 struct inode_security_struct *newisec;
4190
Paul Moore253bfae2010-04-22 14:46:19 -04004191 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 if (err)
4193 return err;
4194
4195 newisec = SOCK_INODE(newsock)->i_security;
4196
4197 isec = SOCK_INODE(sock)->i_security;
4198 newisec->sclass = isec->sclass;
4199 newisec->sid = isec->sid;
4200 newisec->initialized = 1;
4201
4202 return 0;
4203}
4204
4205static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004206 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207{
Paul Moore253bfae2010-04-22 14:46:19 -04004208 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209}
4210
4211static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4212 int size, int flags)
4213{
Paul Moore253bfae2010-04-22 14:46:19 -04004214 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215}
4216
4217static int selinux_socket_getsockname(struct socket *sock)
4218{
Paul Moore253bfae2010-04-22 14:46:19 -04004219 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220}
4221
4222static int selinux_socket_getpeername(struct socket *sock)
4223{
Paul Moore253bfae2010-04-22 14:46:19 -04004224 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225}
4226
Eric Paris828dfe12008-04-17 13:17:49 -04004227static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228{
Paul Mooref8687af2006-10-30 15:22:15 -08004229 int err;
4230
Paul Moore253bfae2010-04-22 14:46:19 -04004231 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004232 if (err)
4233 return err;
4234
4235 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236}
4237
4238static int selinux_socket_getsockopt(struct socket *sock, int level,
4239 int optname)
4240{
Paul Moore253bfae2010-04-22 14:46:19 -04004241 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242}
4243
4244static int selinux_socket_shutdown(struct socket *sock, int how)
4245{
Paul Moore253bfae2010-04-22 14:46:19 -04004246 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247}
4248
David S. Miller3610cda2011-01-05 15:38:53 -08004249static int selinux_socket_unix_stream_connect(struct sock *sock,
4250 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 struct sock *newsk)
4252{
David S. Miller3610cda2011-01-05 15:38:53 -08004253 struct sk_security_struct *sksec_sock = sock->sk_security;
4254 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004255 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004256 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004257 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004258 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 int err;
4260
Thomas Liu2bf49692009-07-14 12:14:09 -04004261 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004262 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004263 ad.u.net = &net;
4264 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
Paul Moore4d1e2452010-04-22 14:46:18 -04004266 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4267 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4269 if (err)
4270 return err;
4271
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004273 sksec_new->peer_sid = sksec_sock->sid;
4274 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4275 &sksec_new->sid);
4276 if (err)
4277 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004278
Paul Moore4d1e2452010-04-22 14:46:18 -04004279 /* connecting socket */
4280 sksec_sock->peer_sid = sksec_new->sid;
4281
4282 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283}
4284
4285static int selinux_socket_unix_may_send(struct socket *sock,
4286 struct socket *other)
4287{
Paul Moore253bfae2010-04-22 14:46:19 -04004288 struct sk_security_struct *ssec = sock->sk->sk_security;
4289 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004290 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004291 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004292 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Thomas Liu2bf49692009-07-14 12:14:09 -04004294 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004295 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004296 ad.u.net = &net;
4297 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Paul Moore253bfae2010-04-22 14:46:19 -04004299 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4300 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301}
4302
Paul Mooreeffad8d2008-01-29 08:49:27 -05004303static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4304 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004305 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004306{
4307 int err;
4308 u32 if_sid;
4309 u32 node_sid;
4310
4311 err = sel_netif_sid(ifindex, &if_sid);
4312 if (err)
4313 return err;
4314 err = avc_has_perm(peer_sid, if_sid,
4315 SECCLASS_NETIF, NETIF__INGRESS, ad);
4316 if (err)
4317 return err;
4318
4319 err = sel_netnode_sid(addrp, family, &node_sid);
4320 if (err)
4321 return err;
4322 return avc_has_perm(peer_sid, node_sid,
4323 SECCLASS_NODE, NODE__RECVFROM, ad);
4324}
4325
Paul Moore220deb92008-01-29 08:38:23 -05004326static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004327 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004328{
Paul Moore277d3422008-12-31 12:54:11 -05004329 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004330 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004331 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004332 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004333 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004334 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004335 char *addrp;
4336
Thomas Liu2bf49692009-07-14 12:14:09 -04004337 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004338 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004339 ad.u.net = &net;
4340 ad.u.net->netif = skb->skb_iif;
4341 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004342 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4343 if (err)
4344 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004345
Paul Moore58bfbb52009-03-27 17:10:41 -04004346 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004347 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004348 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004349 if (err)
4350 return err;
4351 }
Paul Moore220deb92008-01-29 08:38:23 -05004352
Steffen Klassertb9679a72011-02-23 12:55:21 +01004353 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4354 if (err)
4355 return err;
4356 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004357
James Morris4e5ab4c2006-06-09 00:33:33 -07004358 return err;
4359}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004360
James Morris4e5ab4c2006-06-09 00:33:33 -07004361static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4362{
Paul Moore220deb92008-01-29 08:38:23 -05004363 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004364 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004365 u16 family = sk->sk_family;
4366 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004367 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004368 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004369 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004370 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004371 u8 secmark_active;
4372 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004373
James Morris4e5ab4c2006-06-09 00:33:33 -07004374 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004375 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004376
4377 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004378 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004379 family = PF_INET;
4380
Paul Moored8395c82008-10-10 10:16:30 -04004381 /* If any sort of compatibility mode is enabled then handoff processing
4382 * to the selinux_sock_rcv_skb_compat() function to deal with the
4383 * special handling. We do this in an attempt to keep this function
4384 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004385 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004386 return selinux_sock_rcv_skb_compat(sk, skb, family);
4387
4388 secmark_active = selinux_secmark_enabled();
4389 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4390 if (!secmark_active && !peerlbl_active)
4391 return 0;
4392
Thomas Liu2bf49692009-07-14 12:14:09 -04004393 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004394 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004395 ad.u.net = &net;
4396 ad.u.net->netif = skb->skb_iif;
4397 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004398 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004399 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004400 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004401
Paul Moored8395c82008-10-10 10:16:30 -04004402 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004403 u32 peer_sid;
4404
4405 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4406 if (err)
4407 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004408 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004409 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004410 if (err) {
4411 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004412 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004413 }
Paul Moored621d352008-01-29 08:43:36 -05004414 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4415 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004416 if (err)
4417 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004418 }
4419
Paul Moored8395c82008-10-10 10:16:30 -04004420 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004421 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4422 PACKET__RECV, &ad);
4423 if (err)
4424 return err;
4425 }
4426
Paul Moored621d352008-01-29 08:43:36 -05004427 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428}
4429
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004430static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4431 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432{
4433 int err = 0;
4434 char *scontext;
4435 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004436 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004437 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Paul Moore253bfae2010-04-22 14:46:19 -04004439 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4440 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004441 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004442 if (peer_sid == SECSID_NULL)
4443 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004445 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004447 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
4449 if (scontext_len > len) {
4450 err = -ERANGE;
4451 goto out_len;
4452 }
4453
4454 if (copy_to_user(optval, scontext, scontext_len))
4455 err = -EFAULT;
4456
4457out_len:
4458 if (put_user(scontext_len, optlen))
4459 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 return err;
4462}
4463
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004464static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004465{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004466 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004467 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004468
Paul Mooreaa862902008-10-10 10:16:29 -04004469 if (skb && skb->protocol == htons(ETH_P_IP))
4470 family = PF_INET;
4471 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4472 family = PF_INET6;
4473 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004474 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004475 else
4476 goto out;
4477
4478 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004479 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004480 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004481 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004482
Paul Moore75e22912008-01-29 08:38:04 -05004483out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004484 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004485 if (peer_secid == SECSID_NULL)
4486 return -EINVAL;
4487 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004488}
4489
Al Viro7d877f32005-10-21 03:20:43 -04004490static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491{
Paul Moore84914b72010-04-22 14:46:18 -04004492 struct sk_security_struct *sksec;
4493
4494 sksec = kzalloc(sizeof(*sksec), priority);
4495 if (!sksec)
4496 return -ENOMEM;
4497
4498 sksec->peer_sid = SECINITSID_UNLABELED;
4499 sksec->sid = SECINITSID_UNLABELED;
4500 selinux_netlbl_sk_security_reset(sksec);
4501 sk->sk_security = sksec;
4502
4503 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504}
4505
4506static void selinux_sk_free_security(struct sock *sk)
4507{
Paul Moore84914b72010-04-22 14:46:18 -04004508 struct sk_security_struct *sksec = sk->sk_security;
4509
4510 sk->sk_security = NULL;
4511 selinux_netlbl_sk_security_free(sksec);
4512 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513}
4514
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004515static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4516{
Eric Parisdd3e7832010-04-07 15:08:46 -04004517 struct sk_security_struct *sksec = sk->sk_security;
4518 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004519
Eric Parisdd3e7832010-04-07 15:08:46 -04004520 newsksec->sid = sksec->sid;
4521 newsksec->peer_sid = sksec->peer_sid;
4522 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004523
Eric Parisdd3e7832010-04-07 15:08:46 -04004524 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004525}
4526
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004527static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004528{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004529 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004530 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004531 else {
4532 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004533
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004534 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004535 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004536}
4537
Eric Paris828dfe12008-04-17 13:17:49 -04004538static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004539{
4540 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4541 struct sk_security_struct *sksec = sk->sk_security;
4542
David Woodhouse2148ccc2006-09-29 15:50:25 -07004543 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4544 sk->sk_family == PF_UNIX)
4545 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004546 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004547}
4548
Adrian Bunk9a673e52006-08-15 00:03:53 -07004549static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4550 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004551{
4552 struct sk_security_struct *sksec = sk->sk_security;
4553 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004554 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004555 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004556 u32 peersid;
4557
Paul Mooreaa862902008-10-10 10:16:29 -04004558 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4559 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4560 family = PF_INET;
4561
4562 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004563 if (err)
4564 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004565 if (peersid == SECSID_NULL) {
4566 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004567 req->peer_secid = SECSID_NULL;
Paul Moore389fb802009-03-27 17:10:34 -04004568 } else {
4569 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4570 if (err)
4571 return err;
4572 req->secid = newsid;
4573 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004574 }
4575
Paul Moore389fb802009-03-27 17:10:34 -04004576 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004577}
4578
Adrian Bunk9a673e52006-08-15 00:03:53 -07004579static void selinux_inet_csk_clone(struct sock *newsk,
4580 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581{
4582 struct sk_security_struct *newsksec = newsk->sk_security;
4583
4584 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004585 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004586 /* NOTE: Ideally, we should also get the isec->sid for the
4587 new socket in sync, but we don't have the isec available yet.
4588 So we will wait until sock_graft to do it, by which
4589 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004590
Paul Moore9f2ad662006-11-17 17:38:53 -05004591 /* We don't need to take any sort of lock here as we are the only
4592 * thread with access to newsksec */
Paul Moore389fb802009-03-27 17:10:34 -04004593 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004594}
4595
Paul Moore014ab192008-10-10 10:16:33 -04004596static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004597{
Paul Mooreaa862902008-10-10 10:16:29 -04004598 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004599 struct sk_security_struct *sksec = sk->sk_security;
4600
Paul Mooreaa862902008-10-10 10:16:29 -04004601 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4602 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4603 family = PF_INET;
4604
4605 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004606}
4607
Eric Paris2606fd12010-10-13 16:24:41 -04004608static int selinux_secmark_relabel_packet(u32 sid)
4609{
4610 const struct task_security_struct *__tsec;
4611 u32 tsid;
4612
4613 __tsec = current_security();
4614 tsid = __tsec->sid;
4615
4616 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4617}
4618
4619static void selinux_secmark_refcount_inc(void)
4620{
4621 atomic_inc(&selinux_secmark_refcount);
4622}
4623
4624static void selinux_secmark_refcount_dec(void)
4625{
4626 atomic_dec(&selinux_secmark_refcount);
4627}
4628
Adrian Bunk9a673e52006-08-15 00:03:53 -07004629static void selinux_req_classify_flow(const struct request_sock *req,
4630 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004631{
David S. Miller1d28f422011-03-12 00:29:39 -05004632 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004633}
4634
Paul Mooreed6d76e2009-08-28 18:12:49 -04004635static int selinux_tun_dev_create(void)
4636{
4637 u32 sid = current_sid();
4638
4639 /* we aren't taking into account the "sockcreate" SID since the socket
4640 * that is being created here is not a socket in the traditional sense,
4641 * instead it is a private sock, accessible only to the kernel, and
4642 * representing a wide range of network traffic spanning multiple
4643 * connections unlike traditional sockets - check the TUN driver to
4644 * get a better understanding of why this socket is special */
4645
4646 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4647 NULL);
4648}
4649
4650static void selinux_tun_dev_post_create(struct sock *sk)
4651{
4652 struct sk_security_struct *sksec = sk->sk_security;
4653
4654 /* we don't currently perform any NetLabel based labeling here and it
4655 * isn't clear that we would want to do so anyway; while we could apply
4656 * labeling without the support of the TUN user the resulting labeled
4657 * traffic from the other end of the connection would almost certainly
4658 * cause confusion to the TUN user that had no idea network labeling
4659 * protocols were being used */
4660
4661 /* see the comments in selinux_tun_dev_create() about why we don't use
4662 * the sockcreate SID here */
4663
4664 sksec->sid = current_sid();
4665 sksec->sclass = SECCLASS_TUN_SOCKET;
4666}
4667
4668static int selinux_tun_dev_attach(struct sock *sk)
4669{
4670 struct sk_security_struct *sksec = sk->sk_security;
4671 u32 sid = current_sid();
4672 int err;
4673
4674 err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
4675 TUN_SOCKET__RELABELFROM, NULL);
4676 if (err)
4677 return err;
4678 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4679 TUN_SOCKET__RELABELTO, NULL);
4680 if (err)
4681 return err;
4682
4683 sksec->sid = sid;
4684
4685 return 0;
4686}
4687
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4689{
4690 int err = 0;
4691 u32 perm;
4692 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004693 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004694
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695 if (skb->len < NLMSG_SPACE(0)) {
4696 err = -EINVAL;
4697 goto out;
4698 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004699 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004700
Paul Moore253bfae2010-04-22 14:46:19 -04004701 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702 if (err) {
4703 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004704 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705 "SELinux: unrecognized netlink message"
4706 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004707 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004708 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709 err = 0;
4710 }
4711
4712 /* Ignore */
4713 if (err == -ENOENT)
4714 err = 0;
4715 goto out;
4716 }
4717
Paul Moore253bfae2010-04-22 14:46:19 -04004718 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719out:
4720 return err;
4721}
4722
4723#ifdef CONFIG_NETFILTER
4724
Paul Mooreeffad8d2008-01-29 08:49:27 -05004725static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4726 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727{
Paul Mooredfaebe92008-10-10 10:16:31 -04004728 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004729 char *addrp;
4730 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004731 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004732 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004733 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004734 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004735 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004736 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004737
Paul Mooreeffad8d2008-01-29 08:49:27 -05004738 if (!selinux_policycap_netpeer)
4739 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004740
Paul Mooreeffad8d2008-01-29 08:49:27 -05004741 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004742 netlbl_active = netlbl_enabled();
4743 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004744 if (!secmark_active && !peerlbl_active)
4745 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004746
Paul Moored8395c82008-10-10 10:16:30 -04004747 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4748 return NF_DROP;
4749
Thomas Liu2bf49692009-07-14 12:14:09 -04004750 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004751 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004752 ad.u.net = &net;
4753 ad.u.net->netif = ifindex;
4754 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004755 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4756 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757
Paul Mooredfaebe92008-10-10 10:16:31 -04004758 if (peerlbl_active) {
4759 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4760 peer_sid, &ad);
4761 if (err) {
4762 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004763 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004764 }
4765 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004766
4767 if (secmark_active)
4768 if (avc_has_perm(peer_sid, skb->secmark,
4769 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4770 return NF_DROP;
4771
Paul Moore948bf852008-10-10 10:16:32 -04004772 if (netlbl_active)
4773 /* we do this in the FORWARD path and not the POST_ROUTING
4774 * path because we want to make sure we apply the necessary
4775 * labeling before IPsec is applied so we can leverage AH
4776 * protection */
4777 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4778 return NF_DROP;
4779
Paul Mooreeffad8d2008-01-29 08:49:27 -05004780 return NF_ACCEPT;
4781}
4782
4783static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4784 struct sk_buff *skb,
4785 const struct net_device *in,
4786 const struct net_device *out,
4787 int (*okfn)(struct sk_buff *))
4788{
4789 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4790}
4791
4792#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4793static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4794 struct sk_buff *skb,
4795 const struct net_device *in,
4796 const struct net_device *out,
4797 int (*okfn)(struct sk_buff *))
4798{
4799 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4800}
4801#endif /* IPV6 */
4802
Paul Moore948bf852008-10-10 10:16:32 -04004803static unsigned int selinux_ip_output(struct sk_buff *skb,
4804 u16 family)
4805{
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004806 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004807 u32 sid;
4808
4809 if (!netlbl_enabled())
4810 return NF_ACCEPT;
4811
4812 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4813 * because we want to make sure we apply the necessary labeling
4814 * before IPsec is applied so we can leverage AH protection */
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004815 sk = skb->sk;
4816 if (sk) {
4817 struct sk_security_struct *sksec;
4818
4819 if (sk->sk_state == TCP_LISTEN)
4820 /* if the socket is the listening state then this
4821 * packet is a SYN-ACK packet which means it needs to
4822 * be labeled based on the connection/request_sock and
4823 * not the parent socket. unfortunately, we can't
4824 * lookup the request_sock yet as it isn't queued on
4825 * the parent socket until after the SYN-ACK is sent.
4826 * the "solution" is to simply pass the packet as-is
4827 * as any IP option based labeling should be copied
4828 * from the initial connection request (in the IP
4829 * layer). it is far from ideal, but until we get a
4830 * security label in the packet itself this is the
4831 * best we can do. */
4832 return NF_ACCEPT;
4833
4834 /* standard practice, label using the parent socket */
4835 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004836 sid = sksec->sid;
4837 } else
4838 sid = SECINITSID_KERNEL;
4839 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4840 return NF_DROP;
4841
4842 return NF_ACCEPT;
4843}
4844
4845static unsigned int selinux_ipv4_output(unsigned int hooknum,
4846 struct sk_buff *skb,
4847 const struct net_device *in,
4848 const struct net_device *out,
4849 int (*okfn)(struct sk_buff *))
4850{
4851 return selinux_ip_output(skb, PF_INET);
4852}
4853
Paul Mooreeffad8d2008-01-29 08:49:27 -05004854static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4855 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004856 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004857{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004858 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004859 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004860 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004861 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004862 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004863 char *addrp;
4864 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004865
Paul Mooreeffad8d2008-01-29 08:49:27 -05004866 if (sk == NULL)
4867 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004868 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004869
Thomas Liu2bf49692009-07-14 12:14:09 -04004870 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004871 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004872 ad.u.net = &net;
4873 ad.u.net->netif = ifindex;
4874 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004875 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4876 return NF_DROP;
4877
Paul Moore58bfbb52009-03-27 17:10:41 -04004878 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004879 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004880 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004881 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004882
Steffen Klassertb9679a72011-02-23 12:55:21 +01004883 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4884 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004885
Paul Mooreeffad8d2008-01-29 08:49:27 -05004886 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004887}
4888
Paul Mooreeffad8d2008-01-29 08:49:27 -05004889static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4890 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004892 u32 secmark_perm;
4893 u32 peer_sid;
4894 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004895 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004896 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004897 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004898 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004899 u8 secmark_active;
4900 u8 peerlbl_active;
4901
Paul Mooreeffad8d2008-01-29 08:49:27 -05004902 /* If any sort of compatibility mode is enabled then handoff processing
4903 * to the selinux_ip_postroute_compat() function to deal with the
4904 * special handling. We do this in an attempt to keep this function
4905 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004906 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004907 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004908#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004909 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4910 * packet transformation so allow the packet to pass without any checks
4911 * since we'll have another chance to perform access control checks
4912 * when the packet is on it's final way out.
4913 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4914 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004915 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004916 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004917#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004918 secmark_active = selinux_secmark_enabled();
4919 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4920 if (!secmark_active && !peerlbl_active)
4921 return NF_ACCEPT;
4922
Paul Moored8395c82008-10-10 10:16:30 -04004923 /* if the packet is being forwarded then get the peer label from the
4924 * packet itself; otherwise check to see if it is from a local
4925 * application or the kernel, if from an application get the peer label
4926 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004927 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004928 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004929 if (skb->skb_iif) {
4930 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004931 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004932 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004933 } else {
4934 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004935 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004936 }
Paul Moored8395c82008-10-10 10:16:30 -04004937 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004938 struct sk_security_struct *sksec = sk->sk_security;
4939 peer_sid = sksec->sid;
4940 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004941 }
4942
Thomas Liu2bf49692009-07-14 12:14:09 -04004943 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004944 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004945 ad.u.net = &net;
4946 ad.u.net->netif = ifindex;
4947 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004948 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004949 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004950
Paul Mooreeffad8d2008-01-29 08:49:27 -05004951 if (secmark_active)
4952 if (avc_has_perm(peer_sid, skb->secmark,
4953 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004954 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004955
4956 if (peerlbl_active) {
4957 u32 if_sid;
4958 u32 node_sid;
4959
4960 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004961 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004962 if (avc_has_perm(peer_sid, if_sid,
4963 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004964 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004965
4966 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004967 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004968 if (avc_has_perm(peer_sid, node_sid,
4969 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004970 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004971 }
4972
4973 return NF_ACCEPT;
4974}
4975
4976static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4977 struct sk_buff *skb,
4978 const struct net_device *in,
4979 const struct net_device *out,
4980 int (*okfn)(struct sk_buff *))
4981{
4982 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983}
4984
4985#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004986static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4987 struct sk_buff *skb,
4988 const struct net_device *in,
4989 const struct net_device *out,
4990 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004992 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994#endif /* IPV6 */
4995
4996#endif /* CONFIG_NETFILTER */
4997
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4999{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 int err;
5001
Eric Paris200ac532009-02-12 15:01:04 -05005002 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003 if (err)
5004 return err;
5005
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005006 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007}
5008
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009static int ipc_alloc_security(struct task_struct *task,
5010 struct kern_ipc_perm *perm,
5011 u16 sclass)
5012{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005014 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015
James Morris89d155e2005-10-30 14:59:21 -08005016 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017 if (!isec)
5018 return -ENOMEM;
5019
David Howells275bb412008-11-14 10:39:19 +11005020 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005022 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023 perm->security = isec;
5024
5025 return 0;
5026}
5027
5028static void ipc_free_security(struct kern_ipc_perm *perm)
5029{
5030 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031 perm->security = NULL;
5032 kfree(isec);
5033}
5034
5035static int msg_msg_alloc_security(struct msg_msg *msg)
5036{
5037 struct msg_security_struct *msec;
5038
James Morris89d155e2005-10-30 14:59:21 -08005039 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 if (!msec)
5041 return -ENOMEM;
5042
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 msec->sid = SECINITSID_UNLABELED;
5044 msg->security = msec;
5045
5046 return 0;
5047}
5048
5049static void msg_msg_free_security(struct msg_msg *msg)
5050{
5051 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
5053 msg->security = NULL;
5054 kfree(msec);
5055}
5056
5057static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005058 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005061 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005062 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005063 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 isec = ipc_perms->security;
5066
Thomas Liu2bf49692009-07-14 12:14:09 -04005067 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005068 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 ad.u.ipc_id = ipc_perms->key;
5070
David Howells275bb412008-11-14 10:39:19 +11005071 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072}
5073
5074static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5075{
5076 return msg_msg_alloc_security(msg);
5077}
5078
5079static void selinux_msg_msg_free_security(struct msg_msg *msg)
5080{
5081 msg_msg_free_security(msg);
5082}
5083
5084/* message queue security operations */
5085static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5086{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005088 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005089 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005090 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091 int rc;
5092
5093 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5094 if (rc)
5095 return rc;
5096
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097 isec = msq->q_perm.security;
5098
Thomas Liu2bf49692009-07-14 12:14:09 -04005099 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005100 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005101 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
David Howells275bb412008-11-14 10:39:19 +11005103 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104 MSGQ__CREATE, &ad);
5105 if (rc) {
5106 ipc_free_security(&msq->q_perm);
5107 return rc;
5108 }
5109 return 0;
5110}
5111
5112static void selinux_msg_queue_free_security(struct msg_queue *msq)
5113{
5114 ipc_free_security(&msq->q_perm);
5115}
5116
5117static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5118{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005120 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005121 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005122 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124 isec = msq->q_perm.security;
5125
Thomas Liu2bf49692009-07-14 12:14:09 -04005126 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005127 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 ad.u.ipc_id = msq->q_perm.key;
5129
David Howells275bb412008-11-14 10:39:19 +11005130 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131 MSGQ__ASSOCIATE, &ad);
5132}
5133
5134static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5135{
5136 int err;
5137 int perms;
5138
Eric Paris828dfe12008-04-17 13:17:49 -04005139 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140 case IPC_INFO:
5141 case MSG_INFO:
5142 /* No specific object, just general system-wide information. */
5143 return task_has_system(current, SYSTEM__IPC_INFO);
5144 case IPC_STAT:
5145 case MSG_STAT:
5146 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5147 break;
5148 case IPC_SET:
5149 perms = MSGQ__SETATTR;
5150 break;
5151 case IPC_RMID:
5152 perms = MSGQ__DESTROY;
5153 break;
5154 default:
5155 return 0;
5156 }
5157
Stephen Smalley6af963f2005-05-01 08:58:39 -07005158 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 return err;
5160}
5161
5162static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5163{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164 struct ipc_security_struct *isec;
5165 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005166 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005167 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005168 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 int rc;
5170
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171 isec = msq->q_perm.security;
5172 msec = msg->security;
5173
5174 /*
5175 * First time through, need to assign label to the message
5176 */
5177 if (msec->sid == SECINITSID_UNLABELED) {
5178 /*
5179 * Compute new sid based on current process and
5180 * message queue this message will be stored in
5181 */
David Howells275bb412008-11-14 10:39:19 +11005182 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005183 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 if (rc)
5185 return rc;
5186 }
5187
Thomas Liu2bf49692009-07-14 12:14:09 -04005188 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005189 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190 ad.u.ipc_id = msq->q_perm.key;
5191
5192 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005193 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194 MSGQ__WRITE, &ad);
5195 if (!rc)
5196 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005197 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5198 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199 if (!rc)
5200 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005201 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5202 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
5204 return rc;
5205}
5206
5207static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5208 struct task_struct *target,
5209 long type, int mode)
5210{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211 struct ipc_security_struct *isec;
5212 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005213 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005214 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005215 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 int rc;
5217
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218 isec = msq->q_perm.security;
5219 msec = msg->security;
5220
Thomas Liu2bf49692009-07-14 12:14:09 -04005221 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005222 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005223 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
David Howells275bb412008-11-14 10:39:19 +11005225 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226 SECCLASS_MSGQ, MSGQ__READ, &ad);
5227 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005228 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229 SECCLASS_MSG, MSG__RECEIVE, &ad);
5230 return rc;
5231}
5232
5233/* Shared Memory security operations */
5234static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5235{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005237 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005238 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005239 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240 int rc;
5241
5242 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5243 if (rc)
5244 return rc;
5245
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 isec = shp->shm_perm.security;
5247
Thomas Liu2bf49692009-07-14 12:14:09 -04005248 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005249 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005250 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
David Howells275bb412008-11-14 10:39:19 +11005252 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253 SHM__CREATE, &ad);
5254 if (rc) {
5255 ipc_free_security(&shp->shm_perm);
5256 return rc;
5257 }
5258 return 0;
5259}
5260
5261static void selinux_shm_free_security(struct shmid_kernel *shp)
5262{
5263 ipc_free_security(&shp->shm_perm);
5264}
5265
5266static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5267{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005269 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005270 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005271 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273 isec = shp->shm_perm.security;
5274
Thomas Liu2bf49692009-07-14 12:14:09 -04005275 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005276 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 ad.u.ipc_id = shp->shm_perm.key;
5278
David Howells275bb412008-11-14 10:39:19 +11005279 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 SHM__ASSOCIATE, &ad);
5281}
5282
5283/* Note, at this point, shp is locked down */
5284static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5285{
5286 int perms;
5287 int err;
5288
Eric Paris828dfe12008-04-17 13:17:49 -04005289 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290 case IPC_INFO:
5291 case SHM_INFO:
5292 /* No specific object, just general system-wide information. */
5293 return task_has_system(current, SYSTEM__IPC_INFO);
5294 case IPC_STAT:
5295 case SHM_STAT:
5296 perms = SHM__GETATTR | SHM__ASSOCIATE;
5297 break;
5298 case IPC_SET:
5299 perms = SHM__SETATTR;
5300 break;
5301 case SHM_LOCK:
5302 case SHM_UNLOCK:
5303 perms = SHM__LOCK;
5304 break;
5305 case IPC_RMID:
5306 perms = SHM__DESTROY;
5307 break;
5308 default:
5309 return 0;
5310 }
5311
Stephen Smalley6af963f2005-05-01 08:58:39 -07005312 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313 return err;
5314}
5315
5316static int selinux_shm_shmat(struct shmid_kernel *shp,
5317 char __user *shmaddr, int shmflg)
5318{
5319 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320
5321 if (shmflg & SHM_RDONLY)
5322 perms = SHM__READ;
5323 else
5324 perms = SHM__READ | SHM__WRITE;
5325
Stephen Smalley6af963f2005-05-01 08:58:39 -07005326 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327}
5328
5329/* Semaphore security operations */
5330static int selinux_sem_alloc_security(struct sem_array *sma)
5331{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005333 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005334 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005335 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 int rc;
5337
5338 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5339 if (rc)
5340 return rc;
5341
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 isec = sma->sem_perm.security;
5343
Thomas Liu2bf49692009-07-14 12:14:09 -04005344 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005345 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005346 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
David Howells275bb412008-11-14 10:39:19 +11005348 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349 SEM__CREATE, &ad);
5350 if (rc) {
5351 ipc_free_security(&sma->sem_perm);
5352 return rc;
5353 }
5354 return 0;
5355}
5356
5357static void selinux_sem_free_security(struct sem_array *sma)
5358{
5359 ipc_free_security(&sma->sem_perm);
5360}
5361
5362static int selinux_sem_associate(struct sem_array *sma, int semflg)
5363{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005365 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005366 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005367 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369 isec = sma->sem_perm.security;
5370
Thomas Liu2bf49692009-07-14 12:14:09 -04005371 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005372 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 ad.u.ipc_id = sma->sem_perm.key;
5374
David Howells275bb412008-11-14 10:39:19 +11005375 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 SEM__ASSOCIATE, &ad);
5377}
5378
5379/* Note, at this point, sma is locked down */
5380static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5381{
5382 int err;
5383 u32 perms;
5384
Eric Paris828dfe12008-04-17 13:17:49 -04005385 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 case IPC_INFO:
5387 case SEM_INFO:
5388 /* No specific object, just general system-wide information. */
5389 return task_has_system(current, SYSTEM__IPC_INFO);
5390 case GETPID:
5391 case GETNCNT:
5392 case GETZCNT:
5393 perms = SEM__GETATTR;
5394 break;
5395 case GETVAL:
5396 case GETALL:
5397 perms = SEM__READ;
5398 break;
5399 case SETVAL:
5400 case SETALL:
5401 perms = SEM__WRITE;
5402 break;
5403 case IPC_RMID:
5404 perms = SEM__DESTROY;
5405 break;
5406 case IPC_SET:
5407 perms = SEM__SETATTR;
5408 break;
5409 case IPC_STAT:
5410 case SEM_STAT:
5411 perms = SEM__GETATTR | SEM__ASSOCIATE;
5412 break;
5413 default:
5414 return 0;
5415 }
5416
Stephen Smalley6af963f2005-05-01 08:58:39 -07005417 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 return err;
5419}
5420
5421static int selinux_sem_semop(struct sem_array *sma,
5422 struct sembuf *sops, unsigned nsops, int alter)
5423{
5424 u32 perms;
5425
5426 if (alter)
5427 perms = SEM__READ | SEM__WRITE;
5428 else
5429 perms = SEM__READ;
5430
Stephen Smalley6af963f2005-05-01 08:58:39 -07005431 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432}
5433
5434static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5435{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436 u32 av = 0;
5437
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438 av = 0;
5439 if (flag & S_IRUGO)
5440 av |= IPC__UNIX_READ;
5441 if (flag & S_IWUGO)
5442 av |= IPC__UNIX_WRITE;
5443
5444 if (av == 0)
5445 return 0;
5446
Stephen Smalley6af963f2005-05-01 08:58:39 -07005447 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448}
5449
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005450static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5451{
5452 struct ipc_security_struct *isec = ipcp->security;
5453 *secid = isec->sid;
5454}
5455
Eric Paris828dfe12008-04-17 13:17:49 -04005456static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457{
5458 if (inode)
5459 inode_doinit_with_dentry(inode, dentry);
5460}
5461
5462static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005463 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464{
David Howells275bb412008-11-14 10:39:19 +11005465 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005466 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005468 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469
5470 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005471 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472 if (error)
5473 return error;
5474 }
5475
David Howells275bb412008-11-14 10:39:19 +11005476 rcu_read_lock();
5477 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478
5479 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005480 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005482 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005484 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005485 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005486 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005487 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005488 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005489 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005490 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491 else
David Howells275bb412008-11-14 10:39:19 +11005492 goto invalid;
5493 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494
5495 if (!sid)
5496 return 0;
5497
Al Viro04ff9702007-03-12 16:17:58 +00005498 error = security_sid_to_context(sid, value, &len);
5499 if (error)
5500 return error;
5501 return len;
David Howells275bb412008-11-14 10:39:19 +11005502
5503invalid:
5504 rcu_read_unlock();
5505 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506}
5507
5508static int selinux_setprocattr(struct task_struct *p,
5509 char *name, void *value, size_t size)
5510{
5511 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005512 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005513 struct cred *new;
5514 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 int error;
5516 char *str = value;
5517
5518 if (current != p) {
5519 /* SELinux only allows a process to change its own
5520 security attributes. */
5521 return -EACCES;
5522 }
5523
5524 /*
5525 * Basic control over ability to set these attributes at all.
5526 * current == p, but we'll pass them separately in case the
5527 * above restriction is ever removed.
5528 */
5529 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005530 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005532 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005533 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005534 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005535 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005536 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005538 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539 else
5540 error = -EINVAL;
5541 if (error)
5542 return error;
5543
5544 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleye44b57e2017-01-31 11:54:04 -05005545 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546 if (str[size-1] == '\n') {
5547 str[size-1] = 0;
5548 size--;
5549 }
5550 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005551 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5552 if (!capable(CAP_MAC_ADMIN))
5553 return error;
5554 error = security_context_to_sid_force(value, size,
5555 &sid);
5556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 if (error)
5558 return error;
5559 }
5560
David Howellsd84f4f92008-11-14 10:39:23 +11005561 new = prepare_creds();
5562 if (!new)
5563 return -ENOMEM;
5564
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565 /* Permission checking based on the specified context is
5566 performed during the actual operation (execve,
5567 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005568 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005569 checks and may_create for the file creation checks. The
5570 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005571 tsec = new->security;
5572 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005574 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005575 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005576 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005577 error = may_create_key(sid, p);
5578 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005579 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005580 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005581 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005582 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005583 } else if (!strcmp(name, "current")) {
5584 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005586 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005587
David Howellsd84f4f92008-11-14 10:39:23 +11005588 /* Only allow single threaded processes to change context */
5589 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005590 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005591 error = security_bounded_transition(tsec->sid, sid);
5592 if (error)
5593 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595
5596 /* Check permissions for the transition. */
5597 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005598 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005600 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005601
5602 /* Check for ptracing, and update the task SID if ok.
5603 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005604 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005606 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005607 if (tracer)
5608 ptsid = task_sid(tracer);
5609 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610
David Howellsd84f4f92008-11-14 10:39:23 +11005611 if (tracer) {
5612 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5613 PROCESS__PTRACE, NULL);
5614 if (error)
5615 goto abort_change;
5616 }
5617
5618 tsec->sid = sid;
5619 } else {
5620 error = -EINVAL;
5621 goto abort_change;
5622 }
5623
5624 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005626
5627abort_change:
5628 abort_creds(new);
5629 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630}
5631
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005632static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5633{
5634 return security_sid_to_context(secid, secdata, seclen);
5635}
5636
David Howells7bf570d2008-04-29 20:52:51 +01005637static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005638{
5639 return security_context_to_sid(secdata, seclen, secid);
5640}
5641
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005642static void selinux_release_secctx(char *secdata, u32 seclen)
5643{
Paul Moore088999e2007-08-01 11:12:58 -04005644 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005645}
5646
David P. Quigley1ee65e32009-09-03 14:25:57 -04005647/*
5648 * called with inode->i_mutex locked
5649 */
5650static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5651{
5652 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5653}
5654
5655/*
5656 * called with inode->i_mutex locked
5657 */
5658static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5659{
5660 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5661}
5662
5663static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5664{
5665 int len = 0;
5666 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5667 ctx, true);
5668 if (len < 0)
5669 return len;
5670 *ctxlen = len;
5671 return 0;
5672}
Michael LeMayd7200242006-06-22 14:47:17 -07005673#ifdef CONFIG_KEYS
5674
David Howellsd84f4f92008-11-14 10:39:23 +11005675static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005676 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005677{
David Howellsd84f4f92008-11-14 10:39:23 +11005678 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005679 struct key_security_struct *ksec;
5680
5681 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5682 if (!ksec)
5683 return -ENOMEM;
5684
David Howellsd84f4f92008-11-14 10:39:23 +11005685 tsec = cred->security;
5686 if (tsec->keycreate_sid)
5687 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005688 else
David Howellsd84f4f92008-11-14 10:39:23 +11005689 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005690
David Howells275bb412008-11-14 10:39:19 +11005691 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005692 return 0;
5693}
5694
5695static void selinux_key_free(struct key *k)
5696{
5697 struct key_security_struct *ksec = k->security;
5698
5699 k->security = NULL;
5700 kfree(ksec);
5701}
5702
5703static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005704 const struct cred *cred,
5705 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005706{
5707 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005708 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005709 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005710
5711 /* if no specific permissions are requested, we skip the
5712 permission check. No serious, additional covert channels
5713 appear to be created. */
5714 if (perm == 0)
5715 return 0;
5716
David Howellsd84f4f92008-11-14 10:39:23 +11005717 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005718
5719 key = key_ref_to_ptr(key_ref);
5720 ksec = key->security;
5721
5722 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005723}
5724
David Howells70a5bb72008-04-29 01:01:26 -07005725static int selinux_key_getsecurity(struct key *key, char **_buffer)
5726{
5727 struct key_security_struct *ksec = key->security;
5728 char *context = NULL;
5729 unsigned len;
5730 int rc;
5731
5732 rc = security_sid_to_context(ksec->sid, &context, &len);
5733 if (!rc)
5734 rc = len;
5735 *_buffer = context;
5736 return rc;
5737}
5738
Michael LeMayd7200242006-06-22 14:47:17 -07005739#endif
5740
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005742 .name = "selinux",
5743
Stephen Smalley48a23702012-11-05 08:15:34 -05005744 .binder_set_context_mgr = selinux_binder_set_context_mgr,
5745 .binder_transaction = selinux_binder_transaction,
5746 .binder_transfer_binder = selinux_binder_transfer_binder,
5747 .binder_transfer_file = selinux_binder_transfer_file,
5748
Ingo Molnar9e488582009-05-07 19:26:19 +10005749 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005750 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005752 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753 .capable = selinux_capable,
5754 .quotactl = selinux_quotactl,
5755 .quota_on = selinux_quota_on,
5756 .syslog = selinux_syslog,
5757 .vm_enough_memory = selinux_vm_enough_memory,
5758
5759 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760
David Howellsa6f76f22008-11-14 10:39:24 +11005761 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005762 .bprm_committing_creds = selinux_bprm_committing_creds,
5763 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764 .bprm_secureexec = selinux_bprm_secureexec,
5765
5766 .sb_alloc_security = selinux_sb_alloc_security,
5767 .sb_free_security = selinux_sb_free_security,
5768 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005769 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005770 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005771 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772 .sb_statfs = selinux_sb_statfs,
5773 .sb_mount = selinux_mount,
5774 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005775 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005776 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005777 .sb_parse_opts_str = selinux_parse_opts_str,
5778
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779
5780 .inode_alloc_security = selinux_inode_alloc_security,
5781 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005782 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 .inode_create = selinux_inode_create,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005784 .inode_post_create = selinux_inode_post_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005786 .inode_unlink = selinux_inode_unlink,
5787 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789 .inode_rmdir = selinux_inode_rmdir,
5790 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792 .inode_readlink = selinux_inode_readlink,
5793 .inode_follow_link = selinux_inode_follow_link,
5794 .inode_permission = selinux_inode_permission,
5795 .inode_setattr = selinux_inode_setattr,
5796 .inode_getattr = selinux_inode_getattr,
5797 .inode_setxattr = selinux_inode_setxattr,
5798 .inode_post_setxattr = selinux_inode_post_setxattr,
5799 .inode_getxattr = selinux_inode_getxattr,
5800 .inode_listxattr = selinux_inode_listxattr,
5801 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005802 .inode_getsecurity = selinux_inode_getsecurity,
5803 .inode_setsecurity = selinux_inode_setsecurity,
5804 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005805 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806
5807 .file_permission = selinux_file_permission,
5808 .file_alloc_security = selinux_file_alloc_security,
5809 .file_free_security = selinux_file_free_security,
5810 .file_ioctl = selinux_file_ioctl,
5811 .file_mmap = selinux_file_mmap,
5812 .file_mprotect = selinux_file_mprotect,
5813 .file_lock = selinux_file_lock,
5814 .file_fcntl = selinux_file_fcntl,
5815 .file_set_fowner = selinux_file_set_fowner,
5816 .file_send_sigiotask = selinux_file_send_sigiotask,
5817 .file_receive = selinux_file_receive,
5818
Eric Paris828dfe12008-04-17 13:17:49 -04005819 .dentry_open = selinux_dentry_open,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005820 .file_close = selinux_file_close,
5821 .allow_merge_bio = selinux_allow_merge_bio,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005822
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005824 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005825 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005826 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005827 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005828 .kernel_act_as = selinux_kernel_act_as,
5829 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005830 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005831 .task_setpgid = selinux_task_setpgid,
5832 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005833 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005834 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005836 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005837 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838 .task_setrlimit = selinux_task_setrlimit,
5839 .task_setscheduler = selinux_task_setscheduler,
5840 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005841 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 .task_kill = selinux_task_kill,
5843 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005844 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845
5846 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005847 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848
5849 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5850 .msg_msg_free_security = selinux_msg_msg_free_security,
5851
5852 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5853 .msg_queue_free_security = selinux_msg_queue_free_security,
5854 .msg_queue_associate = selinux_msg_queue_associate,
5855 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5856 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5857 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5858
5859 .shm_alloc_security = selinux_shm_alloc_security,
5860 .shm_free_security = selinux_shm_free_security,
5861 .shm_associate = selinux_shm_associate,
5862 .shm_shmctl = selinux_shm_shmctl,
5863 .shm_shmat = selinux_shm_shmat,
5864
Eric Paris828dfe12008-04-17 13:17:49 -04005865 .sem_alloc_security = selinux_sem_alloc_security,
5866 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 .sem_associate = selinux_sem_associate,
5868 .sem_semctl = selinux_sem_semctl,
5869 .sem_semop = selinux_sem_semop,
5870
Eric Paris828dfe12008-04-17 13:17:49 -04005871 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872
Eric Paris828dfe12008-04-17 13:17:49 -04005873 .getprocattr = selinux_getprocattr,
5874 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005876 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005877 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005878 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005879 .inode_notifysecctx = selinux_inode_notifysecctx,
5880 .inode_setsecctx = selinux_inode_setsecctx,
5881 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005882
Eric Paris828dfe12008-04-17 13:17:49 -04005883 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884 .unix_may_send = selinux_socket_unix_may_send,
5885
5886 .socket_create = selinux_socket_create,
5887 .socket_post_create = selinux_socket_post_create,
5888 .socket_bind = selinux_socket_bind,
5889 .socket_connect = selinux_socket_connect,
5890 .socket_listen = selinux_socket_listen,
5891 .socket_accept = selinux_socket_accept,
5892 .socket_sendmsg = selinux_socket_sendmsg,
5893 .socket_recvmsg = selinux_socket_recvmsg,
5894 .socket_getsockname = selinux_socket_getsockname,
5895 .socket_getpeername = selinux_socket_getpeername,
5896 .socket_getsockopt = selinux_socket_getsockopt,
5897 .socket_setsockopt = selinux_socket_setsockopt,
5898 .socket_shutdown = selinux_socket_shutdown,
5899 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005900 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5901 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902 .sk_alloc_security = selinux_sk_alloc_security,
5903 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005904 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005905 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005906 .sock_graft = selinux_sock_graft,
5907 .inet_conn_request = selinux_inet_conn_request,
5908 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005909 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005910 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5911 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5912 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005913 .req_classify_flow = selinux_req_classify_flow,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005914 .tun_dev_create = selinux_tun_dev_create,
5915 .tun_dev_post_create = selinux_tun_dev_post_create,
5916 .tun_dev_attach = selinux_tun_dev_attach,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005917
5918#ifdef CONFIG_SECURITY_NETWORK_XFRM
5919 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5920 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5921 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005922 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005923 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5924 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005925 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005926 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005927 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005928 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005930
5931#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005932 .key_alloc = selinux_key_alloc,
5933 .key_free = selinux_key_free,
5934 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005935 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005936#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005937
5938#ifdef CONFIG_AUDIT
5939 .audit_rule_init = selinux_audit_rule_init,
5940 .audit_rule_known = selinux_audit_rule_known,
5941 .audit_rule_match = selinux_audit_rule_match,
5942 .audit_rule_free = selinux_audit_rule_free,
5943#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944};
5945
5946static __init int selinux_init(void)
5947{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005948 if (!security_module_enable(&selinux_ops)) {
5949 selinux_enabled = 0;
5950 return 0;
5951 }
5952
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953 if (!selinux_enabled) {
5954 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5955 return 0;
5956 }
5957
5958 printk(KERN_INFO "SELinux: Initializing.\n");
5959
5960 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005961 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005963 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5964
James Morris7cae7e22006-03-22 00:09:22 -08005965 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5966 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005967 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968 avc_init();
5969
Eric Paris828dfe12008-04-17 13:17:49 -04005970 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005971 panic("SELinux: Unable to register with kernel.\n");
5972
Eric Paris828dfe12008-04-17 13:17:49 -04005973 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005974 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005975 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005976 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005977
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978 return 0;
5979}
5980
Al Viroe8c26252010-03-23 06:36:54 -04005981static void delayed_superblock_init(struct super_block *sb, void *unused)
5982{
5983 superblock_doinit(sb, NULL);
5984}
5985
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986void selinux_complete_init(void)
5987{
Eric Parisfadcdb42007-02-22 18:11:31 -05005988 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989
5990 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005991 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005992 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993}
5994
5995/* SELinux requires early initialization in order to label
5996 all processes and objects when they are created. */
5997security_initcall(selinux_init);
5998
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005999#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Paul Mooreeffad8d2008-01-29 08:49:27 -05006001static struct nf_hook_ops selinux_ipv4_ops[] = {
6002 {
6003 .hook = selinux_ipv4_postroute,
6004 .owner = THIS_MODULE,
6005 .pf = PF_INET,
6006 .hooknum = NF_INET_POST_ROUTING,
6007 .priority = NF_IP_PRI_SELINUX_LAST,
6008 },
6009 {
6010 .hook = selinux_ipv4_forward,
6011 .owner = THIS_MODULE,
6012 .pf = PF_INET,
6013 .hooknum = NF_INET_FORWARD,
6014 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006015 },
6016 {
6017 .hook = selinux_ipv4_output,
6018 .owner = THIS_MODULE,
6019 .pf = PF_INET,
6020 .hooknum = NF_INET_LOCAL_OUT,
6021 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023};
6024
6025#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
6026
Paul Mooreeffad8d2008-01-29 08:49:27 -05006027static struct nf_hook_ops selinux_ipv6_ops[] = {
6028 {
6029 .hook = selinux_ipv6_postroute,
6030 .owner = THIS_MODULE,
6031 .pf = PF_INET6,
6032 .hooknum = NF_INET_POST_ROUTING,
6033 .priority = NF_IP6_PRI_SELINUX_LAST,
6034 },
6035 {
6036 .hook = selinux_ipv6_forward,
6037 .owner = THIS_MODULE,
6038 .pf = PF_INET6,
6039 .hooknum = NF_INET_FORWARD,
6040 .priority = NF_IP6_PRI_SELINUX_FIRST,
6041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042};
6043
6044#endif /* IPV6 */
6045
6046static int __init selinux_nf_ip_init(void)
6047{
6048 int err = 0;
6049
6050 if (!selinux_enabled)
6051 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05006052
6053 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6054
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006055 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
6056 if (err)
6057 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058
6059#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006060 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
6061 if (err)
6062 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006064
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065out:
6066 return err;
6067}
6068
6069__initcall(selinux_nf_ip_init);
6070
6071#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6072static void selinux_nf_ip_exit(void)
6073{
Eric Parisfadcdb42007-02-22 18:11:31 -05006074 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006076 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006078 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079#endif /* IPV6 */
6080}
6081#endif
6082
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006083#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
6085#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6086#define selinux_nf_ip_exit()
6087#endif
6088
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006089#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
6091#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006092static int selinux_disabled;
6093
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094int selinux_disable(void)
6095{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 if (ss_initialized) {
6097 /* Not permitted after initial policy load. */
6098 return -EINVAL;
6099 }
6100
6101 if (selinux_disabled) {
6102 /* Only do this once. */
6103 return -EINVAL;
6104 }
6105
6106 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6107
6108 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006109 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006111 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
Eric Parisaf8ff042009-09-20 21:23:01 -04006113 /* Try to destroy the avc node cache */
6114 avc_disable();
6115
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116 /* Unregister netfilter hooks. */
6117 selinux_nf_ip_exit();
6118
6119 /* Unregister selinuxfs. */
6120 exit_sel_fs();
6121
6122 return 0;
6123}
6124#endif