blob: 70d4a8a7f21c1b996379fe59af3c7cca5aa087cd [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[] */
Eric Dumazetca10b9e2013-04-08 17:58:11 +000054#include <net/sock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore216c4a72013-12-04 16:10:45 -050056#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050057#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050058#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040059#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070061#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <linux/bitops.h>
63#include <linux/interrupt.h>
64#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000065#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <linux/tcp.h>
67#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080068#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#include <linux/quota.h>
70#include <linux/un.h> /* for Unix socket types */
71#include <net/af_unix.h> /* for Unix socket types */
72#include <linux/parser.h>
73#include <linux/nfs_mount.h>
74#include <net/ipv6.h>
75#include <linux/hugetlb.h>
76#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070078#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070079#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070080#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070081#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080082#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070083#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040084#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000085#include <linux/msg.h>
86#include <linux/shm.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
Steven Rostedt057f2f72014-01-09 21:46:34 -0500222static void inode_free_rcu(struct rcu_head *head)
223{
224 struct inode_security_struct *isec;
225
226 isec = container_of(head, struct inode_security_struct, rcu);
227 kmem_cache_free(sel_inode_cache, isec);
228}
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230static void inode_free_security(struct inode *inode)
231{
232 struct inode_security_struct *isec = inode->i_security;
233 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
234
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 spin_lock(&sbsec->isec_lock);
236 if (!list_empty(&isec->list))
237 list_del_init(&isec->list);
238 spin_unlock(&sbsec->isec_lock);
239
Steven Rostedt057f2f72014-01-09 21:46:34 -0500240 /*
241 * The inode may still be referenced in a path walk and
242 * a call to selinux_inode_permission() can be made
243 * after inode_free_security() is called. Ideally, the VFS
244 * wouldn't do this, but fixing that is a much harder
245 * job. For now, simply free the i_security via RCU, and
246 * leave the current inode->i_security pointer intact.
247 * The inode will be freed after the RCU grace period too.
248 */
249 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250}
251
252static int file_alloc_security(struct file *file)
253{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100255 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800257 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 if (!fsec)
259 return -ENOMEM;
260
David Howells275bb412008-11-14 10:39:19 +1100261 fsec->sid = sid;
262 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 file->f_security = fsec;
264
265 return 0;
266}
267
268static void file_free_security(struct file *file)
269{
270 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 file->f_security = NULL;
272 kfree(fsec);
273}
274
275static int superblock_alloc_security(struct super_block *sb)
276{
277 struct superblock_security_struct *sbsec;
278
James Morris89d155e2005-10-30 14:59:21 -0800279 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!sbsec)
281 return -ENOMEM;
282
Eric Parisbc7e9822006-09-25 23:32:02 -0700283 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 INIT_LIST_HEAD(&sbsec->isec_head);
285 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 sbsec->sb = sb;
287 sbsec->sid = SECINITSID_UNLABELED;
288 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700289 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 sb->s_security = sbsec;
291
292 return 0;
293}
294
295static void superblock_free_security(struct super_block *sb)
296{
297 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 sb->s_security = NULL;
299 kfree(sbsec);
300}
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302/* The file system's label must be initialized prior to use. */
303
Stephen Hemminger634a5392010-03-04 21:59:03 -0800304static const char *labeling_behaviors[6] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 "uses xattr",
306 "uses transition SIDs",
307 "uses task SIDs",
308 "uses genfs_contexts",
309 "not configured for labeling",
310 "uses mountpoint labeling",
311};
312
313static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
314
315static inline int inode_doinit(struct inode *inode)
316{
317 return inode_doinit_with_dentry(inode, NULL);
318}
319
320enum {
Eric Paris31e87932007-09-19 17:19:12 -0400321 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 Opt_context = 1,
323 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500324 Opt_defcontext = 3,
325 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500326 Opt_labelsupport = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327};
328
Steven Whitehousea447c092008-10-13 10:46:57 +0100329static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400330 {Opt_context, CONTEXT_STR "%s"},
331 {Opt_fscontext, FSCONTEXT_STR "%s"},
332 {Opt_defcontext, DEFCONTEXT_STR "%s"},
333 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500334 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400335 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336};
337
338#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
339
Eric Parisc312feb2006-07-10 04:43:53 -0700340static int may_context_mount_sb_relabel(u32 sid,
341 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100342 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700343{
David Howells275bb412008-11-14 10:39:19 +1100344 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700345 int rc;
346
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(tsec->sid, sid, SECCLASS_FILESYSTEM,
353 FILESYSTEM__RELABELTO, NULL);
354 return rc;
355}
356
Eric Paris08089252006-07-10 04:43:55 -0700357static int may_context_mount_inode_relabel(u32 sid,
358 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100359 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700360{
David Howells275bb412008-11-14 10:39:19 +1100361 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700362 int rc;
363 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
364 FILESYSTEM__RELABELFROM, NULL);
365 if (rc)
366 return rc;
367
368 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
369 FILESYSTEM__ASSOCIATE, NULL);
370 return rc;
371}
372
Eric Parisc9180a52007-11-30 13:00:35 -0500373static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
375 struct superblock_security_struct *sbsec = sb->s_security;
376 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500377 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 int rc = 0;
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
381 /* Make sure that the xattr handler exists and that no
382 error other than -ENODATA is returned by getxattr on
383 the root directory. -ENODATA is ok, as this may be
384 the first boot of the SELinux kernel before we have
385 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500386 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
388 "xattr support\n", sb->s_id, sb->s_type->name);
389 rc = -EOPNOTSUPP;
390 goto out;
391 }
Eric Parisc9180a52007-11-30 13:00:35 -0500392 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 if (rc < 0 && rc != -ENODATA) {
394 if (rc == -EOPNOTSUPP)
395 printk(KERN_WARNING "SELinux: (dev %s, type "
396 "%s) has no security xattr handler\n",
397 sb->s_id, sb->s_type->name);
398 else
399 printk(KERN_WARNING "SELinux: (dev %s, type "
400 "%s) getxattr errno %d\n", sb->s_id,
401 sb->s_type->name, -rc);
402 goto out;
403 }
404 }
405
David P. Quigley11689d42009-01-16 09:22:03 -0500406 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Eric Parisc9180a52007-11-30 13:00:35 -0500408 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500409 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500411 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500412 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 sb->s_id, sb->s_type->name,
414 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
David P. Quigley11689d42009-01-16 09:22:03 -0500416 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
417 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
418 sbsec->behavior == SECURITY_FS_USE_NONE ||
419 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
420 sbsec->flags &= ~SE_SBLABELSUPP;
421
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400422 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
423 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
424 sbsec->flags |= SE_SBLABELSUPP;
425
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500427 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 /* Initialize any other inodes associated with the superblock, e.g.
430 inodes created prior to initial policy load or inodes created
431 during get_sb by a pseudo filesystem that directly
432 populates itself. */
433 spin_lock(&sbsec->isec_lock);
434next_inode:
435 if (!list_empty(&sbsec->isec_head)) {
436 struct inode_security_struct *isec =
437 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500438 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 struct inode *inode = isec->inode;
440 spin_unlock(&sbsec->isec_lock);
441 inode = igrab(inode);
442 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500443 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 inode_doinit(inode);
445 iput(inode);
446 }
447 spin_lock(&sbsec->isec_lock);
448 list_del_init(&isec->list);
449 goto next_inode;
450 }
451 spin_unlock(&sbsec->isec_lock);
452out:
Eric Parisc9180a52007-11-30 13:00:35 -0500453 return rc;
454}
455
456/*
457 * This function should allow an FS to ask what it's mount security
458 * options were so it can use those later for submounts, displaying
459 * mount options, or whatever.
460 */
461static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500462 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500463{
464 int rc = 0, i;
465 struct superblock_security_struct *sbsec = sb->s_security;
466 char *context = NULL;
467 u32 len;
468 char tmp;
469
Eric Parise0007522008-03-05 10:31:54 -0500470 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500471
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500472 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500473 return -EINVAL;
474
475 if (!ss_initialized)
476 return -EINVAL;
477
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500478 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500479 /* count the number of mount options for this sb */
480 for (i = 0; i < 8; i++) {
481 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500482 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500483 tmp >>= 1;
484 }
David P. Quigley11689d42009-01-16 09:22:03 -0500485 /* Check if the Label support flag is set */
486 if (sbsec->flags & SE_SBLABELSUPP)
487 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500488
Eric Parise0007522008-03-05 10:31:54 -0500489 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
490 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500491 rc = -ENOMEM;
492 goto out_free;
493 }
494
Eric Parise0007522008-03-05 10:31:54 -0500495 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
496 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500497 rc = -ENOMEM;
498 goto out_free;
499 }
500
501 i = 0;
502 if (sbsec->flags & FSCONTEXT_MNT) {
503 rc = security_sid_to_context(sbsec->sid, &context, &len);
504 if (rc)
505 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500506 opts->mnt_opts[i] = context;
507 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500508 }
509 if (sbsec->flags & CONTEXT_MNT) {
510 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
511 if (rc)
512 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500513 opts->mnt_opts[i] = context;
514 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500515 }
516 if (sbsec->flags & DEFCONTEXT_MNT) {
517 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
518 if (rc)
519 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500520 opts->mnt_opts[i] = context;
521 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500522 }
523 if (sbsec->flags & ROOTCONTEXT_MNT) {
524 struct inode *root = sbsec->sb->s_root->d_inode;
525 struct inode_security_struct *isec = root->i_security;
526
527 rc = security_sid_to_context(isec->sid, &context, &len);
528 if (rc)
529 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500530 opts->mnt_opts[i] = context;
531 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500532 }
David P. Quigley11689d42009-01-16 09:22:03 -0500533 if (sbsec->flags & SE_SBLABELSUPP) {
534 opts->mnt_opts[i] = NULL;
535 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
536 }
Eric Parisc9180a52007-11-30 13:00:35 -0500537
Eric Parise0007522008-03-05 10:31:54 -0500538 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500539
540 return 0;
541
542out_free:
Eric Parise0007522008-03-05 10:31:54 -0500543 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500544 return rc;
545}
546
547static int bad_option(struct superblock_security_struct *sbsec, char flag,
548 u32 old_sid, u32 new_sid)
549{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500550 char mnt_flags = sbsec->flags & SE_MNTMASK;
551
Eric Parisc9180a52007-11-30 13:00:35 -0500552 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500553 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500554 if (!(sbsec->flags & flag) ||
555 (old_sid != new_sid))
556 return 1;
557
558 /* check if we were passed the same options twice,
559 * aka someone passed context=a,context=b
560 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500561 if (!(sbsec->flags & SE_SBINITIALIZED))
562 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500563 return 1;
564 return 0;
565}
Eric Parise0007522008-03-05 10:31:54 -0500566
Eric Parisc9180a52007-11-30 13:00:35 -0500567/*
568 * Allow filesystems with binary mount data to explicitly set mount point
569 * labeling information.
570 */
Eric Parise0007522008-03-05 10:31:54 -0500571static int selinux_set_mnt_opts(struct super_block *sb,
572 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500573{
David Howells275bb412008-11-14 10:39:19 +1100574 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500575 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500576 struct superblock_security_struct *sbsec = sb->s_security;
577 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000578 struct inode *inode = sbsec->sb->s_root->d_inode;
579 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500580 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
581 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500582 char **mount_options = opts->mnt_opts;
583 int *flags = opts->mnt_opts_flags;
584 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500585
586 mutex_lock(&sbsec->lock);
587
588 if (!ss_initialized) {
589 if (!num_opts) {
590 /* Defer initialization until selinux_complete_init,
591 after the initial policy is loaded and the security
592 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500593 goto out;
594 }
595 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400596 printk(KERN_WARNING "SELinux: Unable to set superblock options "
597 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500598 goto out;
599 }
600
601 /*
Eric Parise0007522008-03-05 10:31:54 -0500602 * Binary mount data FS will come through this function twice. Once
603 * from an explicit call and once from the generic calls from the vfs.
604 * Since the generic VFS calls will not contain any security mount data
605 * we need to skip the double mount verification.
606 *
607 * This does open a hole in which we will not notice if the first
608 * mount using this sb set explict options and a second mount using
609 * this sb does not set any security options. (The first options
610 * will be used for both mounts)
611 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500612 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500613 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400614 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500615
616 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500617 * parse the mount options, check if they are valid sids.
618 * also check if someone is trying to mount the same sb more
619 * than once with different security options.
620 */
621 for (i = 0; i < num_opts; i++) {
622 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500623
624 if (flags[i] == SE_SBLABELSUPP)
625 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500626 rc = security_context_to_sid(mount_options[i],
627 strlen(mount_options[i]), &sid);
628 if (rc) {
629 printk(KERN_WARNING "SELinux: security_context_to_sid"
630 "(%s) failed for (dev %s, type %s) errno=%d\n",
631 mount_options[i], sb->s_id, name, rc);
632 goto out;
633 }
634 switch (flags[i]) {
635 case FSCONTEXT_MNT:
636 fscontext_sid = sid;
637
638 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
639 fscontext_sid))
640 goto out_double_mount;
641
642 sbsec->flags |= FSCONTEXT_MNT;
643 break;
644 case CONTEXT_MNT:
645 context_sid = sid;
646
647 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
648 context_sid))
649 goto out_double_mount;
650
651 sbsec->flags |= CONTEXT_MNT;
652 break;
653 case ROOTCONTEXT_MNT:
654 rootcontext_sid = sid;
655
656 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
657 rootcontext_sid))
658 goto out_double_mount;
659
660 sbsec->flags |= ROOTCONTEXT_MNT;
661
662 break;
663 case DEFCONTEXT_MNT:
664 defcontext_sid = sid;
665
666 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
667 defcontext_sid))
668 goto out_double_mount;
669
670 sbsec->flags |= DEFCONTEXT_MNT;
671
672 break;
673 default:
674 rc = -EINVAL;
675 goto out;
676 }
677 }
678
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500679 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500680 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500681 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500682 goto out_double_mount;
683 rc = 0;
684 goto out;
685 }
686
James Morris089be432008-07-15 18:32:49 +1000687 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500688 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500689
690 /* Determine the labeling behavior to use for this filesystem type. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500691 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500692 if (rc) {
693 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000694 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500695 goto out;
696 }
697
698 /* sets the context of the superblock for the fs being mounted. */
699 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100700 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500701 if (rc)
702 goto out;
703
704 sbsec->sid = fscontext_sid;
705 }
706
707 /*
708 * Switch to using mount point labeling behavior.
709 * sets the label used on all file below the mountpoint, and will set
710 * the superblock context if not already set.
711 */
712 if (context_sid) {
713 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100714 rc = may_context_mount_sb_relabel(context_sid, sbsec,
715 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500716 if (rc)
717 goto out;
718 sbsec->sid = context_sid;
719 } else {
David Howells275bb412008-11-14 10:39:19 +1100720 rc = may_context_mount_inode_relabel(context_sid, sbsec,
721 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500722 if (rc)
723 goto out;
724 }
725 if (!rootcontext_sid)
726 rootcontext_sid = context_sid;
727
728 sbsec->mntpoint_sid = context_sid;
729 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
730 }
731
732 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100733 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
734 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500735 if (rc)
736 goto out;
737
738 root_isec->sid = rootcontext_sid;
739 root_isec->initialized = 1;
740 }
741
742 if (defcontext_sid) {
743 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
744 rc = -EINVAL;
745 printk(KERN_WARNING "SELinux: defcontext option is "
746 "invalid for this filesystem type\n");
747 goto out;
748 }
749
750 if (defcontext_sid != sbsec->def_sid) {
751 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100752 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500753 if (rc)
754 goto out;
755 }
756
757 sbsec->def_sid = defcontext_sid;
758 }
759
760 rc = sb_finish_set_opts(sb);
761out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700762 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500764out_double_mount:
765 rc = -EINVAL;
766 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
767 "security settings for (dev %s, type %s)\n", sb->s_id, name);
768 goto out;
769}
770
Jeff Layton094f7b62013-04-01 08:14:24 -0400771static int selinux_cmp_sb_context(const struct super_block *oldsb,
772 const struct super_block *newsb)
773{
774 struct superblock_security_struct *old = oldsb->s_security;
775 struct superblock_security_struct *new = newsb->s_security;
776 char oldflags = old->flags & SE_MNTMASK;
777 char newflags = new->flags & SE_MNTMASK;
778
779 if (oldflags != newflags)
780 goto mismatch;
781 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
782 goto mismatch;
783 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
784 goto mismatch;
785 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
786 goto mismatch;
787 if (oldflags & ROOTCONTEXT_MNT) {
788 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
789 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
790 if (oldroot->sid != newroot->sid)
791 goto mismatch;
792 }
793 return 0;
794mismatch:
795 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
796 "different security settings for (dev %s, "
797 "type %s)\n", newsb->s_id, newsb->s_type->name);
798 return -EBUSY;
799}
800
801static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500802 struct super_block *newsb)
803{
804 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
805 struct superblock_security_struct *newsbsec = newsb->s_security;
806
807 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
808 int set_context = (oldsbsec->flags & CONTEXT_MNT);
809 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
810
Eric Paris0f5e6422008-04-21 16:24:11 -0400811 /*
812 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400813 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400814 */
Al Viroe8c26252010-03-23 06:36:54 -0400815 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400816 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500817
Eric Parisc9180a52007-11-30 13:00:35 -0500818 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500819 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500820
Jeff Layton094f7b62013-04-01 08:14:24 -0400821 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500822 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400823 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400824
Eric Parisc9180a52007-11-30 13:00:35 -0500825 mutex_lock(&newsbsec->lock);
826
827 newsbsec->flags = oldsbsec->flags;
828
829 newsbsec->sid = oldsbsec->sid;
830 newsbsec->def_sid = oldsbsec->def_sid;
831 newsbsec->behavior = oldsbsec->behavior;
832
833 if (set_context) {
834 u32 sid = oldsbsec->mntpoint_sid;
835
836 if (!set_fscontext)
837 newsbsec->sid = sid;
838 if (!set_rootcontext) {
839 struct inode *newinode = newsb->s_root->d_inode;
840 struct inode_security_struct *newisec = newinode->i_security;
841 newisec->sid = sid;
842 }
843 newsbsec->mntpoint_sid = sid;
844 }
845 if (set_rootcontext) {
846 const struct inode *oldinode = oldsb->s_root->d_inode;
847 const struct inode_security_struct *oldisec = oldinode->i_security;
848 struct inode *newinode = newsb->s_root->d_inode;
849 struct inode_security_struct *newisec = newinode->i_security;
850
851 newisec->sid = oldisec->sid;
852 }
853
854 sb_finish_set_opts(newsb);
855 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400856 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500857}
858
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200859static int selinux_parse_opts_str(char *options,
860 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500861{
Eric Parise0007522008-03-05 10:31:54 -0500862 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500863 char *context = NULL, *defcontext = NULL;
864 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500865 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500866
Eric Parise0007522008-03-05 10:31:54 -0500867 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500868
869 /* Standard string-based options. */
870 while ((p = strsep(&options, "|")) != NULL) {
871 int token;
872 substring_t args[MAX_OPT_ARGS];
873
874 if (!*p)
875 continue;
876
877 token = match_token(p, tokens, args);
878
879 switch (token) {
880 case Opt_context:
881 if (context || defcontext) {
882 rc = -EINVAL;
883 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
884 goto out_err;
885 }
886 context = match_strdup(&args[0]);
887 if (!context) {
888 rc = -ENOMEM;
889 goto out_err;
890 }
891 break;
892
893 case Opt_fscontext:
894 if (fscontext) {
895 rc = -EINVAL;
896 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
897 goto out_err;
898 }
899 fscontext = match_strdup(&args[0]);
900 if (!fscontext) {
901 rc = -ENOMEM;
902 goto out_err;
903 }
904 break;
905
906 case Opt_rootcontext:
907 if (rootcontext) {
908 rc = -EINVAL;
909 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
910 goto out_err;
911 }
912 rootcontext = match_strdup(&args[0]);
913 if (!rootcontext) {
914 rc = -ENOMEM;
915 goto out_err;
916 }
917 break;
918
919 case Opt_defcontext:
920 if (context || defcontext) {
921 rc = -EINVAL;
922 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
923 goto out_err;
924 }
925 defcontext = match_strdup(&args[0]);
926 if (!defcontext) {
927 rc = -ENOMEM;
928 goto out_err;
929 }
930 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500931 case Opt_labelsupport:
932 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500933 default:
934 rc = -EINVAL;
935 printk(KERN_WARNING "SELinux: unknown mount option\n");
936 goto out_err;
937
938 }
939 }
940
Eric Parise0007522008-03-05 10:31:54 -0500941 rc = -ENOMEM;
942 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
943 if (!opts->mnt_opts)
944 goto out_err;
945
946 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
947 if (!opts->mnt_opts_flags) {
948 kfree(opts->mnt_opts);
949 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500950 }
951
Eric Parise0007522008-03-05 10:31:54 -0500952 if (fscontext) {
953 opts->mnt_opts[num_mnt_opts] = fscontext;
954 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
955 }
956 if (context) {
957 opts->mnt_opts[num_mnt_opts] = context;
958 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
959 }
960 if (rootcontext) {
961 opts->mnt_opts[num_mnt_opts] = rootcontext;
962 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
963 }
964 if (defcontext) {
965 opts->mnt_opts[num_mnt_opts] = defcontext;
966 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
967 }
968
969 opts->num_mnt_opts = num_mnt_opts;
970 return 0;
971
Eric Parisc9180a52007-11-30 13:00:35 -0500972out_err:
973 kfree(context);
974 kfree(defcontext);
975 kfree(fscontext);
976 kfree(rootcontext);
977 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978}
Eric Parise0007522008-03-05 10:31:54 -0500979/*
980 * string mount options parsing and call set the sbsec
981 */
982static int superblock_doinit(struct super_block *sb, void *data)
983{
984 int rc = 0;
985 char *options = data;
986 struct security_mnt_opts opts;
987
988 security_init_mnt_opts(&opts);
989
990 if (!data)
991 goto out;
992
993 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
994
995 rc = selinux_parse_opts_str(options, &opts);
996 if (rc)
997 goto out_err;
998
999out:
1000 rc = selinux_set_mnt_opts(sb, &opts);
1001
1002out_err:
1003 security_free_mnt_opts(&opts);
1004 return rc;
1005}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Adrian Bunk3583a712008-07-22 20:21:23 +03001007static void selinux_write_opts(struct seq_file *m,
1008 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001009{
1010 int i;
1011 char *prefix;
1012
1013 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001014 char *has_comma;
1015
1016 if (opts->mnt_opts[i])
1017 has_comma = strchr(opts->mnt_opts[i], ',');
1018 else
1019 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001020
1021 switch (opts->mnt_opts_flags[i]) {
1022 case CONTEXT_MNT:
1023 prefix = CONTEXT_STR;
1024 break;
1025 case FSCONTEXT_MNT:
1026 prefix = FSCONTEXT_STR;
1027 break;
1028 case ROOTCONTEXT_MNT:
1029 prefix = ROOTCONTEXT_STR;
1030 break;
1031 case DEFCONTEXT_MNT:
1032 prefix = DEFCONTEXT_STR;
1033 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001034 case SE_SBLABELSUPP:
1035 seq_putc(m, ',');
1036 seq_puts(m, LABELSUPP_STR);
1037 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001038 default:
1039 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001040 return;
Eric Paris2069f452008-07-04 09:47:13 +10001041 };
1042 /* we need a comma before each option */
1043 seq_putc(m, ',');
1044 seq_puts(m, prefix);
1045 if (has_comma)
1046 seq_putc(m, '\"');
1047 seq_puts(m, opts->mnt_opts[i]);
1048 if (has_comma)
1049 seq_putc(m, '\"');
1050 }
1051}
1052
1053static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1054{
1055 struct security_mnt_opts opts;
1056 int rc;
1057
1058 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001059 if (rc) {
1060 /* before policy load we may get EINVAL, don't show anything */
1061 if (rc == -EINVAL)
1062 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001063 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001064 }
Eric Paris2069f452008-07-04 09:47:13 +10001065
1066 selinux_write_opts(m, &opts);
1067
1068 security_free_mnt_opts(&opts);
1069
1070 return rc;
1071}
1072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073static inline u16 inode_mode_to_security_class(umode_t mode)
1074{
1075 switch (mode & S_IFMT) {
1076 case S_IFSOCK:
1077 return SECCLASS_SOCK_FILE;
1078 case S_IFLNK:
1079 return SECCLASS_LNK_FILE;
1080 case S_IFREG:
1081 return SECCLASS_FILE;
1082 case S_IFBLK:
1083 return SECCLASS_BLK_FILE;
1084 case S_IFDIR:
1085 return SECCLASS_DIR;
1086 case S_IFCHR:
1087 return SECCLASS_CHR_FILE;
1088 case S_IFIFO:
1089 return SECCLASS_FIFO_FILE;
1090
1091 }
1092
1093 return SECCLASS_FILE;
1094}
1095
James Morris13402582005-09-30 14:24:34 -04001096static inline int default_protocol_stream(int protocol)
1097{
1098 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1099}
1100
1101static inline int default_protocol_dgram(int protocol)
1102{
1103 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1104}
1105
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1107{
1108 switch (family) {
1109 case PF_UNIX:
1110 switch (type) {
1111 case SOCK_STREAM:
1112 case SOCK_SEQPACKET:
1113 return SECCLASS_UNIX_STREAM_SOCKET;
1114 case SOCK_DGRAM:
1115 return SECCLASS_UNIX_DGRAM_SOCKET;
1116 }
1117 break;
1118 case PF_INET:
1119 case PF_INET6:
1120 switch (type) {
1121 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001122 if (default_protocol_stream(protocol))
1123 return SECCLASS_TCP_SOCKET;
1124 else
1125 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001127 if (default_protocol_dgram(protocol))
1128 return SECCLASS_UDP_SOCKET;
1129 else
1130 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001131 case SOCK_DCCP:
1132 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001133 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return SECCLASS_RAWIP_SOCKET;
1135 }
1136 break;
1137 case PF_NETLINK:
1138 switch (protocol) {
1139 case NETLINK_ROUTE:
1140 return SECCLASS_NETLINK_ROUTE_SOCKET;
1141 case NETLINK_FIREWALL:
1142 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001143 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1145 case NETLINK_NFLOG:
1146 return SECCLASS_NETLINK_NFLOG_SOCKET;
1147 case NETLINK_XFRM:
1148 return SECCLASS_NETLINK_XFRM_SOCKET;
1149 case NETLINK_SELINUX:
1150 return SECCLASS_NETLINK_SELINUX_SOCKET;
1151 case NETLINK_AUDIT:
1152 return SECCLASS_NETLINK_AUDIT_SOCKET;
1153 case NETLINK_IP6_FW:
1154 return SECCLASS_NETLINK_IP6FW_SOCKET;
1155 case NETLINK_DNRTMSG:
1156 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001157 case NETLINK_KOBJECT_UEVENT:
1158 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 default:
1160 return SECCLASS_NETLINK_SOCKET;
1161 }
1162 case PF_PACKET:
1163 return SECCLASS_PACKET_SOCKET;
1164 case PF_KEY:
1165 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001166 case PF_APPLETALK:
1167 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 }
1169
1170 return SECCLASS_SOCKET;
1171}
1172
1173#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001174static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 u16 tclass,
1176 u32 *sid)
1177{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001178 int rc;
1179 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
Eric Paris828dfe12008-04-17 13:17:49 -04001181 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (!buffer)
1183 return -ENOMEM;
1184
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001185 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1186 if (IS_ERR(path))
1187 rc = PTR_ERR(path);
1188 else {
1189 /* each process gets a /proc/PID/ entry. Strip off the
1190 * PID part to get a valid selinux labeling.
1191 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1192 while (path[1] >= '0' && path[1] <= '9') {
1193 path[1] = '/';
1194 path++;
1195 }
1196 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 free_page((unsigned long)buffer);
1199 return rc;
1200}
1201#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001202static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 u16 tclass,
1204 u32 *sid)
1205{
1206 return -EINVAL;
1207}
1208#endif
1209
1210/* The inode's security attributes must be initialized before first use. */
1211static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1212{
1213 struct superblock_security_struct *sbsec = NULL;
1214 struct inode_security_struct *isec = inode->i_security;
1215 u32 sid;
1216 struct dentry *dentry;
1217#define INITCONTEXTLEN 255
1218 char *context = NULL;
1219 unsigned len = 0;
1220 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 if (isec->initialized)
1223 goto out;
1224
Eric Paris23970742006-09-25 23:32:01 -07001225 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001227 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001230 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 /* Defer initialization until selinux_complete_init,
1232 after the initial policy is loaded and the security
1233 server is ready to handle calls. */
1234 spin_lock(&sbsec->isec_lock);
1235 if (list_empty(&isec->list))
1236 list_add(&isec->list, &sbsec->isec_head);
1237 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001238 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240
1241 switch (sbsec->behavior) {
1242 case SECURITY_FS_USE_XATTR:
1243 if (!inode->i_op->getxattr) {
1244 isec->sid = sbsec->def_sid;
1245 break;
1246 }
1247
1248 /* Need a dentry, since the xattr API requires one.
1249 Life would be simpler if we could just pass the inode. */
1250 if (opt_dentry) {
1251 /* Called from d_instantiate or d_splice_alias. */
1252 dentry = dget(opt_dentry);
1253 } else {
1254 /* Called from selinux_complete_init, try to find a dentry. */
1255 dentry = d_find_alias(inode);
1256 }
1257 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001258 /*
1259 * this is can be hit on boot when a file is accessed
1260 * before the policy is loaded. When we load policy we
1261 * may find inodes that have no dentry on the
1262 * sbsec->isec_head list. No reason to complain as these
1263 * will get fixed up the next time we go through
1264 * inode_doinit with a dentry, before these inodes could
1265 * be used again by userspace.
1266 */
Eric Paris23970742006-09-25 23:32:01 -07001267 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
1269
1270 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001271 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 if (!context) {
1273 rc = -ENOMEM;
1274 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001275 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001277 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1279 context, len);
1280 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001281 kfree(context);
1282
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 /* Need a larger buffer. Query for the right size. */
1284 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1285 NULL, 0);
1286 if (rc < 0) {
1287 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001288 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001291 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (!context) {
1293 rc = -ENOMEM;
1294 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001295 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001297 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 rc = inode->i_op->getxattr(dentry,
1299 XATTR_NAME_SELINUX,
1300 context, len);
1301 }
1302 dput(dentry);
1303 if (rc < 0) {
1304 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001305 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001306 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 -rc, inode->i_sb->s_id, inode->i_ino);
1308 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001309 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 }
1311 /* Map ENODATA to the default file SID */
1312 sid = sbsec->def_sid;
1313 rc = 0;
1314 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001315 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001316 sbsec->def_sid,
1317 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001319 char *dev = inode->i_sb->s_id;
1320 unsigned long ino = inode->i_ino;
1321
1322 if (rc == -EINVAL) {
1323 if (printk_ratelimit())
1324 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1325 "context=%s. This indicates you may need to relabel the inode or the "
1326 "filesystem in question.\n", ino, dev, context);
1327 } else {
1328 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1329 "returned %d for dev=%s ino=%ld\n",
1330 __func__, context, -rc, dev, ino);
1331 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 kfree(context);
1333 /* Leave with the unlabeled SID */
1334 rc = 0;
1335 break;
1336 }
1337 }
1338 kfree(context);
1339 isec->sid = sid;
1340 break;
1341 case SECURITY_FS_USE_TASK:
1342 isec->sid = isec->task_sid;
1343 break;
1344 case SECURITY_FS_USE_TRANS:
1345 /* Default to the fs SID. */
1346 isec->sid = sbsec->sid;
1347
1348 /* Try to obtain a transition SID. */
1349 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001350 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1351 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001353 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 isec->sid = sid;
1355 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001356 case SECURITY_FS_USE_MNTPOINT:
1357 isec->sid = sbsec->mntpoint_sid;
1358 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001360 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 isec->sid = sbsec->sid;
1362
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001363 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Paul Moore913a13b2014-03-19 16:46:18 -04001364 /* We must have a dentry to determine the label on
1365 * procfs inodes */
1366 if (opt_dentry)
1367 /* Called from d_instantiate or
1368 * d_splice_alias. */
1369 dentry = dget(opt_dentry);
1370 else
1371 /* Called from selinux_complete_init, try to
1372 * find a dentry. */
1373 dentry = d_find_alias(inode);
1374 /*
1375 * This can be hit on boot when a file is accessed
1376 * before the policy is loaded. When we load policy we
1377 * may find inodes that have no dentry on the
1378 * sbsec->isec_head list. No reason to complain as
1379 * these will get fixed up the next time we go through
1380 * inode_doinit() with a dentry, before these inodes
1381 * could be used again by userspace.
1382 */
1383 if (!dentry)
1384 goto out_unlock;
1385 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1386 rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
1387 dput(dentry);
1388 if (rc)
1389 goto out_unlock;
1390 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
1392 break;
1393 }
1394
1395 isec->initialized = 1;
1396
Eric Paris23970742006-09-25 23:32:01 -07001397out_unlock:
1398 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399out:
1400 if (isec->sclass == SECCLASS_FILE)
1401 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 return rc;
1403}
1404
1405/* Convert a Linux signal to an access vector. */
1406static inline u32 signal_to_av(int sig)
1407{
1408 u32 perm = 0;
1409
1410 switch (sig) {
1411 case SIGCHLD:
1412 /* Commonly granted from child to parent. */
1413 perm = PROCESS__SIGCHLD;
1414 break;
1415 case SIGKILL:
1416 /* Cannot be caught or ignored */
1417 perm = PROCESS__SIGKILL;
1418 break;
1419 case SIGSTOP:
1420 /* Cannot be caught or ignored */
1421 perm = PROCESS__SIGSTOP;
1422 break;
1423 default:
1424 /* All other signals. */
1425 perm = PROCESS__SIGNAL;
1426 break;
1427 }
1428
1429 return perm;
1430}
1431
David Howells275bb412008-11-14 10:39:19 +11001432/*
David Howellsd84f4f92008-11-14 10:39:23 +11001433 * Check permission between a pair of credentials
1434 * fork check, ptrace check, etc.
1435 */
1436static int cred_has_perm(const struct cred *actor,
1437 const struct cred *target,
1438 u32 perms)
1439{
1440 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1441
1442 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1443}
1444
1445/*
David Howells88e67f32008-11-14 10:39:21 +11001446 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001447 * fork check, ptrace check, etc.
1448 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001449 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001450 */
1451static int task_has_perm(const struct task_struct *tsk1,
1452 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 u32 perms)
1454{
David Howells275bb412008-11-14 10:39:19 +11001455 const struct task_security_struct *__tsec1, *__tsec2;
1456 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
David Howells275bb412008-11-14 10:39:19 +11001458 rcu_read_lock();
1459 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1460 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1461 rcu_read_unlock();
1462 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
David Howells3b11a1d2008-11-14 10:39:26 +11001465/*
1466 * Check permission between current and another task, e.g. signal checks,
1467 * fork check, ptrace check, etc.
1468 * current is the actor and tsk2 is the target
1469 * - this uses current's subjective creds
1470 */
1471static int current_has_perm(const struct task_struct *tsk,
1472 u32 perms)
1473{
1474 u32 sid, tsid;
1475
1476 sid = current_sid();
1477 tsid = task_sid(tsk);
1478 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1479}
1480
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001481#if CAP_LAST_CAP > 63
1482#error Fix SELinux to handle capabilities > 63.
1483#endif
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001486static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001487 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488{
Thomas Liu2bf49692009-07-14 12:14:09 -04001489 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001490 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001491 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001492 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001493 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001494 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Eric Paris50c205f2012-04-04 15:01:43 -04001496 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 ad.u.cap = cap;
1498
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001499 switch (CAP_TO_INDEX(cap)) {
1500 case 0:
1501 sclass = SECCLASS_CAPABILITY;
1502 break;
1503 case 1:
1504 sclass = SECCLASS_CAPABILITY2;
1505 break;
1506 default:
1507 printk(KERN_ERR
1508 "SELinux: out of range capability %d\n", cap);
1509 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001510 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001511 }
Eric Paris06112162008-11-11 22:02:50 +11001512
David Howells275bb412008-11-14 10:39:19 +11001513 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001514 if (audit == SECURITY_CAP_AUDIT) {
1515 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1516 if (rc2)
1517 return rc2;
1518 }
Eric Paris06112162008-11-11 22:02:50 +11001519 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520}
1521
1522/* Check whether a task is allowed to use a system operation. */
1523static int task_has_system(struct task_struct *tsk,
1524 u32 perms)
1525{
David Howells275bb412008-11-14 10:39:19 +11001526 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
David Howells275bb412008-11-14 10:39:19 +11001528 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 SECCLASS_SYSTEM, perms, NULL);
1530}
1531
1532/* Check whether a task has a particular permission to an inode.
1533 The 'adp' parameter is optional and allows other audit
1534 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001535static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 struct inode *inode,
1537 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001538 struct common_audit_data *adp,
1539 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001542 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
David Howellse0e81732009-09-02 09:13:40 +01001544 validate_creds(cred);
1545
Eric Paris828dfe12008-04-17 13:17:49 -04001546 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001547 return 0;
1548
David Howells88e67f32008-11-14 10:39:21 +11001549 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 isec = inode->i_security;
1551
Eric Paris9ade0cf2011-04-25 16:26:29 -04001552 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553}
1554
1555/* Same as inode_has_perm, but pass explicit audit data containing
1556 the dentry to help the auditing code to more easily generate the
1557 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001558static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 struct dentry *dentry,
1560 u32 av)
1561{
1562 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001563 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001564
Eric Paris50c205f2012-04-04 15:01:43 -04001565 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001566 ad.u.dentry = dentry;
1567 return inode_has_perm(cred, inode, av, &ad, 0);
1568}
1569
1570/* Same as inode_has_perm, but pass explicit audit data containing
1571 the path to help the auditing code to more easily generate the
1572 pathname if needed. */
1573static inline int path_has_perm(const struct cred *cred,
1574 struct path *path,
1575 u32 av)
1576{
1577 struct inode *inode = path->dentry->d_inode;
1578 struct common_audit_data ad;
1579
Eric Paris50c205f2012-04-04 15:01:43 -04001580 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001581 ad.u.path = *path;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001582 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583}
1584
1585/* Check whether a task can use an open file descriptor to
1586 access an inode in a given way. Check access to the
1587 descriptor itself, and then use dentry_has_perm to
1588 check a particular permission to the file.
1589 Access to the descriptor is implicitly granted if it
1590 has the same SID as the process. If av is zero, then
1591 access to the file is not checked, e.g. for cases
1592 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001593static int file_has_perm(const struct cred *cred,
1594 struct file *file,
1595 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001598 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001599 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001600 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 int rc;
1602
Eric Paris50c205f2012-04-04 15:01:43 -04001603 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001604 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
David Howells275bb412008-11-14 10:39:19 +11001606 if (sid != fsec->sid) {
1607 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 SECCLASS_FD,
1609 FD__USE,
1610 &ad);
1611 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001612 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 }
1614
1615 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001616 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001618 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
David Howells88e67f32008-11-14 10:39:21 +11001620out:
1621 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622}
1623
1624/* Check whether a task can create a file. */
1625static int may_create(struct inode *dir,
1626 struct dentry *dentry,
1627 u16 tclass)
1628{
Paul Moore5fb49872010-04-22 14:46:19 -04001629 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 struct inode_security_struct *dsec;
1631 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001632 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001633 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 int rc;
1635
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 dsec = dir->i_security;
1637 sbsec = dir->i_sb->s_security;
1638
David Howells275bb412008-11-14 10:39:19 +11001639 sid = tsec->sid;
1640 newsid = tsec->create_sid;
1641
Eric Paris50c205f2012-04-04 15:01:43 -04001642 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001643 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
David Howells275bb412008-11-14 10:39:19 +11001645 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 DIR__ADD_NAME | DIR__SEARCH,
1647 &ad);
1648 if (rc)
1649 return rc;
1650
David P. Quigleycd895962009-01-16 09:22:04 -05001651 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001652 rc = security_transition_sid(sid, dsec->sid, tclass,
1653 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 if (rc)
1655 return rc;
1656 }
1657
David Howells275bb412008-11-14 10:39:19 +11001658 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 if (rc)
1660 return rc;
1661
1662 return avc_has_perm(newsid, sbsec->sid,
1663 SECCLASS_FILESYSTEM,
1664 FILESYSTEM__ASSOCIATE, &ad);
1665}
1666
Michael LeMay4eb582c2006-06-26 00:24:57 -07001667/* Check whether a task can create a key. */
1668static int may_create_key(u32 ksid,
1669 struct task_struct *ctx)
1670{
David Howells275bb412008-11-14 10:39:19 +11001671 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001672
David Howells275bb412008-11-14 10:39:19 +11001673 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001674}
1675
Eric Paris828dfe12008-04-17 13:17:49 -04001676#define MAY_LINK 0
1677#define MAY_UNLINK 1
1678#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
1680/* Check whether a task can link, unlink, or rmdir a file/directory. */
1681static int may_link(struct inode *dir,
1682 struct dentry *dentry,
1683 int kind)
1684
1685{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001687 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001688 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 u32 av;
1690 int rc;
1691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 dsec = dir->i_security;
1693 isec = dentry->d_inode->i_security;
1694
Eric Paris50c205f2012-04-04 15:01:43 -04001695 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001696 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
1698 av = DIR__SEARCH;
1699 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001700 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 if (rc)
1702 return rc;
1703
1704 switch (kind) {
1705 case MAY_LINK:
1706 av = FILE__LINK;
1707 break;
1708 case MAY_UNLINK:
1709 av = FILE__UNLINK;
1710 break;
1711 case MAY_RMDIR:
1712 av = DIR__RMDIR;
1713 break;
1714 default:
Eric Paris744ba352008-04-17 11:52:44 -04001715 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1716 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 return 0;
1718 }
1719
David Howells275bb412008-11-14 10:39:19 +11001720 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 return rc;
1722}
1723
1724static inline int may_rename(struct inode *old_dir,
1725 struct dentry *old_dentry,
1726 struct inode *new_dir,
1727 struct dentry *new_dentry)
1728{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001730 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001731 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 u32 av;
1733 int old_is_dir, new_is_dir;
1734 int rc;
1735
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 old_dsec = old_dir->i_security;
1737 old_isec = old_dentry->d_inode->i_security;
1738 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1739 new_dsec = new_dir->i_security;
1740
Eric Paris50c205f2012-04-04 15:01:43 -04001741 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
Eric Parisa2694342011-04-25 13:10:27 -04001743 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001744 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1746 if (rc)
1747 return rc;
David Howells275bb412008-11-14 10:39:19 +11001748 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 old_isec->sclass, FILE__RENAME, &ad);
1750 if (rc)
1751 return rc;
1752 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001753 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 old_isec->sclass, DIR__REPARENT, &ad);
1755 if (rc)
1756 return rc;
1757 }
1758
Eric Parisa2694342011-04-25 13:10:27 -04001759 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 av = DIR__ADD_NAME | DIR__SEARCH;
1761 if (new_dentry->d_inode)
1762 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001763 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 if (rc)
1765 return rc;
1766 if (new_dentry->d_inode) {
1767 new_isec = new_dentry->d_inode->i_security;
1768 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001769 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 new_isec->sclass,
1771 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1772 if (rc)
1773 return rc;
1774 }
1775
1776 return 0;
1777}
1778
1779/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001780static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 struct super_block *sb,
1782 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001783 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001786 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001789 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790}
1791
1792/* Convert a Linux mode and permission mask to an access vector. */
1793static inline u32 file_mask_to_av(int mode, int mask)
1794{
1795 u32 av = 0;
1796
Al Virodba19c62011-07-25 20:49:29 -04001797 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 if (mask & MAY_EXEC)
1799 av |= FILE__EXECUTE;
1800 if (mask & MAY_READ)
1801 av |= FILE__READ;
1802
1803 if (mask & MAY_APPEND)
1804 av |= FILE__APPEND;
1805 else if (mask & MAY_WRITE)
1806 av |= FILE__WRITE;
1807
1808 } else {
1809 if (mask & MAY_EXEC)
1810 av |= DIR__SEARCH;
1811 if (mask & MAY_WRITE)
1812 av |= DIR__WRITE;
1813 if (mask & MAY_READ)
1814 av |= DIR__READ;
1815 }
1816
1817 return av;
1818}
1819
1820/* Convert a Linux file to an access vector. */
1821static inline u32 file_to_av(struct file *file)
1822{
1823 u32 av = 0;
1824
1825 if (file->f_mode & FMODE_READ)
1826 av |= FILE__READ;
1827 if (file->f_mode & FMODE_WRITE) {
1828 if (file->f_flags & O_APPEND)
1829 av |= FILE__APPEND;
1830 else
1831 av |= FILE__WRITE;
1832 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001833 if (!av) {
1834 /*
1835 * Special file opened with flags 3 for ioctl-only use.
1836 */
1837 av = FILE__IOCTL;
1838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
1840 return av;
1841}
1842
Eric Paris8b6a5a32008-10-29 17:06:46 -04001843/*
1844 * Convert a file to an access vector and include the correct open
1845 * open permission.
1846 */
1847static inline u32 open_file_to_av(struct file *file)
1848{
1849 u32 av = file_to_av(file);
1850
Eric Paris49b7b8d2010-07-23 11:44:09 -04001851 if (selinux_policycap_openperm)
1852 av |= FILE__OPEN;
1853
Eric Paris8b6a5a32008-10-29 17:06:46 -04001854 return av;
1855}
1856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857/* Hook functions begin here. */
1858
Ingo Molnar9e488582009-05-07 19:26:19 +10001859static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001860 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 int rc;
1863
Ingo Molnar9e488582009-05-07 19:26:19 +10001864 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 if (rc)
1866 return rc;
1867
Eric Paris69f594a2012-01-03 12:25:15 -05001868 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001869 u32 sid = current_sid();
1870 u32 csid = task_sid(child);
1871 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001872 }
1873
David Howells3b11a1d2008-11-14 10:39:26 +11001874 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001875}
1876
1877static int selinux_ptrace_traceme(struct task_struct *parent)
1878{
1879 int rc;
1880
Eric Paris200ac532009-02-12 15:01:04 -05001881 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001882 if (rc)
1883 return rc;
1884
1885 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886}
1887
1888static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001889 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
1891 int error;
1892
David Howells3b11a1d2008-11-14 10:39:26 +11001893 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 if (error)
1895 return error;
1896
Eric Paris200ac532009-02-12 15:01:04 -05001897 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898}
1899
David Howellsd84f4f92008-11-14 10:39:23 +11001900static int selinux_capset(struct cred *new, const struct cred *old,
1901 const kernel_cap_t *effective,
1902 const kernel_cap_t *inheritable,
1903 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
1905 int error;
1906
Eric Paris200ac532009-02-12 15:01:04 -05001907 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001908 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (error)
1910 return error;
1911
David Howellsd84f4f92008-11-14 10:39:23 +11001912 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913}
1914
James Morris5626d3e2009-01-30 10:05:06 +11001915/*
1916 * (This comment used to live with the selinux_task_setuid hook,
1917 * which was removed).
1918 *
1919 * Since setuid only affects the current process, and since the SELinux
1920 * controls are not based on the Linux identity attributes, SELinux does not
1921 * need to control this operation. However, SELinux does control the use of
1922 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1923 */
1924
Eric Paris6a9de492012-01-03 12:25:14 -05001925static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1926 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927{
1928 int rc;
1929
Eric Paris6a9de492012-01-03 12:25:14 -05001930 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 if (rc)
1932 return rc;
1933
Eric Paris6a9de492012-01-03 12:25:14 -05001934 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935}
1936
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1938{
David Howells88e67f32008-11-14 10:39:21 +11001939 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 int rc = 0;
1941
1942 if (!sb)
1943 return 0;
1944
1945 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001946 case Q_SYNC:
1947 case Q_QUOTAON:
1948 case Q_QUOTAOFF:
1949 case Q_SETINFO:
1950 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001951 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001952 break;
1953 case Q_GETFMT:
1954 case Q_GETINFO:
1955 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001956 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001957 break;
1958 default:
1959 rc = 0; /* let the kernel handle invalid cmds */
1960 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 }
1962 return rc;
1963}
1964
1965static int selinux_quota_on(struct dentry *dentry)
1966{
David Howells88e67f32008-11-14 10:39:21 +11001967 const struct cred *cred = current_cred();
1968
Eric Paris2875fa02011-04-28 16:04:24 -04001969 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970}
1971
Eric Paris12b30522010-11-15 18:36:29 -05001972static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973{
1974 int rc;
1975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08001977 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
1978 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001979 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1980 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001981 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
1982 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
1983 /* Set level of messages printed to console */
1984 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04001985 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1986 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001987 case SYSLOG_ACTION_CLOSE: /* Close log */
1988 case SYSLOG_ACTION_OPEN: /* Open log */
1989 case SYSLOG_ACTION_READ: /* Read from log */
1990 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
1991 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001992 default:
1993 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1994 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
1996 return rc;
1997}
1998
1999/*
2000 * Check that a process has enough memory to allocate a new virtual
2001 * mapping. 0 means there is enough memory for the allocation to
2002 * succeed and -ENOMEM implies there is not.
2003 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 * Do not audit the selinux permission check, as this is applied to all
2005 * processes that allocate mappings.
2006 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002007static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008{
2009 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Eric Paris6a9de492012-01-03 12:25:14 -05002011 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002012 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 if (rc == 0)
2014 cap_sys_admin = 1;
2015
Alan Cox34b4e4a2007-08-22 14:01:28 -07002016 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017}
2018
2019/* binprm security operations */
2020
David Howellsa6f76f22008-11-14 10:39:24 +11002021static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
David Howellsa6f76f22008-11-14 10:39:24 +11002023 const struct task_security_struct *old_tsec;
2024 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002026 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002027 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 int rc;
2029
Eric Paris200ac532009-02-12 15:01:04 -05002030 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 if (rc)
2032 return rc;
2033
David Howellsa6f76f22008-11-14 10:39:24 +11002034 /* SELinux context only depends on initial program or script and not
2035 * the script interpreter */
2036 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 return 0;
2038
David Howellsa6f76f22008-11-14 10:39:24 +11002039 old_tsec = current_security();
2040 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 isec = inode->i_security;
2042
2043 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002044 new_tsec->sid = old_tsec->sid;
2045 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Michael LeMay28eba5b2006-06-27 02:53:42 -07002047 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002048 new_tsec->create_sid = 0;
2049 new_tsec->keycreate_sid = 0;
2050 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
David Howellsa6f76f22008-11-14 10:39:24 +11002052 if (old_tsec->exec_sid) {
2053 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002055 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002056
2057 /*
2058 * Minimize confusion: if no_new_privs and a transition is
2059 * explicitly requested, then fail the exec.
2060 */
2061 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2062 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 } else {
2064 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002065 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002066 SECCLASS_PROCESS, NULL,
2067 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 if (rc)
2069 return rc;
2070 }
2071
Eric Paris50c205f2012-04-04 15:01:43 -04002072 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002073 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002075 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2076 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002077 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
David Howellsa6f76f22008-11-14 10:39:24 +11002079 if (new_tsec->sid == old_tsec->sid) {
2080 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2082 if (rc)
2083 return rc;
2084 } else {
2085 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002086 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2088 if (rc)
2089 return rc;
2090
David Howellsa6f76f22008-11-14 10:39:24 +11002091 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2093 if (rc)
2094 return rc;
2095
David Howellsa6f76f22008-11-14 10:39:24 +11002096 /* Check for shared state */
2097 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2098 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2099 SECCLASS_PROCESS, PROCESS__SHARE,
2100 NULL);
2101 if (rc)
2102 return -EPERM;
2103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
David Howellsa6f76f22008-11-14 10:39:24 +11002105 /* Make sure that anyone attempting to ptrace over a task that
2106 * changes its SID has the appropriate permit */
2107 if (bprm->unsafe &
2108 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2109 struct task_struct *tracer;
2110 struct task_security_struct *sec;
2111 u32 ptsid = 0;
2112
2113 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002114 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002115 if (likely(tracer != NULL)) {
2116 sec = __task_cred(tracer)->security;
2117 ptsid = sec->sid;
2118 }
2119 rcu_read_unlock();
2120
2121 if (ptsid != 0) {
2122 rc = avc_has_perm(ptsid, new_tsec->sid,
2123 SECCLASS_PROCESS,
2124 PROCESS__PTRACE, NULL);
2125 if (rc)
2126 return -EPERM;
2127 }
2128 }
2129
2130 /* Clear any possibly unsafe personality bits on exec: */
2131 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 }
2133
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 return 0;
2135}
2136
Eric Paris828dfe12008-04-17 13:17:49 -04002137static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138{
Paul Moore5fb49872010-04-22 14:46:19 -04002139 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002140 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 int atsecure = 0;
2142
David Howells275bb412008-11-14 10:39:19 +11002143 sid = tsec->sid;
2144 osid = tsec->osid;
2145
2146 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 /* Enable secure mode for SIDs transitions unless
2148 the noatsecure permission is granted between
2149 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002150 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002151 SECCLASS_PROCESS,
2152 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 }
2154
Eric Paris200ac532009-02-12 15:01:04 -05002155 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156}
2157
Al Viroc3c073f2012-08-21 22:32:06 -04002158static int match_file(const void *p, struct file *file, unsigned fd)
2159{
2160 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2161}
2162
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002164static inline void flush_unauthorized_files(const struct cred *cred,
2165 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002168 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002169 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002170 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002172 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002174 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002175 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002176 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002177
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 /* Revalidate access to controlling tty.
Eric Paris602a8dd2012-04-04 15:01:42 -04002179 Use path_has_perm on the tty path directly rather
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 than using file_has_perm, as this particular open
2181 file may belong to another process and we are only
2182 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002183 file_priv = list_first_entry(&tty->tty_files,
2184 struct tty_file_private, list);
2185 file = file_priv->file;
Eric Paris602a8dd2012-04-04 15:01:42 -04002186 if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002187 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002189 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002190 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002192 /* Reset controlling tty. */
2193 if (drop_tty)
2194 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
2196 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002197 n = iterate_fd(files, 0, match_file, cred);
2198 if (!n) /* none found? */
2199 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Al Viroc3c073f2012-08-21 22:32:06 -04002201 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002202 if (IS_ERR(devnull))
2203 devnull = NULL;
2204 /* replace all the matching ones with this */
2205 do {
2206 replace_fd(n - 1, devnull, 0);
2207 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2208 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002209 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210}
2211
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212/*
David Howellsa6f76f22008-11-14 10:39:24 +11002213 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 */
David Howellsa6f76f22008-11-14 10:39:24 +11002215static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
David Howellsa6f76f22008-11-14 10:39:24 +11002217 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 int rc, i;
2220
David Howellsa6f76f22008-11-14 10:39:24 +11002221 new_tsec = bprm->cred->security;
2222 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 return;
2224
2225 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002226 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
David Howellsa6f76f22008-11-14 10:39:24 +11002228 /* Always clear parent death signal on SID transitions. */
2229 current->pdeath_signal = 0;
2230
2231 /* Check whether the new SID can inherit resource limits from the old
2232 * SID. If not, reset all soft limits to the lower of the current
2233 * task's hard limit and the init task's soft limit.
2234 *
2235 * Note that the setting of hard limits (even to lower them) can be
2236 * controlled by the setrlimit check. The inclusion of the init task's
2237 * soft limit into the computation is to avoid resetting soft limits
2238 * higher than the default soft limit for cases where the default is
2239 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2240 */
2241 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2242 PROCESS__RLIMITINH, NULL);
2243 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002244 /* protect against do_prlimit() */
2245 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002246 for (i = 0; i < RLIM_NLIMITS; i++) {
2247 rlim = current->signal->rlim + i;
2248 initrlim = init_task.signal->rlim + i;
2249 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2250 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002251 task_unlock(current);
2252 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002253 }
2254}
2255
2256/*
2257 * Clean up the process immediately after the installation of new credentials
2258 * due to exec
2259 */
2260static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2261{
2262 const struct task_security_struct *tsec = current_security();
2263 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002264 u32 osid, sid;
2265 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002266
David Howellsa6f76f22008-11-14 10:39:24 +11002267 osid = tsec->osid;
2268 sid = tsec->sid;
2269
2270 if (sid == osid)
2271 return;
2272
2273 /* Check whether the new SID can inherit signal state from the old SID.
2274 * If not, clear itimers to avoid subsequent signal generation and
2275 * flush and unblock signals.
2276 *
2277 * This must occur _after_ the task SID has been updated so that any
2278 * kill done after the flush will be checked against the new SID.
2279 */
2280 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 if (rc) {
2282 memset(&itimer, 0, sizeof itimer);
2283 for (i = 0; i < 3; i++)
2284 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002286 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2287 __flush_signals(current);
2288 flush_signal_handlers(current, 1);
2289 sigemptyset(&current->blocked);
2290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 spin_unlock_irq(&current->sighand->siglock);
2292 }
2293
David Howellsa6f76f22008-11-14 10:39:24 +11002294 /* Wake up the parent if it is waiting so that it can recheck
2295 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002296 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002297 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002298 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299}
2300
2301/* superblock security operations */
2302
2303static int selinux_sb_alloc_security(struct super_block *sb)
2304{
2305 return superblock_alloc_security(sb);
2306}
2307
2308static void selinux_sb_free_security(struct super_block *sb)
2309{
2310 superblock_free_security(sb);
2311}
2312
2313static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2314{
2315 if (plen > olen)
2316 return 0;
2317
2318 return !memcmp(prefix, option, plen);
2319}
2320
2321static inline int selinux_option(char *option, int len)
2322{
Eric Paris832cbd92008-04-01 13:24:09 -04002323 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2324 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2325 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002326 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2327 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328}
2329
2330static inline void take_option(char **to, char *from, int *first, int len)
2331{
2332 if (!*first) {
2333 **to = ',';
2334 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002335 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 *first = 0;
2337 memcpy(*to, from, len);
2338 *to += len;
2339}
2340
Eric Paris828dfe12008-04-17 13:17:49 -04002341static inline void take_selinux_option(char **to, char *from, int *first,
2342 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002343{
2344 int current_size = 0;
2345
2346 if (!*first) {
2347 **to = '|';
2348 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002349 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002350 *first = 0;
2351
2352 while (current_size < len) {
2353 if (*from != '"') {
2354 **to = *from;
2355 *to += 1;
2356 }
2357 from += 1;
2358 current_size += 1;
2359 }
2360}
2361
Eric Parise0007522008-03-05 10:31:54 -05002362static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
2364 int fnosec, fsec, rc = 0;
2365 char *in_save, *in_curr, *in_end;
2366 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002367 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368
2369 in_curr = orig;
2370 sec_curr = copy;
2371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2373 if (!nosec) {
2374 rc = -ENOMEM;
2375 goto out;
2376 }
2377
2378 nosec_save = nosec;
2379 fnosec = fsec = 1;
2380 in_save = in_end = orig;
2381
2382 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002383 if (*in_end == '"')
2384 open_quote = !open_quote;
2385 if ((*in_end == ',' && open_quote == 0) ||
2386 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 int len = in_end - in_curr;
2388
2389 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002390 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 else
2392 take_option(&nosec, in_curr, &fnosec, len);
2393
2394 in_curr = in_end + 1;
2395 }
2396 } while (*in_end++);
2397
Eric Paris6931dfc2005-06-30 02:58:51 -07002398 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002399 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400out:
2401 return rc;
2402}
2403
Eric Paris026eb162011-03-03 16:09:14 -05002404static int selinux_sb_remount(struct super_block *sb, void *data)
2405{
2406 int rc, i, *flags;
2407 struct security_mnt_opts opts;
2408 char *secdata, **mount_options;
2409 struct superblock_security_struct *sbsec = sb->s_security;
2410
2411 if (!(sbsec->flags & SE_SBINITIALIZED))
2412 return 0;
2413
2414 if (!data)
2415 return 0;
2416
2417 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2418 return 0;
2419
2420 security_init_mnt_opts(&opts);
2421 secdata = alloc_secdata();
2422 if (!secdata)
2423 return -ENOMEM;
2424 rc = selinux_sb_copy_data(data, secdata);
2425 if (rc)
2426 goto out_free_secdata;
2427
2428 rc = selinux_parse_opts_str(secdata, &opts);
2429 if (rc)
2430 goto out_free_secdata;
2431
2432 mount_options = opts.mnt_opts;
2433 flags = opts.mnt_opts_flags;
2434
2435 for (i = 0; i < opts.num_mnt_opts; i++) {
2436 u32 sid;
2437 size_t len;
2438
2439 if (flags[i] == SE_SBLABELSUPP)
2440 continue;
2441 len = strlen(mount_options[i]);
2442 rc = security_context_to_sid(mount_options[i], len, &sid);
2443 if (rc) {
2444 printk(KERN_WARNING "SELinux: security_context_to_sid"
2445 "(%s) failed for (dev %s, type %s) errno=%d\n",
2446 mount_options[i], sb->s_id, sb->s_type->name, rc);
2447 goto out_free_opts;
2448 }
2449 rc = -EINVAL;
2450 switch (flags[i]) {
2451 case FSCONTEXT_MNT:
2452 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2453 goto out_bad_option;
2454 break;
2455 case CONTEXT_MNT:
2456 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2457 goto out_bad_option;
2458 break;
2459 case ROOTCONTEXT_MNT: {
2460 struct inode_security_struct *root_isec;
2461 root_isec = sb->s_root->d_inode->i_security;
2462
2463 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2464 goto out_bad_option;
2465 break;
2466 }
2467 case DEFCONTEXT_MNT:
2468 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2469 goto out_bad_option;
2470 break;
2471 default:
2472 goto out_free_opts;
2473 }
2474 }
2475
2476 rc = 0;
2477out_free_opts:
2478 security_free_mnt_opts(&opts);
2479out_free_secdata:
2480 free_secdata(secdata);
2481 return rc;
2482out_bad_option:
2483 printk(KERN_WARNING "SELinux: unable to change security options "
2484 "during remount (dev %s, type=%s)\n", sb->s_id,
2485 sb->s_type->name);
2486 goto out_free_opts;
2487}
2488
James Morris12204e22008-12-19 10:44:42 +11002489static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490{
David Howells88e67f32008-11-14 10:39:21 +11002491 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002492 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 int rc;
2494
2495 rc = superblock_doinit(sb, data);
2496 if (rc)
2497 return rc;
2498
James Morris74192242008-12-19 11:41:10 +11002499 /* Allow all mounts performed by the kernel */
2500 if (flags & MS_KERNMOUNT)
2501 return 0;
2502
Eric Paris50c205f2012-04-04 15:01:43 -04002503 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002504 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002505 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506}
2507
David Howells726c3342006-06-23 02:02:58 -07002508static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509{
David Howells88e67f32008-11-14 10:39:21 +11002510 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002511 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
Eric Paris50c205f2012-04-04 15:01:43 -04002513 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002514 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002515 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516}
2517
Al Viro808d4e32012-10-11 11:42:01 -04002518static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002519 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002520 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002521 unsigned long flags,
2522 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523{
David Howells88e67f32008-11-14 10:39:21 +11002524 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
2526 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002527 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002528 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 else
Eric Paris2875fa02011-04-28 16:04:24 -04002530 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531}
2532
2533static int selinux_umount(struct vfsmount *mnt, int flags)
2534{
David Howells88e67f32008-11-14 10:39:21 +11002535 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
David Howells88e67f32008-11-14 10:39:21 +11002537 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002538 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539}
2540
2541/* inode security operations */
2542
2543static int selinux_inode_alloc_security(struct inode *inode)
2544{
2545 return inode_alloc_security(inode);
2546}
2547
2548static void selinux_inode_free_security(struct inode *inode)
2549{
2550 inode_free_security(inode);
2551}
2552
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002553static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002554 const struct qstr *qstr, char **name,
2555 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002556{
Paul Moore5fb49872010-04-22 14:46:19 -04002557 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002558 struct inode_security_struct *dsec;
2559 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002560 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002561 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002562 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002563
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002564 dsec = dir->i_security;
2565 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002566
David Howells275bb412008-11-14 10:39:19 +11002567 sid = tsec->sid;
2568 newsid = tsec->create_sid;
2569
Eric Paris415103f2010-12-02 16:13:40 -05002570 if ((sbsec->flags & SE_SBINITIALIZED) &&
2571 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2572 newsid = sbsec->mntpoint_sid;
2573 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002574 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002575 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002576 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002577 if (rc) {
2578 printk(KERN_WARNING "%s: "
2579 "security_transition_sid failed, rc=%d (dev=%s "
2580 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002581 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002582 -rc, inode->i_sb->s_id, inode->i_ino);
2583 return rc;
2584 }
2585 }
2586
Eric Paris296fddf2006-09-25 23:32:00 -07002587 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002588 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002589 struct inode_security_struct *isec = inode->i_security;
2590 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2591 isec->sid = newsid;
2592 isec->initialized = 1;
2593 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002594
David P. Quigleycd895962009-01-16 09:22:04 -05002595 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002596 return -EOPNOTSUPP;
2597
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002598 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002599 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002600 if (!namep)
2601 return -ENOMEM;
2602 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002603 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002604
2605 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002606 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002607 if (rc) {
2608 kfree(namep);
2609 return rc;
2610 }
2611 *value = context;
2612 *len = clen;
2613 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002614
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002615 return 0;
2616}
2617
Al Viro4acdaf22011-07-26 01:42:34 -04002618static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619{
2620 return may_create(dir, dentry, SECCLASS_FILE);
2621}
2622
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2624{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 return may_link(dir, old_dentry, MAY_LINK);
2626}
2627
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2629{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 return may_link(dir, dentry, MAY_UNLINK);
2631}
2632
2633static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2634{
2635 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2636}
2637
Al Viro18bb1db2011-07-26 01:41:39 -04002638static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
2640 return may_create(dir, dentry, SECCLASS_DIR);
2641}
2642
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2644{
2645 return may_link(dir, dentry, MAY_RMDIR);
2646}
2647
Al Viro1a67aaf2011-07-26 01:52:52 -04002648static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2651}
2652
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002654 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655{
2656 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2657}
2658
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659static int selinux_inode_readlink(struct dentry *dentry)
2660{
David Howells88e67f32008-11-14 10:39:21 +11002661 const struct cred *cred = current_cred();
2662
Eric Paris2875fa02011-04-28 16:04:24 -04002663 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664}
2665
2666static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2667{
David Howells88e67f32008-11-14 10:39:21 +11002668 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Eric Paris2875fa02011-04-28 16:04:24 -04002670 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671}
2672
Eric Parisd4cf970d2012-04-04 15:01:42 -04002673static noinline int audit_inode_permission(struct inode *inode,
2674 u32 perms, u32 audited, u32 denied,
2675 unsigned flags)
2676{
2677 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002678 struct inode_security_struct *isec = inode->i_security;
2679 int rc;
2680
Eric Paris50c205f2012-04-04 15:01:43 -04002681 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002682 ad.u.inode = inode;
2683
2684 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
2685 audited, denied, &ad, flags);
2686 if (rc)
2687 return rc;
2688 return 0;
2689}
2690
Al Viroe74f71e2011-06-20 19:38:15 -04002691static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692{
David Howells88e67f32008-11-14 10:39:21 +11002693 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002694 u32 perms;
2695 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002696 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002697 struct inode_security_struct *isec;
2698 u32 sid;
2699 struct av_decision avd;
2700 int rc, rc2;
2701 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702
Eric Parisb782e0a2010-07-23 11:44:03 -04002703 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002704 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2705
Eric Parisb782e0a2010-07-23 11:44:03 -04002706 /* No permission to check. Existence test. */
2707 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Eric Paris2e334052012-04-04 15:01:42 -04002710 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002711
Eric Paris2e334052012-04-04 15:01:42 -04002712 if (unlikely(IS_PRIVATE(inode)))
2713 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002714
2715 perms = file_mask_to_av(inode->i_mode, mask);
2716
Eric Paris2e334052012-04-04 15:01:42 -04002717 sid = cred_sid(cred);
2718 isec = inode->i_security;
2719
2720 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2721 audited = avc_audit_required(perms, &avd, rc,
2722 from_access ? FILE__AUDIT_ACCESS : 0,
2723 &denied);
2724 if (likely(!audited))
2725 return rc;
2726
Eric Parisd4cf970d2012-04-04 15:01:42 -04002727 rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002728 if (rc2)
2729 return rc2;
2730 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
2733static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2734{
David Howells88e67f32008-11-14 10:39:21 +11002735 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002736 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002737 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002739 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2740 if (ia_valid & ATTR_FORCE) {
2741 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2742 ATTR_FORCE);
2743 if (!ia_valid)
2744 return 0;
2745 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002747 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2748 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002749 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
Eric Paris3d2195c2012-07-06 14:13:30 -04002751 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002752 av |= FILE__OPEN;
2753
2754 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755}
2756
2757static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2758{
David Howells88e67f32008-11-14 10:39:21 +11002759 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002760 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002761
Eric Paris2875fa02011-04-28 16:04:24 -04002762 path.dentry = dentry;
2763 path.mnt = mnt;
2764
2765 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766}
2767
David Howells8f0cfa52008-04-29 00:59:41 -07002768static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002769{
David Howells88e67f32008-11-14 10:39:21 +11002770 const struct cred *cred = current_cred();
2771
Serge E. Hallynb5376772007-10-16 23:31:36 -07002772 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2773 sizeof XATTR_SECURITY_PREFIX - 1)) {
2774 if (!strcmp(name, XATTR_NAME_CAPS)) {
2775 if (!capable(CAP_SETFCAP))
2776 return -EPERM;
2777 } else if (!capable(CAP_SYS_ADMIN)) {
2778 /* A different attribute in the security namespace.
2779 Restrict to administrator. */
2780 return -EPERM;
2781 }
2782 }
2783
2784 /* Not an attribute we recognize, so just check the
2785 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002786 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002787}
2788
David Howells8f0cfa52008-04-29 00:59:41 -07002789static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2790 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 struct inode *inode = dentry->d_inode;
2793 struct inode_security_struct *isec = inode->i_security;
2794 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002795 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002796 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 int rc = 0;
2798
Serge E. Hallynb5376772007-10-16 23:31:36 -07002799 if (strcmp(name, XATTR_NAME_SELINUX))
2800 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002803 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 return -EOPNOTSUPP;
2805
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002806 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return -EPERM;
2808
Eric Paris50c205f2012-04-04 15:01:43 -04002809 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002810 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811
David Howells275bb412008-11-14 10:39:19 +11002812 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 FILE__RELABELFROM, &ad);
2814 if (rc)
2815 return rc;
2816
2817 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002818 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002819 if (!capable(CAP_MAC_ADMIN)) {
2820 struct audit_buffer *ab;
2821 size_t audit_size;
2822 const char *str;
2823
2824 /* We strip a nul only if it is at the end, otherwise the
2825 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002826 if (value) {
2827 str = value;
2828 if (str[size - 1] == '\0')
2829 audit_size = size - 1;
2830 else
2831 audit_size = size;
2832 } else {
2833 str = "";
2834 audit_size = 0;
2835 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002836 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2837 audit_log_format(ab, "op=setxattr invalid_context=");
2838 audit_log_n_untrustedstring(ab, value, audit_size);
2839 audit_log_end(ab);
2840
Stephen Smalley12b29f32008-05-07 13:03:20 -04002841 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002842 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002843 rc = security_context_to_sid_force(value, size, &newsid);
2844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 if (rc)
2846 return rc;
2847
David Howells275bb412008-11-14 10:39:19 +11002848 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 FILE__RELABELTO, &ad);
2850 if (rc)
2851 return rc;
2852
David Howells275bb412008-11-14 10:39:19 +11002853 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002854 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 if (rc)
2856 return rc;
2857
2858 return avc_has_perm(newsid,
2859 sbsec->sid,
2860 SECCLASS_FILESYSTEM,
2861 FILESYSTEM__ASSOCIATE,
2862 &ad);
2863}
2864
David Howells8f0cfa52008-04-29 00:59:41 -07002865static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002866 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002867 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
2869 struct inode *inode = dentry->d_inode;
2870 struct inode_security_struct *isec = inode->i_security;
2871 u32 newsid;
2872 int rc;
2873
2874 if (strcmp(name, XATTR_NAME_SELINUX)) {
2875 /* Not an attribute we recognize, so nothing to do. */
2876 return;
2877 }
2878
Stephen Smalley12b29f32008-05-07 13:03:20 -04002879 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002881 printk(KERN_ERR "SELinux: unable to map context to SID"
2882 "for (%s, %lu), rc=%d\n",
2883 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 return;
2885 }
2886
2887 isec->sid = newsid;
2888 return;
2889}
2890
David Howells8f0cfa52008-04-29 00:59:41 -07002891static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892{
David Howells88e67f32008-11-14 10:39:21 +11002893 const struct cred *cred = current_cred();
2894
Eric Paris2875fa02011-04-28 16:04:24 -04002895 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896}
2897
Eric Paris828dfe12008-04-17 13:17:49 -04002898static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
David Howells88e67f32008-11-14 10:39:21 +11002900 const struct cred *cred = current_cred();
2901
Eric Paris2875fa02011-04-28 16:04:24 -04002902 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903}
2904
David Howells8f0cfa52008-04-29 00:59:41 -07002905static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002907 if (strcmp(name, XATTR_NAME_SELINUX))
2908 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909
2910 /* No one is allowed to remove a SELinux security label.
2911 You can change the label, but all data must be labeled. */
2912 return -EACCES;
2913}
2914
James Morrisd381d8a2005-10-30 14:59:22 -08002915/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002916 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002917 *
2918 * Permission check is handled by selinux_inode_getxattr hook.
2919 */
David P. Quigley42492592008-02-04 22:29:39 -08002920static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921{
David P. Quigley42492592008-02-04 22:29:39 -08002922 u32 size;
2923 int error;
2924 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002927 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2928 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002930 /*
2931 * If the caller has CAP_MAC_ADMIN, then get the raw context
2932 * value even if it is not defined by current policy; otherwise,
2933 * use the in-core value under current policy.
2934 * Use the non-auditing forms of the permission checks since
2935 * getxattr may be called by unprivileged processes commonly
2936 * and lack of permission just means that we fall back to the
2937 * in-core context value, not a denial.
2938 */
Eric Paris6a9de492012-01-03 12:25:14 -05002939 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002940 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002941 if (!error)
2942 error = security_sid_to_context_force(isec->sid, &context,
2943 &size);
2944 else
2945 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002946 if (error)
2947 return error;
2948 error = size;
2949 if (alloc) {
2950 *buffer = context;
2951 goto out_nofree;
2952 }
2953 kfree(context);
2954out_nofree:
2955 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956}
2957
2958static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002959 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960{
2961 struct inode_security_struct *isec = inode->i_security;
2962 u32 newsid;
2963 int rc;
2964
2965 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2966 return -EOPNOTSUPP;
2967
2968 if (!value || !size)
2969 return -EACCES;
2970
Eric Paris828dfe12008-04-17 13:17:49 -04002971 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 if (rc)
2973 return rc;
2974
2975 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04002976 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return 0;
2978}
2979
2980static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2981{
2982 const int len = sizeof(XATTR_NAME_SELINUX);
2983 if (buffer && len <= buffer_size)
2984 memcpy(buffer, XATTR_NAME_SELINUX, len);
2985 return len;
2986}
2987
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02002988static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2989{
2990 struct inode_security_struct *isec = inode->i_security;
2991 *secid = isec->sid;
2992}
2993
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994/* file security operations */
2995
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002996static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997{
David Howells88e67f32008-11-14 10:39:21 +11002998 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05002999 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3002 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3003 mask |= MAY_APPEND;
3004
Paul Moore389fb8002009-03-27 17:10:34 -04003005 return file_has_perm(cred, file,
3006 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007}
3008
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003009static int selinux_file_permission(struct file *file, int mask)
3010{
Al Viro496ad9a2013-01-23 17:07:38 -05003011 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003012 struct file_security_struct *fsec = file->f_security;
3013 struct inode_security_struct *isec = inode->i_security;
3014 u32 sid = current_sid();
3015
Paul Moore389fb8002009-03-27 17:10:34 -04003016 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003017 /* No permission to check. Existence test. */
3018 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003019
Stephen Smalley20dda182009-06-22 14:54:53 -04003020 if (sid == fsec->sid && fsec->isid == isec->sid &&
3021 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003022 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003023 return 0;
3024
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003025 return selinux_revalidate_file_permission(file, mask);
3026}
3027
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028static int selinux_file_alloc_security(struct file *file)
3029{
3030 return file_alloc_security(file);
3031}
3032
3033static void selinux_file_free_security(struct file *file)
3034{
3035 file_free_security(file);
3036}
3037
3038static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3039 unsigned long arg)
3040{
David Howells88e67f32008-11-14 10:39:21 +11003041 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003042 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043
Eric Paris0b24dcb2011-02-25 15:39:20 -05003044 switch (cmd) {
3045 case FIONREAD:
3046 /* fall through */
3047 case FIBMAP:
3048 /* fall through */
3049 case FIGETBSZ:
3050 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003051 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003052 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003053 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003054 error = file_has_perm(cred, file, FILE__GETATTR);
3055 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Al Viro2f99c362012-03-23 16:04:05 -04003057 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003058 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003059 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003060 error = file_has_perm(cred, file, FILE__SETATTR);
3061 break;
3062
3063 /* sys_ioctl() checks */
3064 case FIONBIO:
3065 /* fall through */
3066 case FIOASYNC:
3067 error = file_has_perm(cred, file, 0);
3068 break;
3069
3070 case KDSKBENT:
3071 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003072 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3073 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003074 break;
3075
3076 /* default case assumes that the command will go
3077 * to the file's ioctl() function.
3078 */
3079 default:
3080 error = file_has_perm(cred, file, FILE__IOCTL);
3081 }
3082 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083}
3084
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003085static int default_noexec;
3086
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3088{
David Howells88e67f32008-11-14 10:39:21 +11003089 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003090 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003091
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003092 if (default_noexec &&
3093 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 /*
3095 * We are making executable an anonymous mapping or a
3096 * private file mapping that will also be writable.
3097 * This has an additional check.
3098 */
David Howellsd84f4f92008-11-14 10:39:23 +11003099 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003101 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
3104 if (file) {
3105 /* read access is always possible with a mapping */
3106 u32 av = FILE__READ;
3107
3108 /* write access only matters if the mapping is shared */
3109 if (shared && (prot & PROT_WRITE))
3110 av |= FILE__WRITE;
3111
3112 if (prot & PROT_EXEC)
3113 av |= FILE__EXECUTE;
3114
David Howells88e67f32008-11-14 10:39:21 +11003115 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 }
David Howellsd84f4f92008-11-14 10:39:23 +11003117
3118error:
3119 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120}
3121
Al Viroe5467852012-05-30 13:30:51 -04003122static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123{
Eric Parised032182007-06-28 15:55:21 -04003124 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003125 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Eric Paris84336d1a2009-07-31 12:54:05 -04003127 /*
3128 * notice that we are intentionally putting the SELinux check before
3129 * the secondary cap_file_mmap check. This is such a likely attempt
3130 * at bad behaviour/exploit that we always want to get the AVC, even
3131 * if DAC would have also denied the operation.
3132 */
Eric Parisa2551df2009-07-31 12:54:11 -04003133 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003134 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3135 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003136 if (rc)
3137 return rc;
3138 }
3139
3140 /* do DAC check on address space usage */
Al Viroe5467852012-05-30 13:30:51 -04003141 return cap_mmap_addr(addr);
3142}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143
Al Viroe5467852012-05-30 13:30:51 -04003144static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3145 unsigned long prot, unsigned long flags)
3146{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 if (selinux_checkreqprot)
3148 prot = reqprot;
3149
3150 return file_map_prot_check(file, prot,
3151 (flags & MAP_TYPE) == MAP_SHARED);
3152}
3153
3154static int selinux_file_mprotect(struct vm_area_struct *vma,
3155 unsigned long reqprot,
3156 unsigned long prot)
3157{
David Howells88e67f32008-11-14 10:39:21 +11003158 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
3160 if (selinux_checkreqprot)
3161 prot = reqprot;
3162
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003163 if (default_noexec &&
3164 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003165 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003166 if (vma->vm_start >= vma->vm_mm->start_brk &&
3167 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003168 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003169 } else if (!vma->vm_file &&
3170 vma->vm_start <= vma->vm_mm->start_stack &&
3171 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003172 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003173 } else if (vma->vm_file && vma->anon_vma) {
3174 /*
3175 * We are making executable a file mapping that has
3176 * had some COW done. Since pages might have been
3177 * written, check ability to execute the possibly
3178 * modified content. This typically should only
3179 * occur for text relocations.
3180 */
David Howellsd84f4f92008-11-14 10:39:23 +11003181 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003182 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003183 if (rc)
3184 return rc;
3185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
3187 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3188}
3189
3190static int selinux_file_lock(struct file *file, unsigned int cmd)
3191{
David Howells88e67f32008-11-14 10:39:21 +11003192 const struct cred *cred = current_cred();
3193
3194 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196
3197static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3198 unsigned long arg)
3199{
David Howells88e67f32008-11-14 10:39:21 +11003200 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 int err = 0;
3202
3203 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003204 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003205 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003206 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003208 }
3209 /* fall through */
3210 case F_SETOWN:
3211 case F_SETSIG:
3212 case F_GETFL:
3213 case F_GETOWN:
3214 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003215 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003216 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003217 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003218 break;
3219 case F_GETLK:
3220 case F_SETLK:
3221 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003223 case F_GETLK64:
3224 case F_SETLK64:
3225 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226#endif
David Howells88e67f32008-11-14 10:39:21 +11003227 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003228 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 }
3230
3231 return err;
3232}
3233
3234static int selinux_file_set_fowner(struct file *file)
3235{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 struct file_security_struct *fsec;
3237
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003239 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240
3241 return 0;
3242}
3243
3244static int selinux_file_send_sigiotask(struct task_struct *tsk,
3245 struct fown_struct *fown, int signum)
3246{
Eric Paris828dfe12008-04-17 13:17:49 -04003247 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003248 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 struct file_security_struct *fsec;
3251
3252 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003253 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 fsec = file->f_security;
3256
3257 if (!signum)
3258 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3259 else
3260 perm = signal_to_av(signum);
3261
David Howells275bb412008-11-14 10:39:19 +11003262 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 SECCLASS_PROCESS, perm, NULL);
3264}
3265
3266static int selinux_file_receive(struct file *file)
3267{
David Howells88e67f32008-11-14 10:39:21 +11003268 const struct cred *cred = current_cred();
3269
3270 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271}
3272
Eric Paris83d49852012-04-04 13:45:40 -04003273static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003274{
3275 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003276 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003277
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003278 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003279 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003280 /*
3281 * Save inode label and policy sequence number
3282 * at open-time so that selinux_file_permission
3283 * can determine whether revalidation is necessary.
3284 * Task label is already saved in the file security
3285 * struct as its SID.
3286 */
3287 fsec->isid = isec->sid;
3288 fsec->pseqno = avc_policy_seqno();
3289 /*
3290 * Since the inode label or policy seqno may have changed
3291 * between the selinux_inode_permission check and the saving
3292 * of state above, recheck that access is still permitted.
3293 * Otherwise, access might never be revalidated against the
3294 * new inode label or new policy.
3295 * This check is not redundant - do not remove.
3296 */
Eric Paris602a8dd2012-04-04 15:01:42 -04003297 return path_has_perm(cred, &file->f_path, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003298}
3299
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300/* task security operations */
3301
3302static int selinux_task_create(unsigned long clone_flags)
3303{
David Howells3b11a1d2008-11-14 10:39:26 +11003304 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305}
3306
David Howellsf1752ee2008-11-14 10:39:17 +11003307/*
David Howellsee18d642009-09-02 09:14:21 +01003308 * allocate the SELinux part of blank credentials
3309 */
3310static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3311{
3312 struct task_security_struct *tsec;
3313
3314 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3315 if (!tsec)
3316 return -ENOMEM;
3317
3318 cred->security = tsec;
3319 return 0;
3320}
3321
3322/*
David Howellsf1752ee2008-11-14 10:39:17 +11003323 * detach and free the LSM part of a set of credentials
3324 */
3325static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326{
David Howellsf1752ee2008-11-14 10:39:17 +11003327 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003328
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003329 /*
3330 * cred->security == NULL if security_cred_alloc_blank() or
3331 * security_prepare_creds() returned an error.
3332 */
3333 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003334 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003335 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336}
3337
David Howellsd84f4f92008-11-14 10:39:23 +11003338/*
3339 * prepare a new set of credentials for modification
3340 */
3341static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3342 gfp_t gfp)
3343{
3344 const struct task_security_struct *old_tsec;
3345 struct task_security_struct *tsec;
3346
3347 old_tsec = old->security;
3348
3349 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3350 if (!tsec)
3351 return -ENOMEM;
3352
3353 new->security = tsec;
3354 return 0;
3355}
3356
3357/*
David Howellsee18d642009-09-02 09:14:21 +01003358 * transfer the SELinux data to a blank set of creds
3359 */
3360static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3361{
3362 const struct task_security_struct *old_tsec = old->security;
3363 struct task_security_struct *tsec = new->security;
3364
3365 *tsec = *old_tsec;
3366}
3367
3368/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003369 * set the security data for a kernel service
3370 * - all the creation contexts are set to unlabelled
3371 */
3372static int selinux_kernel_act_as(struct cred *new, u32 secid)
3373{
3374 struct task_security_struct *tsec = new->security;
3375 u32 sid = current_sid();
3376 int ret;
3377
3378 ret = avc_has_perm(sid, secid,
3379 SECCLASS_KERNEL_SERVICE,
3380 KERNEL_SERVICE__USE_AS_OVERRIDE,
3381 NULL);
3382 if (ret == 0) {
3383 tsec->sid = secid;
3384 tsec->create_sid = 0;
3385 tsec->keycreate_sid = 0;
3386 tsec->sockcreate_sid = 0;
3387 }
3388 return ret;
3389}
3390
3391/*
3392 * set the file creation context in a security record to the same as the
3393 * objective context of the specified inode
3394 */
3395static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3396{
3397 struct inode_security_struct *isec = inode->i_security;
3398 struct task_security_struct *tsec = new->security;
3399 u32 sid = current_sid();
3400 int ret;
3401
3402 ret = avc_has_perm(sid, isec->sid,
3403 SECCLASS_KERNEL_SERVICE,
3404 KERNEL_SERVICE__CREATE_FILES_AS,
3405 NULL);
3406
3407 if (ret == 0)
3408 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003409 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003410}
3411
Eric Parisdd8dbf22009-11-03 16:35:32 +11003412static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003413{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003414 u32 sid;
3415 struct common_audit_data ad;
3416
3417 sid = task_sid(current);
3418
Eric Paris50c205f2012-04-04 15:01:43 -04003419 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003420 ad.u.kmod_name = kmod_name;
3421
3422 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3423 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003424}
3425
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3427{
David Howells3b11a1d2008-11-14 10:39:26 +11003428 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429}
3430
3431static int selinux_task_getpgid(struct task_struct *p)
3432{
David Howells3b11a1d2008-11-14 10:39:26 +11003433 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434}
3435
3436static int selinux_task_getsid(struct task_struct *p)
3437{
David Howells3b11a1d2008-11-14 10:39:26 +11003438 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439}
3440
David Quigleyf9008e42006-06-30 01:55:46 -07003441static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3442{
David Howells275bb412008-11-14 10:39:19 +11003443 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003444}
3445
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446static int selinux_task_setnice(struct task_struct *p, int nice)
3447{
3448 int rc;
3449
Eric Paris200ac532009-02-12 15:01:04 -05003450 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 if (rc)
3452 return rc;
3453
David Howells3b11a1d2008-11-14 10:39:26 +11003454 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455}
3456
James Morris03e68062006-06-23 02:03:58 -07003457static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3458{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003459 int rc;
3460
Eric Paris200ac532009-02-12 15:01:04 -05003461 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003462 if (rc)
3463 return rc;
3464
David Howells3b11a1d2008-11-14 10:39:26 +11003465 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003466}
3467
David Quigleya1836a42006-06-30 01:55:49 -07003468static int selinux_task_getioprio(struct task_struct *p)
3469{
David Howells3b11a1d2008-11-14 10:39:26 +11003470 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003471}
3472
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003473static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3474 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003476 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477
3478 /* Control the ability to change the hard limit (whether
3479 lowering or raising it), so that the hard limit can
3480 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003481 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003483 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
3485 return 0;
3486}
3487
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003488static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003490 int rc;
3491
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003492 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003493 if (rc)
3494 return rc;
3495
David Howells3b11a1d2008-11-14 10:39:26 +11003496 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497}
3498
3499static int selinux_task_getscheduler(struct task_struct *p)
3500{
David Howells3b11a1d2008-11-14 10:39:26 +11003501 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502}
3503
David Quigley35601542006-06-23 02:04:01 -07003504static int selinux_task_movememory(struct task_struct *p)
3505{
David Howells3b11a1d2008-11-14 10:39:26 +11003506 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003507}
3508
David Quigleyf9008e42006-06-30 01:55:46 -07003509static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3510 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511{
3512 u32 perm;
3513 int rc;
3514
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 if (!sig)
3516 perm = PROCESS__SIGNULL; /* null signal; existence test */
3517 else
3518 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003519 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003520 rc = avc_has_perm(secid, task_sid(p),
3521 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003522 else
David Howells3b11a1d2008-11-14 10:39:26 +11003523 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003524 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525}
3526
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527static int selinux_task_wait(struct task_struct *p)
3528{
Eric Paris8a535142007-10-22 16:10:31 -04003529 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530}
3531
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532static void selinux_task_to_inode(struct task_struct *p,
3533 struct inode *inode)
3534{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003536 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
David Howells275bb412008-11-14 10:39:19 +11003538 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540}
3541
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003543static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003544 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545{
3546 int offset, ihlen, ret = -EINVAL;
3547 struct iphdr _iph, *ih;
3548
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003549 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3551 if (ih == NULL)
3552 goto out;
3553
3554 ihlen = ih->ihl * 4;
3555 if (ihlen < sizeof(_iph))
3556 goto out;
3557
Eric Paris48c62af2012-04-02 13:15:44 -04003558 ad->u.net->v4info.saddr = ih->saddr;
3559 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 ret = 0;
3561
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003562 if (proto)
3563 *proto = ih->protocol;
3564
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003566 case IPPROTO_TCP: {
3567 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568
Eric Paris828dfe12008-04-17 13:17:49 -04003569 if (ntohs(ih->frag_off) & IP_OFFSET)
3570 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571
3572 offset += ihlen;
3573 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3574 if (th == NULL)
3575 break;
3576
Eric Paris48c62af2012-04-02 13:15:44 -04003577 ad->u.net->sport = th->source;
3578 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581
Eric Paris828dfe12008-04-17 13:17:49 -04003582 case IPPROTO_UDP: {
3583 struct udphdr _udph, *uh;
3584
3585 if (ntohs(ih->frag_off) & IP_OFFSET)
3586 break;
3587
3588 offset += ihlen;
3589 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3590 if (uh == NULL)
3591 break;
3592
Eric Paris48c62af2012-04-02 13:15:44 -04003593 ad->u.net->sport = uh->source;
3594 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003595 break;
3596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597
James Morris2ee92d42006-11-13 16:09:01 -08003598 case IPPROTO_DCCP: {
3599 struct dccp_hdr _dccph, *dh;
3600
3601 if (ntohs(ih->frag_off) & IP_OFFSET)
3602 break;
3603
3604 offset += ihlen;
3605 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3606 if (dh == NULL)
3607 break;
3608
Eric Paris48c62af2012-04-02 13:15:44 -04003609 ad->u.net->sport = dh->dccph_sport;
3610 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003611 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003612 }
James Morris2ee92d42006-11-13 16:09:01 -08003613
Eric Paris828dfe12008-04-17 13:17:49 -04003614 default:
3615 break;
3616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617out:
3618 return ret;
3619}
3620
3621#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3622
3623/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003624static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003625 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626{
3627 u8 nexthdr;
3628 int ret = -EINVAL, offset;
3629 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003630 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003632 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3634 if (ip6 == NULL)
3635 goto out;
3636
Eric Paris48c62af2012-04-02 13:15:44 -04003637 ad->u.net->v6info.saddr = ip6->saddr;
3638 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 ret = 0;
3640
3641 nexthdr = ip6->nexthdr;
3642 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003643 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 if (offset < 0)
3645 goto out;
3646
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003647 if (proto)
3648 *proto = nexthdr;
3649
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 switch (nexthdr) {
3651 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003652 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
3654 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3655 if (th == NULL)
3656 break;
3657
Eric Paris48c62af2012-04-02 13:15:44 -04003658 ad->u.net->sport = th->source;
3659 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 break;
3661 }
3662
3663 case IPPROTO_UDP: {
3664 struct udphdr _udph, *uh;
3665
3666 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3667 if (uh == NULL)
3668 break;
3669
Eric Paris48c62af2012-04-02 13:15:44 -04003670 ad->u.net->sport = uh->source;
3671 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672 break;
3673 }
3674
James Morris2ee92d42006-11-13 16:09:01 -08003675 case IPPROTO_DCCP: {
3676 struct dccp_hdr _dccph, *dh;
3677
3678 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3679 if (dh == NULL)
3680 break;
3681
Eric Paris48c62af2012-04-02 13:15:44 -04003682 ad->u.net->sport = dh->dccph_sport;
3683 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003684 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003685 }
James Morris2ee92d42006-11-13 16:09:01 -08003686
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 /* includes fragments */
3688 default:
3689 break;
3690 }
3691out:
3692 return ret;
3693}
3694
3695#endif /* IPV6 */
3696
Thomas Liu2bf49692009-07-14 12:14:09 -04003697static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003698 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
David Howellscf9481e2008-07-27 21:31:07 +10003700 char *addrp;
3701 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
Eric Paris48c62af2012-04-02 13:15:44 -04003703 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003705 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003706 if (ret)
3707 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003708 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3709 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003710 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711
3712#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3713 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003714 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003715 if (ret)
3716 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003717 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3718 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003719 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720#endif /* IPV6 */
3721 default:
David Howellscf9481e2008-07-27 21:31:07 +10003722 addrp = NULL;
3723 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 }
3725
David Howellscf9481e2008-07-27 21:31:07 +10003726parse_error:
3727 printk(KERN_WARNING
3728 "SELinux: failure in selinux_parse_skb(),"
3729 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003731
3732okay:
3733 if (_addrp)
3734 *_addrp = addrp;
3735 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736}
3737
Paul Moore4f6a9932007-03-01 14:35:22 -05003738/**
Paul Moore220deb92008-01-29 08:38:23 -05003739 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003740 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003741 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003742 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003743 *
3744 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003745 * Check the various different forms of network peer labeling and determine
3746 * the peer label/SID for the packet; most of the magic actually occurs in
3747 * the security server function security_net_peersid_cmp(). The function
3748 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3749 * or -EACCES if @sid is invalid due to inconsistencies with the different
3750 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003751 *
3752 */
Paul Moore220deb92008-01-29 08:38:23 -05003753static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003754{
Paul Moore71f1cb02008-01-29 08:51:16 -05003755 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003756 u32 xfrm_sid;
3757 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003758 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003759
Paul Moore07035702013-12-10 14:57:54 -05003760 selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003761 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003762
Paul Moore71f1cb02008-01-29 08:51:16 -05003763 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3764 if (unlikely(err)) {
3765 printk(KERN_WARNING
3766 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3767 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003768 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003769 }
Paul Moore220deb92008-01-29 08:38:23 -05003770
3771 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003772}
3773
Paul Moore348d7862013-12-04 16:10:51 -05003774/**
3775 * selinux_conn_sid - Determine the child socket label for a connection
3776 * @sk_sid: the parent socket's SID
3777 * @skb_sid: the packet's SID
3778 * @conn_sid: the resulting connection SID
3779 *
3780 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3781 * combined with the MLS information from @skb_sid in order to create
3782 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3783 * of @sk_sid. Returns zero on success, negative values on failure.
3784 *
3785 */
3786static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3787{
3788 int err = 0;
3789
3790 if (skb_sid != SECSID_NULL)
3791 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3792 else
3793 *conn_sid = sk_sid;
3794
3795 return err;
3796}
3797
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003799
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003800static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3801 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003802{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003803 if (tsec->sockcreate_sid > SECSID_NULL) {
3804 *socksid = tsec->sockcreate_sid;
3805 return 0;
3806 }
3807
3808 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3809 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003810}
3811
Paul Moore253bfae2010-04-22 14:46:19 -04003812static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813{
Paul Moore253bfae2010-04-22 14:46:19 -04003814 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003815 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003816 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003817 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Paul Moore253bfae2010-04-22 14:46:19 -04003819 if (sksec->sid == SECINITSID_KERNEL)
3820 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Eric Paris50c205f2012-04-04 15:01:43 -04003822 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003823 ad.u.net = &net;
3824 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825
Paul Moore253bfae2010-04-22 14:46:19 -04003826 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827}
3828
3829static int selinux_socket_create(int family, int type,
3830 int protocol, int kern)
3831{
Paul Moore5fb49872010-04-22 14:46:19 -04003832 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003833 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003834 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003835 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836
3837 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003838 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
David Howells275bb412008-11-14 10:39:19 +11003840 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003841 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3842 if (rc)
3843 return rc;
3844
Paul Moored4f2d972010-04-22 14:46:18 -04003845 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846}
3847
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003848static int selinux_socket_post_create(struct socket *sock, int family,
3849 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850{
Paul Moore5fb49872010-04-22 14:46:19 -04003851 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003852 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003853 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003854 int err = 0;
3855
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003856 isec->sclass = socket_type_to_security_class(family, type, protocol);
3857
David Howells275bb412008-11-14 10:39:19 +11003858 if (kern)
3859 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003860 else {
3861 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3862 if (err)
3863 return err;
3864 }
David Howells275bb412008-11-14 10:39:19 +11003865
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 isec->initialized = 1;
3867
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003868 if (sock->sk) {
3869 sksec = sock->sk->sk_security;
3870 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003871 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04003872 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003873 }
3874
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003875 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876}
3877
3878/* Range of port numbers used to automatically bind.
3879 Need to determine whether we should perform a name_bind
3880 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
3882static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3883{
Paul Moore253bfae2010-04-22 14:46:19 -04003884 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 u16 family;
3886 int err;
3887
Paul Moore253bfae2010-04-22 14:46:19 -04003888 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 if (err)
3890 goto out;
3891
3892 /*
3893 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003894 * Multiple address binding for SCTP is not supported yet: we just
3895 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 */
Paul Moore253bfae2010-04-22 14:46:19 -04003897 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 if (family == PF_INET || family == PF_INET6) {
3899 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04003900 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003901 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003902 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 struct sockaddr_in *addr4 = NULL;
3904 struct sockaddr_in6 *addr6 = NULL;
3905 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10003906 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 if (family == PF_INET) {
3909 addr4 = (struct sockaddr_in *)address;
3910 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 addrp = (char *)&addr4->sin_addr.s_addr;
3912 } else {
3913 addr6 = (struct sockaddr_in6 *)address;
3914 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 addrp = (char *)&addr6->sin6_addr.s6_addr;
3916 }
3917
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003918 if (snum) {
3919 int low, high;
3920
3921 inet_get_local_port_range(&low, &high);
3922
3923 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003924 err = sel_netport_sid(sk->sk_protocol,
3925 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003926 if (err)
3927 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04003928 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003929 ad.u.net = &net;
3930 ad.u.net->sport = htons(snum);
3931 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04003932 err = avc_has_perm(sksec->sid, sid,
3933 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003934 SOCKET__NAME_BIND, &ad);
3935 if (err)
3936 goto out;
3937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 }
Eric Paris828dfe12008-04-17 13:17:49 -04003939
Paul Moore253bfae2010-04-22 14:46:19 -04003940 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003941 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 node_perm = TCP_SOCKET__NODE_BIND;
3943 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003944
James Morris13402582005-09-30 14:24:34 -04003945 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 node_perm = UDP_SOCKET__NODE_BIND;
3947 break;
James Morris2ee92d42006-11-13 16:09:01 -08003948
3949 case SECCLASS_DCCP_SOCKET:
3950 node_perm = DCCP_SOCKET__NODE_BIND;
3951 break;
3952
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 default:
3954 node_perm = RAWIP_SOCKET__NODE_BIND;
3955 break;
3956 }
Eric Paris828dfe12008-04-17 13:17:49 -04003957
Paul Moore224dfbd2008-01-29 08:38:13 -05003958 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 if (err)
3960 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003961
Eric Paris50c205f2012-04-04 15:01:43 -04003962 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003963 ad.u.net = &net;
3964 ad.u.net->sport = htons(snum);
3965 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
3967 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04003968 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 else
Eric Paris48c62af2012-04-02 13:15:44 -04003970 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Paul Moore253bfae2010-04-22 14:46:19 -04003972 err = avc_has_perm(sksec->sid, sid,
3973 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 if (err)
3975 goto out;
3976 }
3977out:
3978 return err;
3979}
3980
3981static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3982{
Paul Moore014ab192008-10-10 10:16:33 -04003983 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04003984 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 int err;
3986
Paul Moore253bfae2010-04-22 14:46:19 -04003987 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 if (err)
3989 return err;
3990
3991 /*
James Morris2ee92d42006-11-13 16:09:01 -08003992 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 */
Paul Moore253bfae2010-04-22 14:46:19 -04003994 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3995 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04003996 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003997 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 struct sockaddr_in *addr4 = NULL;
3999 struct sockaddr_in6 *addr6 = NULL;
4000 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004001 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
4003 if (sk->sk_family == PF_INET) {
4004 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004005 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 return -EINVAL;
4007 snum = ntohs(addr4->sin_port);
4008 } else {
4009 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004010 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 return -EINVAL;
4012 snum = ntohs(addr6->sin6_port);
4013 }
4014
Paul Moore3e112172008-04-10 10:48:14 -04004015 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 if (err)
4017 goto out;
4018
Paul Moore253bfae2010-04-22 14:46:19 -04004019 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004020 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4021
Eric Paris50c205f2012-04-04 15:01:43 -04004022 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004023 ad.u.net = &net;
4024 ad.u.net->dport = htons(snum);
4025 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004026 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 if (err)
4028 goto out;
4029 }
4030
Paul Moore014ab192008-10-10 10:16:33 -04004031 err = selinux_netlbl_socket_connect(sk, address);
4032
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033out:
4034 return err;
4035}
4036
4037static int selinux_socket_listen(struct socket *sock, int backlog)
4038{
Paul Moore253bfae2010-04-22 14:46:19 -04004039 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040}
4041
4042static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4043{
4044 int err;
4045 struct inode_security_struct *isec;
4046 struct inode_security_struct *newisec;
4047
Paul Moore253bfae2010-04-22 14:46:19 -04004048 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 if (err)
4050 return err;
4051
4052 newisec = SOCK_INODE(newsock)->i_security;
4053
4054 isec = SOCK_INODE(sock)->i_security;
4055 newisec->sclass = isec->sclass;
4056 newisec->sid = isec->sid;
4057 newisec->initialized = 1;
4058
4059 return 0;
4060}
4061
4062static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004063 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
Paul Moore253bfae2010-04-22 14:46:19 -04004065 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066}
4067
4068static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4069 int size, int flags)
4070{
Paul Moore253bfae2010-04-22 14:46:19 -04004071 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072}
4073
4074static int selinux_socket_getsockname(struct socket *sock)
4075{
Paul Moore253bfae2010-04-22 14:46:19 -04004076 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077}
4078
4079static int selinux_socket_getpeername(struct socket *sock)
4080{
Paul Moore253bfae2010-04-22 14:46:19 -04004081 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082}
4083
Eric Paris828dfe12008-04-17 13:17:49 -04004084static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085{
Paul Mooref8687af2006-10-30 15:22:15 -08004086 int err;
4087
Paul Moore253bfae2010-04-22 14:46:19 -04004088 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004089 if (err)
4090 return err;
4091
4092 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093}
4094
4095static int selinux_socket_getsockopt(struct socket *sock, int level,
4096 int optname)
4097{
Paul Moore253bfae2010-04-22 14:46:19 -04004098 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099}
4100
4101static int selinux_socket_shutdown(struct socket *sock, int how)
4102{
Paul Moore253bfae2010-04-22 14:46:19 -04004103 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104}
4105
David S. Miller3610cda2011-01-05 15:38:53 -08004106static int selinux_socket_unix_stream_connect(struct sock *sock,
4107 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 struct sock *newsk)
4109{
David S. Miller3610cda2011-01-05 15:38:53 -08004110 struct sk_security_struct *sksec_sock = sock->sk_security;
4111 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004112 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004113 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004114 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 int err;
4116
Eric Paris50c205f2012-04-04 15:01:43 -04004117 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004118 ad.u.net = &net;
4119 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
Paul Moore4d1e2452010-04-22 14:46:18 -04004121 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4122 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4124 if (err)
4125 return err;
4126
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004128 sksec_new->peer_sid = sksec_sock->sid;
4129 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4130 &sksec_new->sid);
4131 if (err)
4132 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004133
Paul Moore4d1e2452010-04-22 14:46:18 -04004134 /* connecting socket */
4135 sksec_sock->peer_sid = sksec_new->sid;
4136
4137 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138}
4139
4140static int selinux_socket_unix_may_send(struct socket *sock,
4141 struct socket *other)
4142{
Paul Moore253bfae2010-04-22 14:46:19 -04004143 struct sk_security_struct *ssec = sock->sk->sk_security;
4144 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004145 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004146 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Eric Paris50c205f2012-04-04 15:01:43 -04004148 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004149 ad.u.net = &net;
4150 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Paul Moore253bfae2010-04-22 14:46:19 -04004152 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4153 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154}
4155
Paul Mooreeffad8d2008-01-29 08:49:27 -05004156static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4157 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004158 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004159{
4160 int err;
4161 u32 if_sid;
4162 u32 node_sid;
4163
4164 err = sel_netif_sid(ifindex, &if_sid);
4165 if (err)
4166 return err;
4167 err = avc_has_perm(peer_sid, if_sid,
4168 SECCLASS_NETIF, NETIF__INGRESS, ad);
4169 if (err)
4170 return err;
4171
4172 err = sel_netnode_sid(addrp, family, &node_sid);
4173 if (err)
4174 return err;
4175 return avc_has_perm(peer_sid, node_sid,
4176 SECCLASS_NODE, NODE__RECVFROM, ad);
4177}
4178
Paul Moore220deb92008-01-29 08:38:23 -05004179static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004180 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004181{
Paul Moore277d3422008-12-31 12:54:11 -05004182 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004183 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004184 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004185 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004186 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004187 char *addrp;
4188
Eric Paris50c205f2012-04-04 15:01:43 -04004189 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004190 ad.u.net = &net;
4191 ad.u.net->netif = skb->skb_iif;
4192 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004193 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4194 if (err)
4195 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004196
Paul Moore58bfbb52009-03-27 17:10:41 -04004197 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004198 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004199 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004200 if (err)
4201 return err;
4202 }
Paul Moore220deb92008-01-29 08:38:23 -05004203
Steffen Klassertb9679a72011-02-23 12:55:21 +01004204 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4205 if (err)
4206 return err;
4207 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004208
James Morris4e5ab4c2006-06-09 00:33:33 -07004209 return err;
4210}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004211
James Morris4e5ab4c2006-06-09 00:33:33 -07004212static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4213{
Paul Moore220deb92008-01-29 08:38:23 -05004214 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004215 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004216 u16 family = sk->sk_family;
4217 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004218 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004219 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004220 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004221 u8 secmark_active;
4222 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004223
James Morris4e5ab4c2006-06-09 00:33:33 -07004224 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004225 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004226
4227 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004228 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004229 family = PF_INET;
4230
Paul Moored8395c82008-10-10 10:16:30 -04004231 /* If any sort of compatibility mode is enabled then handoff processing
4232 * to the selinux_sock_rcv_skb_compat() function to deal with the
4233 * special handling. We do this in an attempt to keep this function
4234 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004235 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004236 return selinux_sock_rcv_skb_compat(sk, skb, family);
4237
4238 secmark_active = selinux_secmark_enabled();
4239 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4240 if (!secmark_active && !peerlbl_active)
4241 return 0;
4242
Eric Paris50c205f2012-04-04 15:01:43 -04004243 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004244 ad.u.net = &net;
4245 ad.u.net->netif = skb->skb_iif;
4246 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004247 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004248 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004249 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004250
Paul Moored8395c82008-10-10 10:16:30 -04004251 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004252 u32 peer_sid;
4253
4254 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4255 if (err)
4256 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004257 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004258 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004259 if (err) {
4260 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004261 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004262 }
Paul Moored621d352008-01-29 08:43:36 -05004263 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4264 PEER__RECV, &ad);
Chad Hansonfaecbbe2013-12-23 17:45:01 -05004265 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004266 selinux_netlbl_err(skb, err, 0);
Chad Hansonfaecbbe2013-12-23 17:45:01 -05004267 return err;
4268 }
Paul Moored621d352008-01-29 08:43:36 -05004269 }
4270
Paul Moored8395c82008-10-10 10:16:30 -04004271 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004272 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4273 PACKET__RECV, &ad);
4274 if (err)
4275 return err;
4276 }
4277
Paul Moored621d352008-01-29 08:43:36 -05004278 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279}
4280
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004281static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4282 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283{
4284 int err = 0;
4285 char *scontext;
4286 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004287 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004288 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289
Paul Moore253bfae2010-04-22 14:46:19 -04004290 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4291 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004292 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004293 if (peer_sid == SECSID_NULL)
4294 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004296 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004298 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
4300 if (scontext_len > len) {
4301 err = -ERANGE;
4302 goto out_len;
4303 }
4304
4305 if (copy_to_user(optval, scontext, scontext_len))
4306 err = -EFAULT;
4307
4308out_len:
4309 if (put_user(scontext_len, optlen))
4310 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 return err;
4313}
4314
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004315static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004316{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004317 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004318 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004319
Paul Mooreaa862902008-10-10 10:16:29 -04004320 if (skb && skb->protocol == htons(ETH_P_IP))
4321 family = PF_INET;
4322 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4323 family = PF_INET6;
4324 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004325 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004326 else
4327 goto out;
4328
4329 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004330 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004331 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004332 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004333
Paul Moore75e22912008-01-29 08:38:04 -05004334out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004335 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004336 if (peer_secid == SECSID_NULL)
4337 return -EINVAL;
4338 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004339}
4340
Al Viro7d877f32005-10-21 03:20:43 -04004341static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342{
Paul Moore84914b72010-04-22 14:46:18 -04004343 struct sk_security_struct *sksec;
4344
4345 sksec = kzalloc(sizeof(*sksec), priority);
4346 if (!sksec)
4347 return -ENOMEM;
4348
4349 sksec->peer_sid = SECINITSID_UNLABELED;
4350 sksec->sid = SECINITSID_UNLABELED;
4351 selinux_netlbl_sk_security_reset(sksec);
4352 sk->sk_security = sksec;
4353
4354 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355}
4356
4357static void selinux_sk_free_security(struct sock *sk)
4358{
Paul Moore84914b72010-04-22 14:46:18 -04004359 struct sk_security_struct *sksec = sk->sk_security;
4360
4361 sk->sk_security = NULL;
4362 selinux_netlbl_sk_security_free(sksec);
4363 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364}
4365
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004366static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4367{
Eric Parisdd3e7832010-04-07 15:08:46 -04004368 struct sk_security_struct *sksec = sk->sk_security;
4369 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004370
Eric Parisdd3e7832010-04-07 15:08:46 -04004371 newsksec->sid = sksec->sid;
4372 newsksec->peer_sid = sksec->peer_sid;
4373 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004374
Eric Parisdd3e7832010-04-07 15:08:46 -04004375 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004376}
4377
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004378static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004379{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004380 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004381 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004382 else {
4383 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004384
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004385 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004386 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004387}
4388
Eric Paris828dfe12008-04-17 13:17:49 -04004389static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004390{
4391 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4392 struct sk_security_struct *sksec = sk->sk_security;
4393
David Woodhouse2148ccc2006-09-29 15:50:25 -07004394 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4395 sk->sk_family == PF_UNIX)
4396 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004397 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004398}
4399
Adrian Bunk9a673e52006-08-15 00:03:53 -07004400static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4401 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004402{
4403 struct sk_security_struct *sksec = sk->sk_security;
4404 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004405 u16 family = sk->sk_family;
Paul Moore348d7862013-12-04 16:10:51 -05004406 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004407 u32 peersid;
4408
Paul Mooreaa862902008-10-10 10:16:29 -04004409 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4410 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4411 family = PF_INET;
4412
4413 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004414 if (err)
4415 return err;
Paul Moore348d7862013-12-04 16:10:51 -05004416 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4417 if (err)
4418 return err;
4419 req->secid = connsid;
4420 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004421
Paul Moore389fb8002009-03-27 17:10:34 -04004422 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004423}
4424
Adrian Bunk9a673e52006-08-15 00:03:53 -07004425static void selinux_inet_csk_clone(struct sock *newsk,
4426 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004427{
4428 struct sk_security_struct *newsksec = newsk->sk_security;
4429
4430 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004431 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004432 /* NOTE: Ideally, we should also get the isec->sid for the
4433 new socket in sync, but we don't have the isec available yet.
4434 So we will wait until sock_graft to do it, by which
4435 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004436
Paul Moore9f2ad662006-11-17 17:38:53 -05004437 /* We don't need to take any sort of lock here as we are the only
4438 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004439 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004440}
4441
Paul Moore014ab192008-10-10 10:16:33 -04004442static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004443{
Paul Mooreaa862902008-10-10 10:16:29 -04004444 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004445 struct sk_security_struct *sksec = sk->sk_security;
4446
Paul Mooreaa862902008-10-10 10:16:29 -04004447 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4448 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4449 family = PF_INET;
4450
4451 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004452}
4453
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004454static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4455{
4456 skb_set_owner_w(skb, sk);
4457}
4458
Eric Paris2606fd12010-10-13 16:24:41 -04004459static int selinux_secmark_relabel_packet(u32 sid)
4460{
4461 const struct task_security_struct *__tsec;
4462 u32 tsid;
4463
4464 __tsec = current_security();
4465 tsid = __tsec->sid;
4466
4467 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4468}
4469
4470static void selinux_secmark_refcount_inc(void)
4471{
4472 atomic_inc(&selinux_secmark_refcount);
4473}
4474
4475static void selinux_secmark_refcount_dec(void)
4476{
4477 atomic_dec(&selinux_secmark_refcount);
4478}
4479
Adrian Bunk9a673e52006-08-15 00:03:53 -07004480static void selinux_req_classify_flow(const struct request_sock *req,
4481 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004482{
David S. Miller1d28f422011-03-12 00:29:39 -05004483 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004484}
4485
Paul Moore5dbbaf22013-01-14 07:12:19 +00004486static int selinux_tun_dev_alloc_security(void **security)
4487{
4488 struct tun_security_struct *tunsec;
4489
4490 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4491 if (!tunsec)
4492 return -ENOMEM;
4493 tunsec->sid = current_sid();
4494
4495 *security = tunsec;
4496 return 0;
4497}
4498
4499static void selinux_tun_dev_free_security(void *security)
4500{
4501 kfree(security);
4502}
4503
Paul Mooreed6d76e2009-08-28 18:12:49 -04004504static int selinux_tun_dev_create(void)
4505{
4506 u32 sid = current_sid();
4507
4508 /* we aren't taking into account the "sockcreate" SID since the socket
4509 * that is being created here is not a socket in the traditional sense,
4510 * instead it is a private sock, accessible only to the kernel, and
4511 * representing a wide range of network traffic spanning multiple
4512 * connections unlike traditional sockets - check the TUN driver to
4513 * get a better understanding of why this socket is special */
4514
4515 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4516 NULL);
4517}
4518
Paul Moore5dbbaf22013-01-14 07:12:19 +00004519static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004520{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004521 struct tun_security_struct *tunsec = security;
4522
4523 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4524 TUN_SOCKET__ATTACH_QUEUE, NULL);
4525}
4526
4527static int selinux_tun_dev_attach(struct sock *sk, void *security)
4528{
4529 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004530 struct sk_security_struct *sksec = sk->sk_security;
4531
4532 /* we don't currently perform any NetLabel based labeling here and it
4533 * isn't clear that we would want to do so anyway; while we could apply
4534 * labeling without the support of the TUN user the resulting labeled
4535 * traffic from the other end of the connection would almost certainly
4536 * cause confusion to the TUN user that had no idea network labeling
4537 * protocols were being used */
4538
Paul Moore5dbbaf22013-01-14 07:12:19 +00004539 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004540 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004541
4542 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004543}
4544
Paul Moore5dbbaf22013-01-14 07:12:19 +00004545static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004546{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004547 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004548 u32 sid = current_sid();
4549 int err;
4550
Paul Moore5dbbaf22013-01-14 07:12:19 +00004551 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004552 TUN_SOCKET__RELABELFROM, NULL);
4553 if (err)
4554 return err;
4555 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4556 TUN_SOCKET__RELABELTO, NULL);
4557 if (err)
4558 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004559 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004560
4561 return 0;
4562}
4563
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4565{
4566 int err = 0;
4567 u32 perm;
4568 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004569 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004570
Hong zhi guo77954982013-03-27 06:49:35 +00004571 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 err = -EINVAL;
4573 goto out;
4574 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004575 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004576
Paul Moore253bfae2010-04-22 14:46:19 -04004577 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 if (err) {
4579 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004580 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 "SELinux: unrecognized netlink message"
4582 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004583 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004584 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 err = 0;
4586 }
4587
4588 /* Ignore */
4589 if (err == -ENOENT)
4590 err = 0;
4591 goto out;
4592 }
4593
Paul Moore253bfae2010-04-22 14:46:19 -04004594 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595out:
4596 return err;
4597}
4598
4599#ifdef CONFIG_NETFILTER
4600
Paul Mooreeffad8d2008-01-29 08:49:27 -05004601static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4602 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
Paul Mooredfaebe92008-10-10 10:16:31 -04004604 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004605 char *addrp;
4606 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004607 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004608 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004609 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004610 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004611 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004612
Paul Mooreeffad8d2008-01-29 08:49:27 -05004613 if (!selinux_policycap_netpeer)
4614 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004615
Paul Mooreeffad8d2008-01-29 08:49:27 -05004616 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004617 netlbl_active = netlbl_enabled();
4618 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004619 if (!secmark_active && !peerlbl_active)
4620 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004621
Paul Moored8395c82008-10-10 10:16:30 -04004622 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4623 return NF_DROP;
4624
Eric Paris50c205f2012-04-04 15:01:43 -04004625 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004626 ad.u.net = &net;
4627 ad.u.net->netif = ifindex;
4628 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004629 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4630 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631
Paul Mooredfaebe92008-10-10 10:16:31 -04004632 if (peerlbl_active) {
4633 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4634 peer_sid, &ad);
4635 if (err) {
4636 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004637 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004638 }
4639 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004640
4641 if (secmark_active)
4642 if (avc_has_perm(peer_sid, skb->secmark,
4643 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4644 return NF_DROP;
4645
Paul Moore948bf852008-10-10 10:16:32 -04004646 if (netlbl_active)
4647 /* we do this in the FORWARD path and not the POST_ROUTING
4648 * path because we want to make sure we apply the necessary
4649 * labeling before IPsec is applied so we can leverage AH
4650 * protection */
4651 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4652 return NF_DROP;
4653
Paul Mooreeffad8d2008-01-29 08:49:27 -05004654 return NF_ACCEPT;
4655}
4656
4657static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4658 struct sk_buff *skb,
4659 const struct net_device *in,
4660 const struct net_device *out,
4661 int (*okfn)(struct sk_buff *))
4662{
4663 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4664}
4665
4666#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4667static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4668 struct sk_buff *skb,
4669 const struct net_device *in,
4670 const struct net_device *out,
4671 int (*okfn)(struct sk_buff *))
4672{
4673 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4674}
4675#endif /* IPV6 */
4676
Paul Moore948bf852008-10-10 10:16:32 -04004677static unsigned int selinux_ip_output(struct sk_buff *skb,
4678 u16 family)
4679{
Paul Moore216c4a72013-12-04 16:10:45 -05004680 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004681 u32 sid;
4682
4683 if (!netlbl_enabled())
4684 return NF_ACCEPT;
4685
4686 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4687 * because we want to make sure we apply the necessary labeling
4688 * before IPsec is applied so we can leverage AH protection */
Paul Moore216c4a72013-12-04 16:10:45 -05004689 sk = skb->sk;
4690 if (sk) {
4691 struct sk_security_struct *sksec;
4692
4693 if (sk->sk_state == TCP_LISTEN)
4694 /* if the socket is the listening state then this
4695 * packet is a SYN-ACK packet which means it needs to
4696 * be labeled based on the connection/request_sock and
4697 * not the parent socket. unfortunately, we can't
4698 * lookup the request_sock yet as it isn't queued on
4699 * the parent socket until after the SYN-ACK is sent.
4700 * the "solution" is to simply pass the packet as-is
4701 * as any IP option based labeling should be copied
4702 * from the initial connection request (in the IP
4703 * layer). it is far from ideal, but until we get a
4704 * security label in the packet itself this is the
4705 * best we can do. */
4706 return NF_ACCEPT;
4707
4708 /* standard practice, label using the parent socket */
4709 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004710 sid = sksec->sid;
4711 } else
4712 sid = SECINITSID_KERNEL;
4713 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4714 return NF_DROP;
4715
4716 return NF_ACCEPT;
4717}
4718
4719static unsigned int selinux_ipv4_output(unsigned int hooknum,
4720 struct sk_buff *skb,
4721 const struct net_device *in,
4722 const struct net_device *out,
4723 int (*okfn)(struct sk_buff *))
4724{
4725 return selinux_ip_output(skb, PF_INET);
4726}
4727
Paul Mooreeffad8d2008-01-29 08:49:27 -05004728static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4729 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004730 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004731{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004732 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004733 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004734 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004735 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004736 char *addrp;
4737 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004738
Paul Mooreeffad8d2008-01-29 08:49:27 -05004739 if (sk == NULL)
4740 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004741 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004742
Eric Paris50c205f2012-04-04 15:01:43 -04004743 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004744 ad.u.net = &net;
4745 ad.u.net->netif = ifindex;
4746 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004747 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4748 return NF_DROP;
4749
Paul Moore58bfbb52009-03-27 17:10:41 -04004750 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004751 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004752 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004753 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004754
Steffen Klassertb9679a72011-02-23 12:55:21 +01004755 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4756 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004757
Paul Mooreeffad8d2008-01-29 08:49:27 -05004758 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759}
4760
Paul Mooreeffad8d2008-01-29 08:49:27 -05004761static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4762 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004764 u32 secmark_perm;
4765 u32 peer_sid;
4766 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004767 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004768 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004769 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004770 u8 secmark_active;
4771 u8 peerlbl_active;
4772
Paul Mooreeffad8d2008-01-29 08:49:27 -05004773 /* If any sort of compatibility mode is enabled then handoff processing
4774 * to the selinux_ip_postroute_compat() function to deal with the
4775 * special handling. We do this in an attempt to keep this function
4776 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004777 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004778 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moore0fdb9382013-12-10 14:58:01 -05004779
Paul Mooreeffad8d2008-01-29 08:49:27 -05004780 secmark_active = selinux_secmark_enabled();
4781 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4782 if (!secmark_active && !peerlbl_active)
4783 return NF_ACCEPT;
4784
Paul Mooreeffad8d2008-01-29 08:49:27 -05004785 sk = skb->sk;
Paul Moore0fdb9382013-12-10 14:58:01 -05004786
4787#ifdef CONFIG_XFRM
4788 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4789 * packet transformation so allow the packet to pass without any checks
4790 * since we'll have another chance to perform access control checks
4791 * when the packet is on it's final way out.
4792 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4793 * is NULL, in this case go ahead and apply access control.
4794 * is NULL, in this case go ahead and apply access control.
4795 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4796 * TCP listening state we cannot wait until the XFRM processing
4797 * is done as we will miss out on the SA label if we do;
4798 * unfortunately, this means more work, but it is only once per
4799 * connection. */
4800 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4801 !(sk != NULL && sk->sk_state == TCP_LISTEN))
4802 return NF_ACCEPT;
4803#endif
4804
Paul Moored8395c82008-10-10 10:16:30 -04004805 if (sk == NULL) {
Paul Moore348d7862013-12-04 16:10:51 -05004806 /* Without an associated socket the packet is either coming
4807 * from the kernel or it is being forwarded; check the packet
4808 * to determine which and if the packet is being forwarded
4809 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004810 if (skb->skb_iif) {
4811 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004812 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004813 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004814 } else {
4815 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004816 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004817 }
Paul Moore348d7862013-12-04 16:10:51 -05004818 } else if (sk->sk_state == TCP_LISTEN) {
4819 /* Locally generated packet but the associated socket is in the
4820 * listening state which means this is a SYN-ACK packet. In
4821 * this particular case the correct security label is assigned
4822 * to the connection/request_sock but unfortunately we can't
4823 * query the request_sock as it isn't queued on the parent
4824 * socket until after the SYN-ACK packet is sent; the only
4825 * viable choice is to regenerate the label like we do in
4826 * selinux_inet_conn_request(). See also selinux_ip_output()
4827 * for similar problems. */
4828 u32 skb_sid;
4829 struct sk_security_struct *sksec = sk->sk_security;
4830 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4831 return NF_DROP;
Paul Moore0fdb9382013-12-10 14:58:01 -05004832 /* At this point, if the returned skb peerlbl is SECSID_NULL
4833 * and the packet has been through at least one XFRM
4834 * transformation then we must be dealing with the "final"
4835 * form of labeled IPsec packet; since we've already applied
4836 * all of our access controls on this packet we can safely
4837 * pass the packet. */
4838 if (skb_sid == SECSID_NULL) {
4839 switch (family) {
4840 case PF_INET:
4841 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4842 return NF_ACCEPT;
4843 break;
4844 case PF_INET6:
4845 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4846 return NF_ACCEPT;
4847 default:
4848 return NF_DROP_ERR(-ECONNREFUSED);
4849 }
4850 }
Paul Moore348d7862013-12-04 16:10:51 -05004851 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4852 return NF_DROP;
4853 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004854 } else {
Paul Moore348d7862013-12-04 16:10:51 -05004855 /* Locally generated packet, fetch the security label from the
4856 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004857 struct sk_security_struct *sksec = sk->sk_security;
4858 peer_sid = sksec->sid;
4859 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004860 }
4861
Eric Paris50c205f2012-04-04 15:01:43 -04004862 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004863 ad.u.net = &net;
4864 ad.u.net->netif = ifindex;
4865 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004866 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004867 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004868
Paul Mooreeffad8d2008-01-29 08:49:27 -05004869 if (secmark_active)
4870 if (avc_has_perm(peer_sid, skb->secmark,
4871 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004872 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004873
4874 if (peerlbl_active) {
4875 u32 if_sid;
4876 u32 node_sid;
4877
4878 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004879 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004880 if (avc_has_perm(peer_sid, if_sid,
4881 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004882 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004883
4884 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004885 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004886 if (avc_has_perm(peer_sid, node_sid,
4887 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004888 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004889 }
4890
4891 return NF_ACCEPT;
4892}
4893
4894static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4895 struct sk_buff *skb,
4896 const struct net_device *in,
4897 const struct net_device *out,
4898 int (*okfn)(struct sk_buff *))
4899{
4900 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901}
4902
4903#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004904static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4905 struct sk_buff *skb,
4906 const struct net_device *in,
4907 const struct net_device *out,
4908 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004910 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004911}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912#endif /* IPV6 */
4913
4914#endif /* CONFIG_NETFILTER */
4915
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4917{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918 int err;
4919
Eric Paris200ac532009-02-12 15:01:04 -05004920 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921 if (err)
4922 return err;
4923
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004924 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925}
4926
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927static int ipc_alloc_security(struct task_struct *task,
4928 struct kern_ipc_perm *perm,
4929 u16 sclass)
4930{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004932 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933
James Morris89d155e2005-10-30 14:59:21 -08004934 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004935 if (!isec)
4936 return -ENOMEM;
4937
David Howells275bb412008-11-14 10:39:19 +11004938 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11004940 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 perm->security = isec;
4942
4943 return 0;
4944}
4945
4946static void ipc_free_security(struct kern_ipc_perm *perm)
4947{
4948 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004949 perm->security = NULL;
4950 kfree(isec);
4951}
4952
4953static int msg_msg_alloc_security(struct msg_msg *msg)
4954{
4955 struct msg_security_struct *msec;
4956
James Morris89d155e2005-10-30 14:59:21 -08004957 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958 if (!msec)
4959 return -ENOMEM;
4960
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961 msec->sid = SECINITSID_UNLABELED;
4962 msg->security = msec;
4963
4964 return 0;
4965}
4966
4967static void msg_msg_free_security(struct msg_msg *msg)
4968{
4969 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970
4971 msg->security = NULL;
4972 kfree(msec);
4973}
4974
4975static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004976 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004979 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004980 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982 isec = ipc_perms->security;
4983
Eric Paris50c205f2012-04-04 15:01:43 -04004984 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985 ad.u.ipc_id = ipc_perms->key;
4986
David Howells275bb412008-11-14 10:39:19 +11004987 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988}
4989
4990static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4991{
4992 return msg_msg_alloc_security(msg);
4993}
4994
4995static void selinux_msg_msg_free_security(struct msg_msg *msg)
4996{
4997 msg_msg_free_security(msg);
4998}
4999
5000/* message queue security operations */
5001static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5002{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005004 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005005 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006 int rc;
5007
5008 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5009 if (rc)
5010 return rc;
5011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 isec = msq->q_perm.security;
5013
Eric Paris50c205f2012-04-04 15:01:43 -04005014 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005015 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016
David Howells275bb412008-11-14 10:39:19 +11005017 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 MSGQ__CREATE, &ad);
5019 if (rc) {
5020 ipc_free_security(&msq->q_perm);
5021 return rc;
5022 }
5023 return 0;
5024}
5025
5026static void selinux_msg_queue_free_security(struct msg_queue *msq)
5027{
5028 ipc_free_security(&msq->q_perm);
5029}
5030
5031static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5032{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005034 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005035 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037 isec = msq->q_perm.security;
5038
Eric Paris50c205f2012-04-04 15:01:43 -04005039 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 ad.u.ipc_id = msq->q_perm.key;
5041
David Howells275bb412008-11-14 10:39:19 +11005042 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 MSGQ__ASSOCIATE, &ad);
5044}
5045
5046static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5047{
5048 int err;
5049 int perms;
5050
Eric Paris828dfe12008-04-17 13:17:49 -04005051 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 case IPC_INFO:
5053 case MSG_INFO:
5054 /* No specific object, just general system-wide information. */
5055 return task_has_system(current, SYSTEM__IPC_INFO);
5056 case IPC_STAT:
5057 case MSG_STAT:
5058 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5059 break;
5060 case IPC_SET:
5061 perms = MSGQ__SETATTR;
5062 break;
5063 case IPC_RMID:
5064 perms = MSGQ__DESTROY;
5065 break;
5066 default:
5067 return 0;
5068 }
5069
Stephen Smalley6af963f2005-05-01 08:58:39 -07005070 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 return err;
5072}
5073
5074static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5075{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 struct ipc_security_struct *isec;
5077 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005078 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005079 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080 int rc;
5081
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 isec = msq->q_perm.security;
5083 msec = msg->security;
5084
5085 /*
5086 * First time through, need to assign label to the message
5087 */
5088 if (msec->sid == SECINITSID_UNLABELED) {
5089 /*
5090 * Compute new sid based on current process and
5091 * message queue this message will be stored in
5092 */
David Howells275bb412008-11-14 10:39:19 +11005093 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005094 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095 if (rc)
5096 return rc;
5097 }
5098
Eric Paris50c205f2012-04-04 15:01:43 -04005099 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100 ad.u.ipc_id = msq->q_perm.key;
5101
5102 /* Can this process write to the queue? */
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__WRITE, &ad);
5105 if (!rc)
5106 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005107 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5108 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 if (!rc)
5110 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005111 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5112 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005113
5114 return rc;
5115}
5116
5117static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5118 struct task_struct *target,
5119 long type, int mode)
5120{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121 struct ipc_security_struct *isec;
5122 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005123 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005124 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 int rc;
5126
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 isec = msq->q_perm.security;
5128 msec = msg->security;
5129
Eric Paris50c205f2012-04-04 15:01:43 -04005130 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005131 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132
David Howells275bb412008-11-14 10:39:19 +11005133 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134 SECCLASS_MSGQ, MSGQ__READ, &ad);
5135 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005136 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137 SECCLASS_MSG, MSG__RECEIVE, &ad);
5138 return rc;
5139}
5140
5141/* Shared Memory security operations */
5142static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5143{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005145 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005146 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 int rc;
5148
5149 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5150 if (rc)
5151 return rc;
5152
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 isec = shp->shm_perm.security;
5154
Eric Paris50c205f2012-04-04 15:01:43 -04005155 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005156 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157
David Howells275bb412008-11-14 10:39:19 +11005158 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 SHM__CREATE, &ad);
5160 if (rc) {
5161 ipc_free_security(&shp->shm_perm);
5162 return rc;
5163 }
5164 return 0;
5165}
5166
5167static void selinux_shm_free_security(struct shmid_kernel *shp)
5168{
5169 ipc_free_security(&shp->shm_perm);
5170}
5171
5172static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5173{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005175 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005176 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178 isec = shp->shm_perm.security;
5179
Eric Paris50c205f2012-04-04 15:01:43 -04005180 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181 ad.u.ipc_id = shp->shm_perm.key;
5182
David Howells275bb412008-11-14 10:39:19 +11005183 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 SHM__ASSOCIATE, &ad);
5185}
5186
5187/* Note, at this point, shp is locked down */
5188static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5189{
5190 int perms;
5191 int err;
5192
Eric Paris828dfe12008-04-17 13:17:49 -04005193 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194 case IPC_INFO:
5195 case SHM_INFO:
5196 /* No specific object, just general system-wide information. */
5197 return task_has_system(current, SYSTEM__IPC_INFO);
5198 case IPC_STAT:
5199 case SHM_STAT:
5200 perms = SHM__GETATTR | SHM__ASSOCIATE;
5201 break;
5202 case IPC_SET:
5203 perms = SHM__SETATTR;
5204 break;
5205 case SHM_LOCK:
5206 case SHM_UNLOCK:
5207 perms = SHM__LOCK;
5208 break;
5209 case IPC_RMID:
5210 perms = SHM__DESTROY;
5211 break;
5212 default:
5213 return 0;
5214 }
5215
Stephen Smalley6af963f2005-05-01 08:58:39 -07005216 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 return err;
5218}
5219
5220static int selinux_shm_shmat(struct shmid_kernel *shp,
5221 char __user *shmaddr, int shmflg)
5222{
5223 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
5225 if (shmflg & SHM_RDONLY)
5226 perms = SHM__READ;
5227 else
5228 perms = SHM__READ | SHM__WRITE;
5229
Stephen Smalley6af963f2005-05-01 08:58:39 -07005230 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231}
5232
5233/* Semaphore security operations */
5234static int selinux_sem_alloc_security(struct sem_array *sma)
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;
David Howells275bb412008-11-14 10:39:19 +11005238 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 int rc;
5240
5241 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5242 if (rc)
5243 return rc;
5244
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 isec = sma->sem_perm.security;
5246
Eric Paris50c205f2012-04-04 15:01:43 -04005247 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005248 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249
David Howells275bb412008-11-14 10:39:19 +11005250 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 SEM__CREATE, &ad);
5252 if (rc) {
5253 ipc_free_security(&sma->sem_perm);
5254 return rc;
5255 }
5256 return 0;
5257}
5258
5259static void selinux_sem_free_security(struct sem_array *sma)
5260{
5261 ipc_free_security(&sma->sem_perm);
5262}
5263
5264static int selinux_sem_associate(struct sem_array *sma, int semflg)
5265{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005267 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005268 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 isec = sma->sem_perm.security;
5271
Eric Paris50c205f2012-04-04 15:01:43 -04005272 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273 ad.u.ipc_id = sma->sem_perm.key;
5274
David Howells275bb412008-11-14 10:39:19 +11005275 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276 SEM__ASSOCIATE, &ad);
5277}
5278
5279/* Note, at this point, sma is locked down */
5280static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5281{
5282 int err;
5283 u32 perms;
5284
Eric Paris828dfe12008-04-17 13:17:49 -04005285 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286 case IPC_INFO:
5287 case SEM_INFO:
5288 /* No specific object, just general system-wide information. */
5289 return task_has_system(current, SYSTEM__IPC_INFO);
5290 case GETPID:
5291 case GETNCNT:
5292 case GETZCNT:
5293 perms = SEM__GETATTR;
5294 break;
5295 case GETVAL:
5296 case GETALL:
5297 perms = SEM__READ;
5298 break;
5299 case SETVAL:
5300 case SETALL:
5301 perms = SEM__WRITE;
5302 break;
5303 case IPC_RMID:
5304 perms = SEM__DESTROY;
5305 break;
5306 case IPC_SET:
5307 perms = SEM__SETATTR;
5308 break;
5309 case IPC_STAT:
5310 case SEM_STAT:
5311 perms = SEM__GETATTR | SEM__ASSOCIATE;
5312 break;
5313 default:
5314 return 0;
5315 }
5316
Stephen Smalley6af963f2005-05-01 08:58:39 -07005317 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318 return err;
5319}
5320
5321static int selinux_sem_semop(struct sem_array *sma,
5322 struct sembuf *sops, unsigned nsops, int alter)
5323{
5324 u32 perms;
5325
5326 if (alter)
5327 perms = SEM__READ | SEM__WRITE;
5328 else
5329 perms = SEM__READ;
5330
Stephen Smalley6af963f2005-05-01 08:58:39 -07005331 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332}
5333
5334static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5335{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 u32 av = 0;
5337
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 av = 0;
5339 if (flag & S_IRUGO)
5340 av |= IPC__UNIX_READ;
5341 if (flag & S_IWUGO)
5342 av |= IPC__UNIX_WRITE;
5343
5344 if (av == 0)
5345 return 0;
5346
Stephen Smalley6af963f2005-05-01 08:58:39 -07005347 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348}
5349
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005350static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5351{
5352 struct ipc_security_struct *isec = ipcp->security;
5353 *secid = isec->sid;
5354}
5355
Eric Paris828dfe12008-04-17 13:17:49 -04005356static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357{
5358 if (inode)
5359 inode_doinit_with_dentry(inode, dentry);
5360}
5361
5362static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005363 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364{
David Howells275bb412008-11-14 10:39:19 +11005365 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005366 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005368 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369
5370 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005371 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372 if (error)
5373 return error;
5374 }
5375
David Howells275bb412008-11-14 10:39:19 +11005376 rcu_read_lock();
5377 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
5379 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005380 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005382 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005384 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005386 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005387 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005388 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005389 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005390 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391 else
David Howells275bb412008-11-14 10:39:19 +11005392 goto invalid;
5393 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394
5395 if (!sid)
5396 return 0;
5397
Al Viro04ff9702007-03-12 16:17:58 +00005398 error = security_sid_to_context(sid, value, &len);
5399 if (error)
5400 return error;
5401 return len;
David Howells275bb412008-11-14 10:39:19 +11005402
5403invalid:
5404 rcu_read_unlock();
5405 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406}
5407
5408static int selinux_setprocattr(struct task_struct *p,
5409 char *name, void *value, size_t size)
5410{
5411 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005412 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005413 struct cred *new;
5414 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415 int error;
5416 char *str = value;
5417
5418 if (current != p) {
5419 /* SELinux only allows a process to change its own
5420 security attributes. */
5421 return -EACCES;
5422 }
5423
5424 /*
5425 * Basic control over ability to set these attributes at all.
5426 * current == p, but we'll pass them separately in case the
5427 * above restriction is ever removed.
5428 */
5429 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005430 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005432 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005433 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005434 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005435 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005436 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005438 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439 else
5440 error = -EINVAL;
5441 if (error)
5442 return error;
5443
5444 /* Obtain a SID for the context, if one was specified. */
5445 if (size && str[1] && str[1] != '\n') {
5446 if (str[size-1] == '\n') {
5447 str[size-1] = 0;
5448 size--;
5449 }
5450 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005451 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005452 if (!capable(CAP_MAC_ADMIN)) {
5453 struct audit_buffer *ab;
5454 size_t audit_size;
5455
5456 /* We strip a nul only if it is at the end, otherwise the
5457 * context contains a nul and we should audit that */
5458 if (str[size - 1] == '\0')
5459 audit_size = size - 1;
5460 else
5461 audit_size = size;
5462 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5463 audit_log_format(ab, "op=fscreate invalid_context=");
5464 audit_log_n_untrustedstring(ab, value, audit_size);
5465 audit_log_end(ab);
5466
Stephen Smalley12b29f32008-05-07 13:03:20 -04005467 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005468 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005469 error = security_context_to_sid_force(value, size,
5470 &sid);
5471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472 if (error)
5473 return error;
5474 }
5475
David Howellsd84f4f92008-11-14 10:39:23 +11005476 new = prepare_creds();
5477 if (!new)
5478 return -ENOMEM;
5479
Linus Torvalds1da177e2005-04-16 15:20:36 -07005480 /* Permission checking based on the specified context is
5481 performed during the actual operation (execve,
5482 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005483 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 checks and may_create for the file creation checks. The
5485 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005486 tsec = new->security;
5487 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005489 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005491 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005492 error = may_create_key(sid, p);
5493 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005494 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005495 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005496 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005497 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005498 } else if (!strcmp(name, "current")) {
5499 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005501 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005502
David Howellsd84f4f92008-11-14 10:39:23 +11005503 /* Only allow single threaded processes to change context */
5504 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005505 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005506 error = security_bounded_transition(tsec->sid, sid);
5507 if (error)
5508 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510
5511 /* Check permissions for the transition. */
5512 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005513 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005515 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516
5517 /* Check for ptracing, and update the task SID if ok.
5518 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005519 ptsid = 0;
Oleg Nesterov2b259252013-12-23 17:45:01 -05005520 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005521 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005522 if (tracer)
5523 ptsid = task_sid(tracer);
Oleg Nesterov2b259252013-12-23 17:45:01 -05005524 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525
David Howellsd84f4f92008-11-14 10:39:23 +11005526 if (tracer) {
5527 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5528 PROCESS__PTRACE, NULL);
5529 if (error)
5530 goto abort_change;
5531 }
5532
5533 tsec->sid = sid;
5534 } else {
5535 error = -EINVAL;
5536 goto abort_change;
5537 }
5538
5539 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005541
5542abort_change:
5543 abort_creds(new);
5544 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545}
5546
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005547static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5548{
5549 return security_sid_to_context(secid, secdata, seclen);
5550}
5551
David Howells7bf570d2008-04-29 20:52:51 +01005552static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005553{
5554 return security_context_to_sid(secdata, seclen, secid);
5555}
5556
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005557static void selinux_release_secctx(char *secdata, u32 seclen)
5558{
Paul Moore088999e2007-08-01 11:12:58 -04005559 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005560}
5561
David P. Quigley1ee65e32009-09-03 14:25:57 -04005562/*
5563 * called with inode->i_mutex locked
5564 */
5565static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5566{
5567 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5568}
5569
5570/*
5571 * called with inode->i_mutex locked
5572 */
5573static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5574{
5575 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5576}
5577
5578static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5579{
5580 int len = 0;
5581 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5582 ctx, true);
5583 if (len < 0)
5584 return len;
5585 *ctxlen = len;
5586 return 0;
5587}
Michael LeMayd7200242006-06-22 14:47:17 -07005588#ifdef CONFIG_KEYS
5589
David Howellsd84f4f92008-11-14 10:39:23 +11005590static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005591 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005592{
David Howellsd84f4f92008-11-14 10:39:23 +11005593 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005594 struct key_security_struct *ksec;
5595
5596 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5597 if (!ksec)
5598 return -ENOMEM;
5599
David Howellsd84f4f92008-11-14 10:39:23 +11005600 tsec = cred->security;
5601 if (tsec->keycreate_sid)
5602 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005603 else
David Howellsd84f4f92008-11-14 10:39:23 +11005604 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005605
David Howells275bb412008-11-14 10:39:19 +11005606 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005607 return 0;
5608}
5609
5610static void selinux_key_free(struct key *k)
5611{
5612 struct key_security_struct *ksec = k->security;
5613
5614 k->security = NULL;
5615 kfree(ksec);
5616}
5617
5618static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005619 const struct cred *cred,
5620 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005621{
5622 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005623 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005624 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005625
5626 /* if no specific permissions are requested, we skip the
5627 permission check. No serious, additional covert channels
5628 appear to be created. */
5629 if (perm == 0)
5630 return 0;
5631
David Howellsd84f4f92008-11-14 10:39:23 +11005632 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005633
5634 key = key_ref_to_ptr(key_ref);
5635 ksec = key->security;
5636
5637 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005638}
5639
David Howells70a5bb72008-04-29 01:01:26 -07005640static int selinux_key_getsecurity(struct key *key, char **_buffer)
5641{
5642 struct key_security_struct *ksec = key->security;
5643 char *context = NULL;
5644 unsigned len;
5645 int rc;
5646
5647 rc = security_sid_to_context(ksec->sid, &context, &len);
5648 if (!rc)
5649 rc = len;
5650 *_buffer = context;
5651 return rc;
5652}
5653
Michael LeMayd7200242006-06-22 14:47:17 -07005654#endif
5655
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005657 .name = "selinux",
5658
Ingo Molnar9e488582009-05-07 19:26:19 +10005659 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005660 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005662 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663 .capable = selinux_capable,
5664 .quotactl = selinux_quotactl,
5665 .quota_on = selinux_quota_on,
5666 .syslog = selinux_syslog,
5667 .vm_enough_memory = selinux_vm_enough_memory,
5668
5669 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
David Howellsa6f76f22008-11-14 10:39:24 +11005671 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005672 .bprm_committing_creds = selinux_bprm_committing_creds,
5673 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 .bprm_secureexec = selinux_bprm_secureexec,
5675
5676 .sb_alloc_security = selinux_sb_alloc_security,
5677 .sb_free_security = selinux_sb_free_security,
5678 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005679 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005680 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005681 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 .sb_statfs = selinux_sb_statfs,
5683 .sb_mount = selinux_mount,
5684 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005685 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005686 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005687 .sb_parse_opts_str = selinux_parse_opts_str,
5688
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689
5690 .inode_alloc_security = selinux_inode_alloc_security,
5691 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005692 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005694 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695 .inode_unlink = selinux_inode_unlink,
5696 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 .inode_rmdir = selinux_inode_rmdir,
5699 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701 .inode_readlink = selinux_inode_readlink,
5702 .inode_follow_link = selinux_inode_follow_link,
5703 .inode_permission = selinux_inode_permission,
5704 .inode_setattr = selinux_inode_setattr,
5705 .inode_getattr = selinux_inode_getattr,
5706 .inode_setxattr = selinux_inode_setxattr,
5707 .inode_post_setxattr = selinux_inode_post_setxattr,
5708 .inode_getxattr = selinux_inode_getxattr,
5709 .inode_listxattr = selinux_inode_listxattr,
5710 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005711 .inode_getsecurity = selinux_inode_getsecurity,
5712 .inode_setsecurity = selinux_inode_setsecurity,
5713 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005714 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
5716 .file_permission = selinux_file_permission,
5717 .file_alloc_security = selinux_file_alloc_security,
5718 .file_free_security = selinux_file_free_security,
5719 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005720 .mmap_file = selinux_mmap_file,
5721 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005722 .file_mprotect = selinux_file_mprotect,
5723 .file_lock = selinux_file_lock,
5724 .file_fcntl = selinux_file_fcntl,
5725 .file_set_fowner = selinux_file_set_fowner,
5726 .file_send_sigiotask = selinux_file_send_sigiotask,
5727 .file_receive = selinux_file_receive,
5728
Eric Paris83d49852012-04-04 13:45:40 -04005729 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005730
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005732 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005733 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005734 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005735 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005736 .kernel_act_as = selinux_kernel_act_as,
5737 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005738 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739 .task_setpgid = selinux_task_setpgid,
5740 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005741 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005742 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005744 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005745 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746 .task_setrlimit = selinux_task_setrlimit,
5747 .task_setscheduler = selinux_task_setscheduler,
5748 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005749 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750 .task_kill = selinux_task_kill,
5751 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005752 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753
5754 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005755 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756
5757 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5758 .msg_msg_free_security = selinux_msg_msg_free_security,
5759
5760 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5761 .msg_queue_free_security = selinux_msg_queue_free_security,
5762 .msg_queue_associate = selinux_msg_queue_associate,
5763 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5764 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5765 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5766
5767 .shm_alloc_security = selinux_shm_alloc_security,
5768 .shm_free_security = selinux_shm_free_security,
5769 .shm_associate = selinux_shm_associate,
5770 .shm_shmctl = selinux_shm_shmctl,
5771 .shm_shmat = selinux_shm_shmat,
5772
Eric Paris828dfe12008-04-17 13:17:49 -04005773 .sem_alloc_security = selinux_sem_alloc_security,
5774 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775 .sem_associate = selinux_sem_associate,
5776 .sem_semctl = selinux_sem_semctl,
5777 .sem_semop = selinux_sem_semop,
5778
Eric Paris828dfe12008-04-17 13:17:49 -04005779 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780
Eric Paris828dfe12008-04-17 13:17:49 -04005781 .getprocattr = selinux_getprocattr,
5782 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005784 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005785 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005786 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005787 .inode_notifysecctx = selinux_inode_notifysecctx,
5788 .inode_setsecctx = selinux_inode_setsecctx,
5789 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005790
Eric Paris828dfe12008-04-17 13:17:49 -04005791 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792 .unix_may_send = selinux_socket_unix_may_send,
5793
5794 .socket_create = selinux_socket_create,
5795 .socket_post_create = selinux_socket_post_create,
5796 .socket_bind = selinux_socket_bind,
5797 .socket_connect = selinux_socket_connect,
5798 .socket_listen = selinux_socket_listen,
5799 .socket_accept = selinux_socket_accept,
5800 .socket_sendmsg = selinux_socket_sendmsg,
5801 .socket_recvmsg = selinux_socket_recvmsg,
5802 .socket_getsockname = selinux_socket_getsockname,
5803 .socket_getpeername = selinux_socket_getpeername,
5804 .socket_getsockopt = selinux_socket_getsockopt,
5805 .socket_setsockopt = selinux_socket_setsockopt,
5806 .socket_shutdown = selinux_socket_shutdown,
5807 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005808 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5809 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810 .sk_alloc_security = selinux_sk_alloc_security,
5811 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005812 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005813 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005814 .sock_graft = selinux_sock_graft,
5815 .inet_conn_request = selinux_inet_conn_request,
5816 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005817 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005818 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5819 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5820 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005821 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005822 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5823 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005824 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005825 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005826 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005827 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005828 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005829
5830#ifdef CONFIG_SECURITY_NETWORK_XFRM
5831 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5832 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5833 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005834 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005835 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5836 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005837 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005838 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005839 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005840 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005842
5843#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005844 .key_alloc = selinux_key_alloc,
5845 .key_free = selinux_key_free,
5846 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005847 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005848#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005849
5850#ifdef CONFIG_AUDIT
5851 .audit_rule_init = selinux_audit_rule_init,
5852 .audit_rule_known = selinux_audit_rule_known,
5853 .audit_rule_match = selinux_audit_rule_match,
5854 .audit_rule_free = selinux_audit_rule_free,
5855#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856};
5857
5858static __init int selinux_init(void)
5859{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005860 if (!security_module_enable(&selinux_ops)) {
5861 selinux_enabled = 0;
5862 return 0;
5863 }
5864
Linus Torvalds1da177e2005-04-16 15:20:36 -07005865 if (!selinux_enabled) {
5866 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5867 return 0;
5868 }
5869
5870 printk(KERN_INFO "SELinux: Initializing.\n");
5871
5872 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005873 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005875 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5876
James Morris7cae7e22006-03-22 00:09:22 -08005877 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5878 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005879 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880 avc_init();
5881
Eric Paris828dfe12008-04-17 13:17:49 -04005882 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883 panic("SELinux: Unable to register with kernel.\n");
5884
Eric Paris828dfe12008-04-17 13:17:49 -04005885 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005886 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005887 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005888 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005889
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890 return 0;
5891}
5892
Al Viroe8c26252010-03-23 06:36:54 -04005893static void delayed_superblock_init(struct super_block *sb, void *unused)
5894{
5895 superblock_doinit(sb, NULL);
5896}
5897
Linus Torvalds1da177e2005-04-16 15:20:36 -07005898void selinux_complete_init(void)
5899{
Eric Parisfadcdb42007-02-22 18:11:31 -05005900 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901
5902 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005903 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005904 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905}
5906
5907/* SELinux requires early initialization in order to label
5908 all processes and objects when they are created. */
5909security_initcall(selinux_init);
5910
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005911#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Paul Mooreeffad8d2008-01-29 08:49:27 -05005913static struct nf_hook_ops selinux_ipv4_ops[] = {
5914 {
5915 .hook = selinux_ipv4_postroute,
5916 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005917 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005918 .hooknum = NF_INET_POST_ROUTING,
5919 .priority = NF_IP_PRI_SELINUX_LAST,
5920 },
5921 {
5922 .hook = selinux_ipv4_forward,
5923 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005924 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005925 .hooknum = NF_INET_FORWARD,
5926 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005927 },
5928 {
5929 .hook = selinux_ipv4_output,
5930 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005931 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04005932 .hooknum = NF_INET_LOCAL_OUT,
5933 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935};
5936
5937#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5938
Paul Mooreeffad8d2008-01-29 08:49:27 -05005939static struct nf_hook_ops selinux_ipv6_ops[] = {
5940 {
5941 .hook = selinux_ipv6_postroute,
5942 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005943 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005944 .hooknum = NF_INET_POST_ROUTING,
5945 .priority = NF_IP6_PRI_SELINUX_LAST,
5946 },
5947 {
5948 .hook = selinux_ipv6_forward,
5949 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005950 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005951 .hooknum = NF_INET_FORWARD,
5952 .priority = NF_IP6_PRI_SELINUX_FIRST,
5953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954};
5955
5956#endif /* IPV6 */
5957
5958static int __init selinux_nf_ip_init(void)
5959{
5960 int err = 0;
5961
5962 if (!selinux_enabled)
5963 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005964
5965 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5966
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005967 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5968 if (err)
5969 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970
5971#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005972 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5973 if (err)
5974 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005976
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977out:
5978 return err;
5979}
5980
5981__initcall(selinux_nf_ip_init);
5982
5983#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5984static void selinux_nf_ip_exit(void)
5985{
Eric Parisfadcdb42007-02-22 18:11:31 -05005986 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005988 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005990 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991#endif /* IPV6 */
5992}
5993#endif
5994
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005995#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996
5997#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5998#define selinux_nf_ip_exit()
5999#endif
6000
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006001#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
6003#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006004static int selinux_disabled;
6005
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006int selinux_disable(void)
6007{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008 if (ss_initialized) {
6009 /* Not permitted after initial policy load. */
6010 return -EINVAL;
6011 }
6012
6013 if (selinux_disabled) {
6014 /* Only do this once. */
6015 return -EINVAL;
6016 }
6017
6018 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6019
6020 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006021 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006022
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006023 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024
Eric Parisaf8ff042009-09-20 21:23:01 -04006025 /* Try to destroy the avc node cache */
6026 avc_disable();
6027
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028 /* Unregister netfilter hooks. */
6029 selinux_nf_ip_exit();
6030
6031 /* Unregister selinuxfs. */
6032 exit_sel_fs();
6033
6034 return 0;
6035}
6036#endif