blob: 75c2e99bfb813a0653350bf18572d1359878dde5 [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>
7 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
10 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com>
Paul Mooreeffad8d2008-01-29 08:49:27 -050015 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
16 * Paul Moore <paul.moore@hp.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090017 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
18 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2,
22 * as published by the Free Software Foundation.
23 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/init.h>
26#include <linux/kernel.h>
27#include <linux/ptrace.h>
28#include <linux/errno.h>
29#include <linux/sched.h>
30#include <linux/security.h>
31#include <linux/xattr.h>
32#include <linux/capability.h>
33#include <linux/unistd.h>
34#include <linux/mm.h>
35#include <linux/mman.h>
36#include <linux/slab.h>
37#include <linux/pagemap.h>
38#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/spinlock.h>
40#include <linux/syscalls.h>
41#include <linux/file.h>
42#include <linux/namei.h>
43#include <linux/mount.h>
44#include <linux/ext2_fs.h>
45#include <linux/proc_fs.h>
46#include <linux/kd.h>
47#include <linux/netfilter_ipv4.h>
48#include <linux/netfilter_ipv6.h>
49#include <linux/tty.h>
50#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070051#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050053#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050054#include <net/netlabel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <asm/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <asm/ioctls.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <asm/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#include <linux/bitops.h>
59#include <linux/interrupt.h>
60#include <linux/netdevice.h> /* for network interface checks */
61#include <linux/netlink.h>
62#include <linux/tcp.h>
63#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080064#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/quota.h>
66#include <linux/un.h> /* for Unix socket types */
67#include <net/af_unix.h> /* for Unix socket types */
68#include <linux/parser.h>
69#include <linux/nfs_mount.h>
70#include <net/ipv6.h>
71#include <linux/hugetlb.h>
72#include <linux/personality.h>
73#include <linux/sysctl.h>
74#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070075#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070076#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070077#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79#include "avc.h"
80#include "objsec.h"
81#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050082#include "netnode.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080083#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050084#include "netlabel.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86#define XATTR_SELINUX_SUFFIX "selinux"
87#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
88
Eric Parisc9180a52007-11-30 13:00:35 -050089#define NUM_SEL_MNT_OPTS 4
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091extern unsigned int policydb_loaded_version;
92extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
James Morris4e5ab4c2006-06-09 00:33:33 -070093extern int selinux_compat_net;
James Morris20510f22007-10-16 23:31:32 -070094extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Paul Moored621d352008-01-29 08:43:36 -050096/* SECMARK reference count */
97atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
98
Linus Torvalds1da177e2005-04-16 15:20:36 -070099#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
100int selinux_enforcing = 0;
101
102static int __init enforcing_setup(char *str)
103{
104 selinux_enforcing = simple_strtol(str,NULL,0);
105 return 1;
106}
107__setup("enforcing=", enforcing_setup);
108#endif
109
110#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
111int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
112
113static int __init selinux_enabled_setup(char *str)
114{
115 selinux_enabled = simple_strtol(str, NULL, 0);
116 return 1;
117}
118__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400119#else
120int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121#endif
122
123/* Original (dummy) security module. */
124static struct security_operations *original_ops = NULL;
125
126/* Minimal support for a secondary security module,
127 just to allow the use of the dummy or capability modules.
128 The owlsm module can alternatively be used as a secondary
129 module as long as CONFIG_OWLSM_FD is not enabled. */
130static struct security_operations *secondary_ops = NULL;
131
132/* Lists of inode and superblock security structures initialized
133 before the policy was loaded. */
134static LIST_HEAD(superblock_security_head);
135static DEFINE_SPINLOCK(sb_security_lock);
136
Christoph Lametere18b8902006-12-06 20:33:20 -0800137static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800138
Paul Moored621d352008-01-29 08:43:36 -0500139/**
140 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
141 *
142 * Description:
143 * This function checks the SECMARK reference counter to see if any SECMARK
144 * targets are currently configured, if the reference counter is greater than
145 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
146 * enabled, false (0) if SECMARK is disabled.
147 *
148 */
149static int selinux_secmark_enabled(void)
150{
151 return (atomic_read(&selinux_secmark_refcount) > 0);
152}
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154/* Allocate and free functions for each kind of security blob. */
155
156static int task_alloc_security(struct task_struct *task)
157{
158 struct task_security_struct *tsec;
159
James Morris89d155e2005-10-30 14:59:21 -0800160 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 if (!tsec)
162 return -ENOMEM;
163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 tsec->task = task;
165 tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
166 task->security = tsec;
167
168 return 0;
169}
170
171static void task_free_security(struct task_struct *task)
172{
173 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 task->security = NULL;
175 kfree(tsec);
176}
177
178static int inode_alloc_security(struct inode *inode)
179{
180 struct task_security_struct *tsec = current->security;
181 struct inode_security_struct *isec;
182
Robert P. J. Dayc3762222007-02-10 01:45:03 -0800183 isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 if (!isec)
185 return -ENOMEM;
186
Eric Paris23970742006-09-25 23:32:01 -0700187 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 isec->inode = inode;
190 isec->sid = SECINITSID_UNLABELED;
191 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800192 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 inode->i_security = isec;
194
195 return 0;
196}
197
198static void inode_free_security(struct inode *inode)
199{
200 struct inode_security_struct *isec = inode->i_security;
201 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 spin_lock(&sbsec->isec_lock);
204 if (!list_empty(&isec->list))
205 list_del_init(&isec->list);
206 spin_unlock(&sbsec->isec_lock);
207
208 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800209 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210}
211
212static int file_alloc_security(struct file *file)
213{
214 struct task_security_struct *tsec = current->security;
215 struct file_security_struct *fsec;
216
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800217 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 if (!fsec)
219 return -ENOMEM;
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 fsec->file = file;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800222 fsec->sid = tsec->sid;
223 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 file->f_security = fsec;
225
226 return 0;
227}
228
229static void file_free_security(struct file *file)
230{
231 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 file->f_security = NULL;
233 kfree(fsec);
234}
235
236static int superblock_alloc_security(struct super_block *sb)
237{
238 struct superblock_security_struct *sbsec;
239
James Morris89d155e2005-10-30 14:59:21 -0800240 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (!sbsec)
242 return -ENOMEM;
243
Eric Parisbc7e9822006-09-25 23:32:02 -0700244 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 INIT_LIST_HEAD(&sbsec->list);
246 INIT_LIST_HEAD(&sbsec->isec_head);
247 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 sbsec->sb = sb;
249 sbsec->sid = SECINITSID_UNLABELED;
250 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700251 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 sb->s_security = sbsec;
253
254 return 0;
255}
256
257static void superblock_free_security(struct super_block *sb)
258{
259 struct superblock_security_struct *sbsec = sb->s_security;
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 spin_lock(&sb_security_lock);
262 if (!list_empty(&sbsec->list))
263 list_del_init(&sbsec->list);
264 spin_unlock(&sb_security_lock);
265
266 sb->s_security = NULL;
267 kfree(sbsec);
268}
269
Al Viro7d877f32005-10-21 03:20:43 -0400270static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 struct sk_security_struct *ssec;
273
James Morris89d155e2005-10-30 14:59:21 -0800274 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 if (!ssec)
276 return -ENOMEM;
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 ssec->sk = sk;
279 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700280 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 sk->sk_security = ssec;
282
Paul Moore99f59ed2006-08-29 17:53:48 -0700283 selinux_netlbl_sk_security_init(ssec, family);
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 return 0;
286}
287
288static void sk_free_security(struct sock *sk)
289{
290 struct sk_security_struct *ssec = sk->sk_security;
291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 sk->sk_security = NULL;
293 kfree(ssec);
294}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
296/* The security server must be initialized before
297 any labeling or access decisions can be provided. */
298extern int ss_initialized;
299
300/* The file system's label must be initialized prior to use. */
301
302static char *labeling_behaviors[6] = {
303 "uses xattr",
304 "uses transition SIDs",
305 "uses task SIDs",
306 "uses genfs_contexts",
307 "not configured for labeling",
308 "uses mountpoint labeling",
309};
310
311static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
312
313static inline int inode_doinit(struct inode *inode)
314{
315 return inode_doinit_with_dentry(inode, NULL);
316}
317
318enum {
Eric Paris31e87932007-09-19 17:19:12 -0400319 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 Opt_context = 1,
321 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500322 Opt_defcontext = 3,
323 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324};
325
326static match_table_t tokens = {
327 {Opt_context, "context=%s"},
328 {Opt_fscontext, "fscontext=%s"},
329 {Opt_defcontext, "defcontext=%s"},
Eric Paris08089252006-07-10 04:43:55 -0700330 {Opt_rootcontext, "rootcontext=%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400331 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332};
333
334#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
335
Eric Parisc312feb2006-07-10 04:43:53 -0700336static int may_context_mount_sb_relabel(u32 sid,
337 struct superblock_security_struct *sbsec,
338 struct task_security_struct *tsec)
339{
340 int rc;
341
342 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
343 FILESYSTEM__RELABELFROM, NULL);
344 if (rc)
345 return rc;
346
347 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
348 FILESYSTEM__RELABELTO, NULL);
349 return rc;
350}
351
Eric Paris08089252006-07-10 04:43:55 -0700352static int may_context_mount_inode_relabel(u32 sid,
353 struct superblock_security_struct *sbsec,
354 struct task_security_struct *tsec)
355{
356 int rc;
357 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
358 FILESYSTEM__RELABELFROM, NULL);
359 if (rc)
360 return rc;
361
362 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
363 FILESYSTEM__ASSOCIATE, NULL);
364 return rc;
365}
366
Eric Parisc9180a52007-11-30 13:00:35 -0500367static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
369 struct superblock_security_struct *sbsec = sb->s_security;
370 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500371 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 int rc = 0;
373
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
375 /* Make sure that the xattr handler exists and that no
376 error other than -ENODATA is returned by getxattr on
377 the root directory. -ENODATA is ok, as this may be
378 the first boot of the SELinux kernel before we have
379 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500380 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
382 "xattr support\n", sb->s_id, sb->s_type->name);
383 rc = -EOPNOTSUPP;
384 goto out;
385 }
Eric Parisc9180a52007-11-30 13:00:35 -0500386 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 if (rc < 0 && rc != -ENODATA) {
388 if (rc == -EOPNOTSUPP)
389 printk(KERN_WARNING "SELinux: (dev %s, type "
390 "%s) has no security xattr handler\n",
391 sb->s_id, sb->s_type->name);
392 else
393 printk(KERN_WARNING "SELinux: (dev %s, type "
394 "%s) getxattr errno %d\n", sb->s_id,
395 sb->s_type->name, -rc);
396 goto out;
397 }
398 }
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 sbsec->initialized = 1;
401
Eric Parisc9180a52007-11-30 13:00:35 -0500402 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500403 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500405 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500406 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 sb->s_id, sb->s_type->name,
408 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500411 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
413 /* Initialize any other inodes associated with the superblock, e.g.
414 inodes created prior to initial policy load or inodes created
415 during get_sb by a pseudo filesystem that directly
416 populates itself. */
417 spin_lock(&sbsec->isec_lock);
418next_inode:
419 if (!list_empty(&sbsec->isec_head)) {
420 struct inode_security_struct *isec =
421 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500422 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 struct inode *inode = isec->inode;
424 spin_unlock(&sbsec->isec_lock);
425 inode = igrab(inode);
426 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500427 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 inode_doinit(inode);
429 iput(inode);
430 }
431 spin_lock(&sbsec->isec_lock);
432 list_del_init(&isec->list);
433 goto next_inode;
434 }
435 spin_unlock(&sbsec->isec_lock);
436out:
Eric Parisc9180a52007-11-30 13:00:35 -0500437 return rc;
438}
439
440/*
441 * This function should allow an FS to ask what it's mount security
442 * options were so it can use those later for submounts, displaying
443 * mount options, or whatever.
444 */
445static int selinux_get_mnt_opts(const struct super_block *sb,
446 char ***mount_options, int **mnt_opts_flags,
447 int *num_opts)
448{
449 int rc = 0, i;
450 struct superblock_security_struct *sbsec = sb->s_security;
451 char *context = NULL;
452 u32 len;
453 char tmp;
454
455 *num_opts = 0;
456 *mount_options = NULL;
457 *mnt_opts_flags = NULL;
458
459 if (!sbsec->initialized)
460 return -EINVAL;
461
462 if (!ss_initialized)
463 return -EINVAL;
464
465 /*
466 * if we ever use sbsec flags for anything other than tracking mount
467 * settings this is going to need a mask
468 */
469 tmp = sbsec->flags;
470 /* count the number of mount options for this sb */
471 for (i = 0; i < 8; i++) {
472 if (tmp & 0x01)
473 (*num_opts)++;
474 tmp >>= 1;
475 }
476
477 *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
478 if (!*mount_options) {
479 rc = -ENOMEM;
480 goto out_free;
481 }
482
483 *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
484 if (!*mnt_opts_flags) {
485 rc = -ENOMEM;
486 goto out_free;
487 }
488
489 i = 0;
490 if (sbsec->flags & FSCONTEXT_MNT) {
491 rc = security_sid_to_context(sbsec->sid, &context, &len);
492 if (rc)
493 goto out_free;
494 (*mount_options)[i] = context;
495 (*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
496 }
497 if (sbsec->flags & CONTEXT_MNT) {
498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
499 if (rc)
500 goto out_free;
501 (*mount_options)[i] = context;
502 (*mnt_opts_flags)[i++] = CONTEXT_MNT;
503 }
504 if (sbsec->flags & DEFCONTEXT_MNT) {
505 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
506 if (rc)
507 goto out_free;
508 (*mount_options)[i] = context;
509 (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
510 }
511 if (sbsec->flags & ROOTCONTEXT_MNT) {
512 struct inode *root = sbsec->sb->s_root->d_inode;
513 struct inode_security_struct *isec = root->i_security;
514
515 rc = security_sid_to_context(isec->sid, &context, &len);
516 if (rc)
517 goto out_free;
518 (*mount_options)[i] = context;
519 (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
520 }
521
522 BUG_ON(i != *num_opts);
523
524 return 0;
525
526out_free:
527 /* don't leak context string if security_sid_to_context had an error */
528 if (*mount_options && i)
529 for (; i > 0; i--)
530 kfree((*mount_options)[i-1]);
531 kfree(*mount_options);
532 *mount_options = NULL;
533 kfree(*mnt_opts_flags);
534 *mnt_opts_flags = NULL;
535 *num_opts = 0;
536 return rc;
537}
538
539static int bad_option(struct superblock_security_struct *sbsec, char flag,
540 u32 old_sid, u32 new_sid)
541{
542 /* check if the old mount command had the same options */
543 if (sbsec->initialized)
544 if (!(sbsec->flags & flag) ||
545 (old_sid != new_sid))
546 return 1;
547
548 /* check if we were passed the same options twice,
549 * aka someone passed context=a,context=b
550 */
551 if (!sbsec->initialized)
552 if (sbsec->flags & flag)
553 return 1;
554 return 0;
555}
556/*
557 * Allow filesystems with binary mount data to explicitly set mount point
558 * labeling information.
559 */
Adrian Bunk374ea012008-01-29 00:11:52 +0200560static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
561 int *flags, int num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500562{
563 int rc = 0, i;
564 struct task_security_struct *tsec = current->security;
565 struct superblock_security_struct *sbsec = sb->s_security;
566 const char *name = sb->s_type->name;
567 struct inode *inode = sbsec->sb->s_root->d_inode;
568 struct inode_security_struct *root_isec = inode->i_security;
569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
570 u32 defcontext_sid = 0;
571
572 mutex_lock(&sbsec->lock);
573
574 if (!ss_initialized) {
575 if (!num_opts) {
576 /* Defer initialization until selinux_complete_init,
577 after the initial policy is loaded and the security
578 server is ready to handle calls. */
579 spin_lock(&sb_security_lock);
580 if (list_empty(&sbsec->list))
581 list_add(&sbsec->list, &superblock_security_head);
582 spin_unlock(&sb_security_lock);
583 goto out;
584 }
585 rc = -EINVAL;
586 printk(KERN_WARNING "Unable to set superblock options before "
587 "the security server is initialized\n");
588 goto out;
589 }
590
591 /*
592 * parse the mount options, check if they are valid sids.
593 * also check if someone is trying to mount the same sb more
594 * than once with different security options.
595 */
596 for (i = 0; i < num_opts; i++) {
597 u32 sid;
598 rc = security_context_to_sid(mount_options[i],
599 strlen(mount_options[i]), &sid);
600 if (rc) {
601 printk(KERN_WARNING "SELinux: security_context_to_sid"
602 "(%s) failed for (dev %s, type %s) errno=%d\n",
603 mount_options[i], sb->s_id, name, rc);
604 goto out;
605 }
606 switch (flags[i]) {
607 case FSCONTEXT_MNT:
608 fscontext_sid = sid;
609
610 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
611 fscontext_sid))
612 goto out_double_mount;
613
614 sbsec->flags |= FSCONTEXT_MNT;
615 break;
616 case CONTEXT_MNT:
617 context_sid = sid;
618
619 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
620 context_sid))
621 goto out_double_mount;
622
623 sbsec->flags |= CONTEXT_MNT;
624 break;
625 case ROOTCONTEXT_MNT:
626 rootcontext_sid = sid;
627
628 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
629 rootcontext_sid))
630 goto out_double_mount;
631
632 sbsec->flags |= ROOTCONTEXT_MNT;
633
634 break;
635 case DEFCONTEXT_MNT:
636 defcontext_sid = sid;
637
638 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
639 defcontext_sid))
640 goto out_double_mount;
641
642 sbsec->flags |= DEFCONTEXT_MNT;
643
644 break;
645 default:
646 rc = -EINVAL;
647 goto out;
648 }
649 }
650
651 if (sbsec->initialized) {
652 /* previously mounted with options, but not on this attempt? */
653 if (sbsec->flags && !num_opts)
654 goto out_double_mount;
655 rc = 0;
656 goto out;
657 }
658
659 if (strcmp(sb->s_type->name, "proc") == 0)
660 sbsec->proc = 1;
661
662 /* Determine the labeling behavior to use for this filesystem type. */
663 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
664 if (rc) {
665 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
666 __FUNCTION__, sb->s_type->name, rc);
667 goto out;
668 }
669
670 /* sets the context of the superblock for the fs being mounted. */
671 if (fscontext_sid) {
672
673 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
674 if (rc)
675 goto out;
676
677 sbsec->sid = fscontext_sid;
678 }
679
680 /*
681 * Switch to using mount point labeling behavior.
682 * sets the label used on all file below the mountpoint, and will set
683 * the superblock context if not already set.
684 */
685 if (context_sid) {
686 if (!fscontext_sid) {
687 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
688 if (rc)
689 goto out;
690 sbsec->sid = context_sid;
691 } else {
692 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
693 if (rc)
694 goto out;
695 }
696 if (!rootcontext_sid)
697 rootcontext_sid = context_sid;
698
699 sbsec->mntpoint_sid = context_sid;
700 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
701 }
702
703 if (rootcontext_sid) {
704 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
705 if (rc)
706 goto out;
707
708 root_isec->sid = rootcontext_sid;
709 root_isec->initialized = 1;
710 }
711
712 if (defcontext_sid) {
713 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
714 rc = -EINVAL;
715 printk(KERN_WARNING "SELinux: defcontext option is "
716 "invalid for this filesystem type\n");
717 goto out;
718 }
719
720 if (defcontext_sid != sbsec->def_sid) {
721 rc = may_context_mount_inode_relabel(defcontext_sid,
722 sbsec, tsec);
723 if (rc)
724 goto out;
725 }
726
727 sbsec->def_sid = defcontext_sid;
728 }
729
730 rc = sb_finish_set_opts(sb);
731out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700732 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500734out_double_mount:
735 rc = -EINVAL;
736 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
737 "security settings for (dev %s, type %s)\n", sb->s_id, name);
738 goto out;
739}
740
741static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
742 struct super_block *newsb)
743{
744 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
745 struct superblock_security_struct *newsbsec = newsb->s_security;
746
747 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
748 int set_context = (oldsbsec->flags & CONTEXT_MNT);
749 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
750
751 /* we can't error, we can't save the info, this shouldn't get called
752 * this early in the boot process. */
753 BUG_ON(!ss_initialized);
754
755 /* this might go away sometime down the line if there is a new user
756 * of clone, but for now, nfs better not get here... */
757 BUG_ON(newsbsec->initialized);
758
759 /* how can we clone if the old one wasn't set up?? */
760 BUG_ON(!oldsbsec->initialized);
761
762 mutex_lock(&newsbsec->lock);
763
764 newsbsec->flags = oldsbsec->flags;
765
766 newsbsec->sid = oldsbsec->sid;
767 newsbsec->def_sid = oldsbsec->def_sid;
768 newsbsec->behavior = oldsbsec->behavior;
769
770 if (set_context) {
771 u32 sid = oldsbsec->mntpoint_sid;
772
773 if (!set_fscontext)
774 newsbsec->sid = sid;
775 if (!set_rootcontext) {
776 struct inode *newinode = newsb->s_root->d_inode;
777 struct inode_security_struct *newisec = newinode->i_security;
778 newisec->sid = sid;
779 }
780 newsbsec->mntpoint_sid = sid;
781 }
782 if (set_rootcontext) {
783 const struct inode *oldinode = oldsb->s_root->d_inode;
784 const struct inode_security_struct *oldisec = oldinode->i_security;
785 struct inode *newinode = newsb->s_root->d_inode;
786 struct inode_security_struct *newisec = newinode->i_security;
787
788 newisec->sid = oldisec->sid;
789 }
790
791 sb_finish_set_opts(newsb);
792 mutex_unlock(&newsbsec->lock);
793}
794
795/*
796 * string mount options parsing and call set the sbsec
797 */
798static int superblock_doinit(struct super_block *sb, void *data)
799{
800 char *context = NULL, *defcontext = NULL;
801 char *fscontext = NULL, *rootcontext = NULL;
802 int rc = 0;
803 char *p, *options = data;
804 /* selinux only know about a fixed number of mount options */
805 char *mnt_opts[NUM_SEL_MNT_OPTS];
806 int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
807
808 if (!data)
809 goto out;
810
811 /* with the nfs patch this will become a goto out; */
812 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
813 const char *name = sb->s_type->name;
814 /* NFS we understand. */
815 if (!strcmp(name, "nfs")) {
816 struct nfs_mount_data *d = data;
817
818 if (d->version != NFS_MOUNT_VERSION)
819 goto out;
820
821 if (d->context[0]) {
822 context = kstrdup(d->context, GFP_KERNEL);
823 if (!context) {
824 rc = -ENOMEM;
825 goto out;
826 }
827 }
828 goto build_flags;
829 } else
830 goto out;
831 }
832
833 /* Standard string-based options. */
834 while ((p = strsep(&options, "|")) != NULL) {
835 int token;
836 substring_t args[MAX_OPT_ARGS];
837
838 if (!*p)
839 continue;
840
841 token = match_token(p, tokens, args);
842
843 switch (token) {
844 case Opt_context:
845 if (context || defcontext) {
846 rc = -EINVAL;
847 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
848 goto out_err;
849 }
850 context = match_strdup(&args[0]);
851 if (!context) {
852 rc = -ENOMEM;
853 goto out_err;
854 }
855 break;
856
857 case Opt_fscontext:
858 if (fscontext) {
859 rc = -EINVAL;
860 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
861 goto out_err;
862 }
863 fscontext = match_strdup(&args[0]);
864 if (!fscontext) {
865 rc = -ENOMEM;
866 goto out_err;
867 }
868 break;
869
870 case Opt_rootcontext:
871 if (rootcontext) {
872 rc = -EINVAL;
873 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
874 goto out_err;
875 }
876 rootcontext = match_strdup(&args[0]);
877 if (!rootcontext) {
878 rc = -ENOMEM;
879 goto out_err;
880 }
881 break;
882
883 case Opt_defcontext:
884 if (context || defcontext) {
885 rc = -EINVAL;
886 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
887 goto out_err;
888 }
889 defcontext = match_strdup(&args[0]);
890 if (!defcontext) {
891 rc = -ENOMEM;
892 goto out_err;
893 }
894 break;
895
896 default:
897 rc = -EINVAL;
898 printk(KERN_WARNING "SELinux: unknown mount option\n");
899 goto out_err;
900
901 }
902 }
903
904build_flags:
905 if (fscontext) {
906 mnt_opts[num_mnt_opts] = fscontext;
907 mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
908 }
909 if (context) {
910 mnt_opts[num_mnt_opts] = context;
911 mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
912 }
913 if (rootcontext) {
914 mnt_opts[num_mnt_opts] = rootcontext;
915 mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
916 }
917 if (defcontext) {
918 mnt_opts[num_mnt_opts] = defcontext;
919 mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
920 }
921
922out:
923 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
924out_err:
925 kfree(context);
926 kfree(defcontext);
927 kfree(fscontext);
928 kfree(rootcontext);
929 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930}
931
932static inline u16 inode_mode_to_security_class(umode_t mode)
933{
934 switch (mode & S_IFMT) {
935 case S_IFSOCK:
936 return SECCLASS_SOCK_FILE;
937 case S_IFLNK:
938 return SECCLASS_LNK_FILE;
939 case S_IFREG:
940 return SECCLASS_FILE;
941 case S_IFBLK:
942 return SECCLASS_BLK_FILE;
943 case S_IFDIR:
944 return SECCLASS_DIR;
945 case S_IFCHR:
946 return SECCLASS_CHR_FILE;
947 case S_IFIFO:
948 return SECCLASS_FIFO_FILE;
949
950 }
951
952 return SECCLASS_FILE;
953}
954
James Morris13402582005-09-30 14:24:34 -0400955static inline int default_protocol_stream(int protocol)
956{
957 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
958}
959
960static inline int default_protocol_dgram(int protocol)
961{
962 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
963}
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965static inline u16 socket_type_to_security_class(int family, int type, int protocol)
966{
967 switch (family) {
968 case PF_UNIX:
969 switch (type) {
970 case SOCK_STREAM:
971 case SOCK_SEQPACKET:
972 return SECCLASS_UNIX_STREAM_SOCKET;
973 case SOCK_DGRAM:
974 return SECCLASS_UNIX_DGRAM_SOCKET;
975 }
976 break;
977 case PF_INET:
978 case PF_INET6:
979 switch (type) {
980 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -0400981 if (default_protocol_stream(protocol))
982 return SECCLASS_TCP_SOCKET;
983 else
984 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -0400986 if (default_protocol_dgram(protocol))
987 return SECCLASS_UDP_SOCKET;
988 else
989 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -0800990 case SOCK_DCCP:
991 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -0400992 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 return SECCLASS_RAWIP_SOCKET;
994 }
995 break;
996 case PF_NETLINK:
997 switch (protocol) {
998 case NETLINK_ROUTE:
999 return SECCLASS_NETLINK_ROUTE_SOCKET;
1000 case NETLINK_FIREWALL:
1001 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001002 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1004 case NETLINK_NFLOG:
1005 return SECCLASS_NETLINK_NFLOG_SOCKET;
1006 case NETLINK_XFRM:
1007 return SECCLASS_NETLINK_XFRM_SOCKET;
1008 case NETLINK_SELINUX:
1009 return SECCLASS_NETLINK_SELINUX_SOCKET;
1010 case NETLINK_AUDIT:
1011 return SECCLASS_NETLINK_AUDIT_SOCKET;
1012 case NETLINK_IP6_FW:
1013 return SECCLASS_NETLINK_IP6FW_SOCKET;
1014 case NETLINK_DNRTMSG:
1015 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001016 case NETLINK_KOBJECT_UEVENT:
1017 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 default:
1019 return SECCLASS_NETLINK_SOCKET;
1020 }
1021 case PF_PACKET:
1022 return SECCLASS_PACKET_SOCKET;
1023 case PF_KEY:
1024 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001025 case PF_APPLETALK:
1026 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 }
1028
1029 return SECCLASS_SOCKET;
1030}
1031
1032#ifdef CONFIG_PROC_FS
1033static int selinux_proc_get_sid(struct proc_dir_entry *de,
1034 u16 tclass,
1035 u32 *sid)
1036{
1037 int buflen, rc;
1038 char *buffer, *path, *end;
1039
1040 buffer = (char*)__get_free_page(GFP_KERNEL);
1041 if (!buffer)
1042 return -ENOMEM;
1043
1044 buflen = PAGE_SIZE;
1045 end = buffer+buflen;
1046 *--end = '\0';
1047 buflen--;
1048 path = end-1;
1049 *path = '/';
1050 while (de && de != de->parent) {
1051 buflen -= de->namelen + 1;
1052 if (buflen < 0)
1053 break;
1054 end -= de->namelen;
1055 memcpy(end, de->name, de->namelen);
1056 *--end = '/';
1057 path = end;
1058 de = de->parent;
1059 }
1060 rc = security_genfs_sid("proc", path, tclass, sid);
1061 free_page((unsigned long)buffer);
1062 return rc;
1063}
1064#else
1065static int selinux_proc_get_sid(struct proc_dir_entry *de,
1066 u16 tclass,
1067 u32 *sid)
1068{
1069 return -EINVAL;
1070}
1071#endif
1072
1073/* The inode's security attributes must be initialized before first use. */
1074static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1075{
1076 struct superblock_security_struct *sbsec = NULL;
1077 struct inode_security_struct *isec = inode->i_security;
1078 u32 sid;
1079 struct dentry *dentry;
1080#define INITCONTEXTLEN 255
1081 char *context = NULL;
1082 unsigned len = 0;
1083 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
1085 if (isec->initialized)
1086 goto out;
1087
Eric Paris23970742006-09-25 23:32:01 -07001088 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001090 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 sbsec = inode->i_sb->s_security;
1093 if (!sbsec->initialized) {
1094 /* Defer initialization until selinux_complete_init,
1095 after the initial policy is loaded and the security
1096 server is ready to handle calls. */
1097 spin_lock(&sbsec->isec_lock);
1098 if (list_empty(&isec->list))
1099 list_add(&isec->list, &sbsec->isec_head);
1100 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001101 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 }
1103
1104 switch (sbsec->behavior) {
1105 case SECURITY_FS_USE_XATTR:
1106 if (!inode->i_op->getxattr) {
1107 isec->sid = sbsec->def_sid;
1108 break;
1109 }
1110
1111 /* Need a dentry, since the xattr API requires one.
1112 Life would be simpler if we could just pass the inode. */
1113 if (opt_dentry) {
1114 /* Called from d_instantiate or d_splice_alias. */
1115 dentry = dget(opt_dentry);
1116 } else {
1117 /* Called from selinux_complete_init, try to find a dentry. */
1118 dentry = d_find_alias(inode);
1119 }
1120 if (!dentry) {
1121 printk(KERN_WARNING "%s: no dentry for dev=%s "
1122 "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
1123 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001124 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
1126
1127 len = INITCONTEXTLEN;
1128 context = kmalloc(len, GFP_KERNEL);
1129 if (!context) {
1130 rc = -ENOMEM;
1131 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001132 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 }
1134 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1135 context, len);
1136 if (rc == -ERANGE) {
1137 /* Need a larger buffer. Query for the right size. */
1138 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1139 NULL, 0);
1140 if (rc < 0) {
1141 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001142 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 }
1144 kfree(context);
1145 len = rc;
1146 context = kmalloc(len, GFP_KERNEL);
1147 if (!context) {
1148 rc = -ENOMEM;
1149 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001150 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
1152 rc = inode->i_op->getxattr(dentry,
1153 XATTR_NAME_SELINUX,
1154 context, len);
1155 }
1156 dput(dentry);
1157 if (rc < 0) {
1158 if (rc != -ENODATA) {
1159 printk(KERN_WARNING "%s: getxattr returned "
1160 "%d for dev=%s ino=%ld\n", __FUNCTION__,
1161 -rc, inode->i_sb->s_id, inode->i_ino);
1162 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001163 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
1165 /* Map ENODATA to the default file SID */
1166 sid = sbsec->def_sid;
1167 rc = 0;
1168 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001169 rc = security_context_to_sid_default(context, rc, &sid,
1170 sbsec->def_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if (rc) {
1172 printk(KERN_WARNING "%s: context_to_sid(%s) "
1173 "returned %d for dev=%s ino=%ld\n",
1174 __FUNCTION__, context, -rc,
1175 inode->i_sb->s_id, inode->i_ino);
1176 kfree(context);
1177 /* Leave with the unlabeled SID */
1178 rc = 0;
1179 break;
1180 }
1181 }
1182 kfree(context);
1183 isec->sid = sid;
1184 break;
1185 case SECURITY_FS_USE_TASK:
1186 isec->sid = isec->task_sid;
1187 break;
1188 case SECURITY_FS_USE_TRANS:
1189 /* Default to the fs SID. */
1190 isec->sid = sbsec->sid;
1191
1192 /* Try to obtain a transition SID. */
1193 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1194 rc = security_transition_sid(isec->task_sid,
1195 sbsec->sid,
1196 isec->sclass,
1197 &sid);
1198 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001199 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 isec->sid = sid;
1201 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001202 case SECURITY_FS_USE_MNTPOINT:
1203 isec->sid = sbsec->mntpoint_sid;
1204 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001206 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 isec->sid = sbsec->sid;
1208
1209 if (sbsec->proc) {
1210 struct proc_inode *proci = PROC_I(inode);
1211 if (proci->pde) {
1212 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1213 rc = selinux_proc_get_sid(proci->pde,
1214 isec->sclass,
1215 &sid);
1216 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001217 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 isec->sid = sid;
1219 }
1220 }
1221 break;
1222 }
1223
1224 isec->initialized = 1;
1225
Eric Paris23970742006-09-25 23:32:01 -07001226out_unlock:
1227 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228out:
1229 if (isec->sclass == SECCLASS_FILE)
1230 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 return rc;
1232}
1233
1234/* Convert a Linux signal to an access vector. */
1235static inline u32 signal_to_av(int sig)
1236{
1237 u32 perm = 0;
1238
1239 switch (sig) {
1240 case SIGCHLD:
1241 /* Commonly granted from child to parent. */
1242 perm = PROCESS__SIGCHLD;
1243 break;
1244 case SIGKILL:
1245 /* Cannot be caught or ignored */
1246 perm = PROCESS__SIGKILL;
1247 break;
1248 case SIGSTOP:
1249 /* Cannot be caught or ignored */
1250 perm = PROCESS__SIGSTOP;
1251 break;
1252 default:
1253 /* All other signals. */
1254 perm = PROCESS__SIGNAL;
1255 break;
1256 }
1257
1258 return perm;
1259}
1260
1261/* Check permission betweeen a pair of tasks, e.g. signal checks,
1262 fork check, ptrace check, etc. */
1263static int task_has_perm(struct task_struct *tsk1,
1264 struct task_struct *tsk2,
1265 u32 perms)
1266{
1267 struct task_security_struct *tsec1, *tsec2;
1268
1269 tsec1 = tsk1->security;
1270 tsec2 = tsk2->security;
1271 return avc_has_perm(tsec1->sid, tsec2->sid,
1272 SECCLASS_PROCESS, perms, NULL);
1273}
1274
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001275#if CAP_LAST_CAP > 63
1276#error Fix SELinux to handle capabilities > 63.
1277#endif
1278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279/* Check whether a task is allowed to use a capability. */
1280static int task_has_capability(struct task_struct *tsk,
1281 int cap)
1282{
1283 struct task_security_struct *tsec;
1284 struct avc_audit_data ad;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001285 u16 sclass;
1286 u32 av = CAP_TO_MASK(cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
1288 tsec = tsk->security;
1289
1290 AVC_AUDIT_DATA_INIT(&ad,CAP);
1291 ad.tsk = tsk;
1292 ad.u.cap = cap;
1293
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001294 switch (CAP_TO_INDEX(cap)) {
1295 case 0:
1296 sclass = SECCLASS_CAPABILITY;
1297 break;
1298 case 1:
1299 sclass = SECCLASS_CAPABILITY2;
1300 break;
1301 default:
1302 printk(KERN_ERR
1303 "SELinux: out of range capability %d\n", cap);
1304 BUG();
1305 }
1306 return avc_has_perm(tsec->sid, tsec->sid, sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307}
1308
1309/* Check whether a task is allowed to use a system operation. */
1310static int task_has_system(struct task_struct *tsk,
1311 u32 perms)
1312{
1313 struct task_security_struct *tsec;
1314
1315 tsec = tsk->security;
1316
1317 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1318 SECCLASS_SYSTEM, perms, NULL);
1319}
1320
1321/* Check whether a task has a particular permission to an inode.
1322 The 'adp' parameter is optional and allows other audit
1323 data to be passed (e.g. the dentry). */
1324static int inode_has_perm(struct task_struct *tsk,
1325 struct inode *inode,
1326 u32 perms,
1327 struct avc_audit_data *adp)
1328{
1329 struct task_security_struct *tsec;
1330 struct inode_security_struct *isec;
1331 struct avc_audit_data ad;
1332
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001333 if (unlikely (IS_PRIVATE (inode)))
1334 return 0;
1335
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 tsec = tsk->security;
1337 isec = inode->i_security;
1338
1339 if (!adp) {
1340 adp = &ad;
1341 AVC_AUDIT_DATA_INIT(&ad, FS);
1342 ad.u.fs.inode = inode;
1343 }
1344
1345 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1346}
1347
1348/* Same as inode_has_perm, but pass explicit audit data containing
1349 the dentry to help the auditing code to more easily generate the
1350 pathname if needed. */
1351static inline int dentry_has_perm(struct task_struct *tsk,
1352 struct vfsmount *mnt,
1353 struct dentry *dentry,
1354 u32 av)
1355{
1356 struct inode *inode = dentry->d_inode;
1357 struct avc_audit_data ad;
1358 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001359 ad.u.fs.path.mnt = mnt;
1360 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 return inode_has_perm(tsk, inode, av, &ad);
1362}
1363
1364/* Check whether a task can use an open file descriptor to
1365 access an inode in a given way. Check access to the
1366 descriptor itself, and then use dentry_has_perm to
1367 check a particular permission to the file.
1368 Access to the descriptor is implicitly granted if it
1369 has the same SID as the process. If av is zero, then
1370 access to the file is not checked, e.g. for cases
1371 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001372static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 struct file *file,
1374 u32 av)
1375{
1376 struct task_security_struct *tsec = tsk->security;
1377 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001378 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 struct avc_audit_data ad;
1380 int rc;
1381
1382 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001383 ad.u.fs.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385 if (tsec->sid != fsec->sid) {
1386 rc = avc_has_perm(tsec->sid, fsec->sid,
1387 SECCLASS_FD,
1388 FD__USE,
1389 &ad);
1390 if (rc)
1391 return rc;
1392 }
1393
1394 /* av is zero if only checking access to the descriptor. */
1395 if (av)
1396 return inode_has_perm(tsk, inode, av, &ad);
1397
1398 return 0;
1399}
1400
1401/* Check whether a task can create a file. */
1402static int may_create(struct inode *dir,
1403 struct dentry *dentry,
1404 u16 tclass)
1405{
1406 struct task_security_struct *tsec;
1407 struct inode_security_struct *dsec;
1408 struct superblock_security_struct *sbsec;
1409 u32 newsid;
1410 struct avc_audit_data ad;
1411 int rc;
1412
1413 tsec = current->security;
1414 dsec = dir->i_security;
1415 sbsec = dir->i_sb->s_security;
1416
1417 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001418 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1421 DIR__ADD_NAME | DIR__SEARCH,
1422 &ad);
1423 if (rc)
1424 return rc;
1425
1426 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1427 newsid = tsec->create_sid;
1428 } else {
1429 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1430 &newsid);
1431 if (rc)
1432 return rc;
1433 }
1434
1435 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1436 if (rc)
1437 return rc;
1438
1439 return avc_has_perm(newsid, sbsec->sid,
1440 SECCLASS_FILESYSTEM,
1441 FILESYSTEM__ASSOCIATE, &ad);
1442}
1443
Michael LeMay4eb582c2006-06-26 00:24:57 -07001444/* Check whether a task can create a key. */
1445static int may_create_key(u32 ksid,
1446 struct task_struct *ctx)
1447{
1448 struct task_security_struct *tsec;
1449
1450 tsec = ctx->security;
1451
1452 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1453}
1454
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455#define MAY_LINK 0
1456#define MAY_UNLINK 1
1457#define MAY_RMDIR 2
1458
1459/* Check whether a task can link, unlink, or rmdir a file/directory. */
1460static int may_link(struct inode *dir,
1461 struct dentry *dentry,
1462 int kind)
1463
1464{
1465 struct task_security_struct *tsec;
1466 struct inode_security_struct *dsec, *isec;
1467 struct avc_audit_data ad;
1468 u32 av;
1469 int rc;
1470
1471 tsec = current->security;
1472 dsec = dir->i_security;
1473 isec = dentry->d_inode->i_security;
1474
1475 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001476 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
1478 av = DIR__SEARCH;
1479 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1480 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1481 if (rc)
1482 return rc;
1483
1484 switch (kind) {
1485 case MAY_LINK:
1486 av = FILE__LINK;
1487 break;
1488 case MAY_UNLINK:
1489 av = FILE__UNLINK;
1490 break;
1491 case MAY_RMDIR:
1492 av = DIR__RMDIR;
1493 break;
1494 default:
1495 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1496 return 0;
1497 }
1498
1499 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1500 return rc;
1501}
1502
1503static inline int may_rename(struct inode *old_dir,
1504 struct dentry *old_dentry,
1505 struct inode *new_dir,
1506 struct dentry *new_dentry)
1507{
1508 struct task_security_struct *tsec;
1509 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1510 struct avc_audit_data ad;
1511 u32 av;
1512 int old_is_dir, new_is_dir;
1513 int rc;
1514
1515 tsec = current->security;
1516 old_dsec = old_dir->i_security;
1517 old_isec = old_dentry->d_inode->i_security;
1518 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1519 new_dsec = new_dir->i_security;
1520
1521 AVC_AUDIT_DATA_INIT(&ad, FS);
1522
Jan Blunck44707fd2008-02-14 19:38:33 -08001523 ad.u.fs.path.dentry = old_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1525 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1526 if (rc)
1527 return rc;
1528 rc = avc_has_perm(tsec->sid, old_isec->sid,
1529 old_isec->sclass, FILE__RENAME, &ad);
1530 if (rc)
1531 return rc;
1532 if (old_is_dir && new_dir != old_dir) {
1533 rc = avc_has_perm(tsec->sid, old_isec->sid,
1534 old_isec->sclass, DIR__REPARENT, &ad);
1535 if (rc)
1536 return rc;
1537 }
1538
Jan Blunck44707fd2008-02-14 19:38:33 -08001539 ad.u.fs.path.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 av = DIR__ADD_NAME | DIR__SEARCH;
1541 if (new_dentry->d_inode)
1542 av |= DIR__REMOVE_NAME;
1543 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1544 if (rc)
1545 return rc;
1546 if (new_dentry->d_inode) {
1547 new_isec = new_dentry->d_inode->i_security;
1548 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1549 rc = avc_has_perm(tsec->sid, new_isec->sid,
1550 new_isec->sclass,
1551 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1552 if (rc)
1553 return rc;
1554 }
1555
1556 return 0;
1557}
1558
1559/* Check whether a task can perform a filesystem operation. */
1560static int superblock_has_perm(struct task_struct *tsk,
1561 struct super_block *sb,
1562 u32 perms,
1563 struct avc_audit_data *ad)
1564{
1565 struct task_security_struct *tsec;
1566 struct superblock_security_struct *sbsec;
1567
1568 tsec = tsk->security;
1569 sbsec = sb->s_security;
1570 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1571 perms, ad);
1572}
1573
1574/* Convert a Linux mode and permission mask to an access vector. */
1575static inline u32 file_mask_to_av(int mode, int mask)
1576{
1577 u32 av = 0;
1578
1579 if ((mode & S_IFMT) != S_IFDIR) {
1580 if (mask & MAY_EXEC)
1581 av |= FILE__EXECUTE;
1582 if (mask & MAY_READ)
1583 av |= FILE__READ;
1584
1585 if (mask & MAY_APPEND)
1586 av |= FILE__APPEND;
1587 else if (mask & MAY_WRITE)
1588 av |= FILE__WRITE;
1589
1590 } else {
1591 if (mask & MAY_EXEC)
1592 av |= DIR__SEARCH;
1593 if (mask & MAY_WRITE)
1594 av |= DIR__WRITE;
1595 if (mask & MAY_READ)
1596 av |= DIR__READ;
1597 }
1598
1599 return av;
1600}
1601
1602/* Convert a Linux file to an access vector. */
1603static inline u32 file_to_av(struct file *file)
1604{
1605 u32 av = 0;
1606
1607 if (file->f_mode & FMODE_READ)
1608 av |= FILE__READ;
1609 if (file->f_mode & FMODE_WRITE) {
1610 if (file->f_flags & O_APPEND)
1611 av |= FILE__APPEND;
1612 else
1613 av |= FILE__WRITE;
1614 }
1615
1616 return av;
1617}
1618
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619/* Hook functions begin here. */
1620
1621static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1622{
1623 struct task_security_struct *psec = parent->security;
1624 struct task_security_struct *csec = child->security;
1625 int rc;
1626
1627 rc = secondary_ops->ptrace(parent,child);
1628 if (rc)
1629 return rc;
1630
1631 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1632 /* Save the SID of the tracing process for later use in apply_creds. */
Stephen Smalley341c2d82006-03-11 03:27:16 -08001633 if (!(child->ptrace & PT_PTRACED) && !rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 csec->ptrace_sid = psec->sid;
1635 return rc;
1636}
1637
1638static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1639 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1640{
1641 int error;
1642
1643 error = task_has_perm(current, target, PROCESS__GETCAP);
1644 if (error)
1645 return error;
1646
1647 return secondary_ops->capget(target, effective, inheritable, permitted);
1648}
1649
1650static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1651 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1652{
1653 int error;
1654
1655 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1656 if (error)
1657 return error;
1658
1659 return task_has_perm(current, target, PROCESS__SETCAP);
1660}
1661
1662static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1663 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1664{
1665 secondary_ops->capset_set(target, effective, inheritable, permitted);
1666}
1667
1668static int selinux_capable(struct task_struct *tsk, int cap)
1669{
1670 int rc;
1671
1672 rc = secondary_ops->capable(tsk, cap);
1673 if (rc)
1674 return rc;
1675
1676 return task_has_capability(tsk,cap);
1677}
1678
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001679static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1680{
1681 int buflen, rc;
1682 char *buffer, *path, *end;
1683
1684 rc = -ENOMEM;
1685 buffer = (char*)__get_free_page(GFP_KERNEL);
1686 if (!buffer)
1687 goto out;
1688
1689 buflen = PAGE_SIZE;
1690 end = buffer+buflen;
1691 *--end = '\0';
1692 buflen--;
1693 path = end-1;
1694 *path = '/';
1695 while (table) {
1696 const char *name = table->procname;
1697 size_t namelen = strlen(name);
1698 buflen -= namelen + 1;
1699 if (buflen < 0)
1700 goto out_free;
1701 end -= namelen;
1702 memcpy(end, name, namelen);
1703 *--end = '/';
1704 path = end;
1705 table = table->parent;
1706 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001707 buflen -= 4;
1708 if (buflen < 0)
1709 goto out_free;
1710 end -= 4;
1711 memcpy(end, "/sys", 4);
1712 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001713 rc = security_genfs_sid("proc", path, tclass, sid);
1714out_free:
1715 free_page((unsigned long)buffer);
1716out:
1717 return rc;
1718}
1719
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720static int selinux_sysctl(ctl_table *table, int op)
1721{
1722 int error = 0;
1723 u32 av;
1724 struct task_security_struct *tsec;
1725 u32 tsid;
1726 int rc;
1727
1728 rc = secondary_ops->sysctl(table, op);
1729 if (rc)
1730 return rc;
1731
1732 tsec = current->security;
1733
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001734 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1735 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 if (rc) {
1737 /* Default to the well-defined sysctl SID. */
1738 tsid = SECINITSID_SYSCTL;
1739 }
1740
1741 /* The op values are "defined" in sysctl.c, thereby creating
1742 * a bad coupling between this module and sysctl.c */
1743 if(op == 001) {
1744 error = avc_has_perm(tsec->sid, tsid,
1745 SECCLASS_DIR, DIR__SEARCH, NULL);
1746 } else {
1747 av = 0;
1748 if (op & 004)
1749 av |= FILE__READ;
1750 if (op & 002)
1751 av |= FILE__WRITE;
1752 if (av)
1753 error = avc_has_perm(tsec->sid, tsid,
1754 SECCLASS_FILE, av, NULL);
1755 }
1756
1757 return error;
1758}
1759
1760static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1761{
1762 int rc = 0;
1763
1764 if (!sb)
1765 return 0;
1766
1767 switch (cmds) {
1768 case Q_SYNC:
1769 case Q_QUOTAON:
1770 case Q_QUOTAOFF:
1771 case Q_SETINFO:
1772 case Q_SETQUOTA:
1773 rc = superblock_has_perm(current,
1774 sb,
1775 FILESYSTEM__QUOTAMOD, NULL);
1776 break;
1777 case Q_GETFMT:
1778 case Q_GETINFO:
1779 case Q_GETQUOTA:
1780 rc = superblock_has_perm(current,
1781 sb,
1782 FILESYSTEM__QUOTAGET, NULL);
1783 break;
1784 default:
1785 rc = 0; /* let the kernel handle invalid cmds */
1786 break;
1787 }
1788 return rc;
1789}
1790
1791static int selinux_quota_on(struct dentry *dentry)
1792{
1793 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1794}
1795
1796static int selinux_syslog(int type)
1797{
1798 int rc;
1799
1800 rc = secondary_ops->syslog(type);
1801 if (rc)
1802 return rc;
1803
1804 switch (type) {
1805 case 3: /* Read last kernel messages */
1806 case 10: /* Return size of the log buffer */
1807 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1808 break;
1809 case 6: /* Disable logging to console */
1810 case 7: /* Enable logging to console */
1811 case 8: /* Set level of messages printed to console */
1812 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1813 break;
1814 case 0: /* Close log */
1815 case 1: /* Open log */
1816 case 2: /* Read from log */
1817 case 4: /* Read/clear last kernel messages */
1818 case 5: /* Clear ring buffer */
1819 default:
1820 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1821 break;
1822 }
1823 return rc;
1824}
1825
1826/*
1827 * Check that a process has enough memory to allocate a new virtual
1828 * mapping. 0 means there is enough memory for the allocation to
1829 * succeed and -ENOMEM implies there is not.
1830 *
1831 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1832 * if the capability is granted, but __vm_enough_memory requires 1 if
1833 * the capability is granted.
1834 *
1835 * Do not audit the selinux permission check, as this is applied to all
1836 * processes that allocate mappings.
1837 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001838static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839{
1840 int rc, cap_sys_admin = 0;
1841 struct task_security_struct *tsec = current->security;
1842
1843 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1844 if (rc == 0)
1845 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001846 SECCLASS_CAPABILITY,
1847 CAP_TO_MASK(CAP_SYS_ADMIN),
1848 0,
1849 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
1851 if (rc == 0)
1852 cap_sys_admin = 1;
1853
Alan Cox34b4e4a2007-08-22 14:01:28 -07001854 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855}
1856
1857/* binprm security operations */
1858
1859static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1860{
1861 struct bprm_security_struct *bsec;
1862
James Morris89d155e2005-10-30 14:59:21 -08001863 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 if (!bsec)
1865 return -ENOMEM;
1866
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 bsec->bprm = bprm;
1868 bsec->sid = SECINITSID_UNLABELED;
1869 bsec->set = 0;
1870
1871 bprm->security = bsec;
1872 return 0;
1873}
1874
1875static int selinux_bprm_set_security(struct linux_binprm *bprm)
1876{
1877 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001878 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 struct inode_security_struct *isec;
1880 struct bprm_security_struct *bsec;
1881 u32 newsid;
1882 struct avc_audit_data ad;
1883 int rc;
1884
1885 rc = secondary_ops->bprm_set_security(bprm);
1886 if (rc)
1887 return rc;
1888
1889 bsec = bprm->security;
1890
1891 if (bsec->set)
1892 return 0;
1893
1894 tsec = current->security;
1895 isec = inode->i_security;
1896
1897 /* Default to the current task SID. */
1898 bsec->sid = tsec->sid;
1899
Michael LeMay28eba5b2006-06-27 02:53:42 -07001900 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001902 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001903 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
1905 if (tsec->exec_sid) {
1906 newsid = tsec->exec_sid;
1907 /* Reset exec SID on execve. */
1908 tsec->exec_sid = 0;
1909 } else {
1910 /* Check for a default transition on this program. */
1911 rc = security_transition_sid(tsec->sid, isec->sid,
1912 SECCLASS_PROCESS, &newsid);
1913 if (rc)
1914 return rc;
1915 }
1916
1917 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001918 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Josef Sipek3d5ff522006-12-08 02:37:38 -08001920 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 newsid = tsec->sid;
1922
1923 if (tsec->sid == newsid) {
1924 rc = avc_has_perm(tsec->sid, isec->sid,
1925 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1926 if (rc)
1927 return rc;
1928 } else {
1929 /* Check permissions for the transition. */
1930 rc = avc_has_perm(tsec->sid, newsid,
1931 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1932 if (rc)
1933 return rc;
1934
1935 rc = avc_has_perm(newsid, isec->sid,
1936 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1937 if (rc)
1938 return rc;
1939
1940 /* Clear any possibly unsafe personality bits on exec: */
1941 current->personality &= ~PER_CLEAR_ON_SETID;
1942
1943 /* Set the security field to the new SID. */
1944 bsec->sid = newsid;
1945 }
1946
1947 bsec->set = 1;
1948 return 0;
1949}
1950
1951static int selinux_bprm_check_security (struct linux_binprm *bprm)
1952{
1953 return secondary_ops->bprm_check_security(bprm);
1954}
1955
1956
1957static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1958{
1959 struct task_security_struct *tsec = current->security;
1960 int atsecure = 0;
1961
1962 if (tsec->osid != tsec->sid) {
1963 /* Enable secure mode for SIDs transitions unless
1964 the noatsecure permission is granted between
1965 the two SIDs, i.e. ahp returns 0. */
1966 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1967 SECCLASS_PROCESS,
1968 PROCESS__NOATSECURE, NULL);
1969 }
1970
1971 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1972}
1973
1974static void selinux_bprm_free_security(struct linux_binprm *bprm)
1975{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07001976 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978}
1979
1980extern struct vfsmount *selinuxfs_mount;
1981extern struct dentry *selinux_null;
1982
1983/* Derived from fs/exec.c:flush_old_files. */
1984static inline void flush_unauthorized_files(struct files_struct * files)
1985{
1986 struct avc_audit_data ad;
1987 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001988 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07001989 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001991 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001993 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001994 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 if (tty) {
1996 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08001997 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 if (file) {
1999 /* Revalidate access to controlling tty.
2000 Use inode_has_perm on the tty inode directly rather
2001 than using file_has_perm, as this particular open
2002 file may belong to another process and we are only
2003 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002004 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 if (inode_has_perm(current, inode,
2006 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002007 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 }
2009 }
2010 file_list_unlock();
2011 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002012 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002013 /* Reset controlling tty. */
2014 if (drop_tty)
2015 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
2017 /* Revalidate access to inherited open files. */
2018
2019 AVC_AUDIT_DATA_INIT(&ad,FS);
2020
2021 spin_lock(&files->file_lock);
2022 for (;;) {
2023 unsigned long set, i;
2024 int fd;
2025
2026 j++;
2027 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002028 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002029 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002031 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 if (!set)
2033 continue;
2034 spin_unlock(&files->file_lock);
2035 for ( ; set ; i++,set >>= 1) {
2036 if (set & 1) {
2037 file = fget(i);
2038 if (!file)
2039 continue;
2040 if (file_has_perm(current,
2041 file,
2042 file_to_av(file))) {
2043 sys_close(i);
2044 fd = get_unused_fd();
2045 if (fd != i) {
2046 if (fd >= 0)
2047 put_unused_fd(fd);
2048 fput(file);
2049 continue;
2050 }
2051 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002052 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 } else {
2054 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002055 if (IS_ERR(devnull)) {
2056 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 put_unused_fd(fd);
2058 fput(file);
2059 continue;
2060 }
2061 }
2062 fd_install(fd, devnull);
2063 }
2064 fput(file);
2065 }
2066 }
2067 spin_lock(&files->file_lock);
2068
2069 }
2070 spin_unlock(&files->file_lock);
2071}
2072
2073static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2074{
2075 struct task_security_struct *tsec;
2076 struct bprm_security_struct *bsec;
2077 u32 sid;
2078 int rc;
2079
2080 secondary_ops->bprm_apply_creds(bprm, unsafe);
2081
2082 tsec = current->security;
2083
2084 bsec = bprm->security;
2085 sid = bsec->sid;
2086
2087 tsec->osid = tsec->sid;
2088 bsec->unsafe = 0;
2089 if (tsec->sid != sid) {
2090 /* Check for shared state. If not ok, leave SID
2091 unchanged and kill. */
2092 if (unsafe & LSM_UNSAFE_SHARE) {
2093 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2094 PROCESS__SHARE, NULL);
2095 if (rc) {
2096 bsec->unsafe = 1;
2097 return;
2098 }
2099 }
2100
2101 /* Check for ptracing, and update the task SID if ok.
2102 Otherwise, leave SID unchanged and kill. */
2103 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2104 rc = avc_has_perm(tsec->ptrace_sid, sid,
2105 SECCLASS_PROCESS, PROCESS__PTRACE,
2106 NULL);
2107 if (rc) {
2108 bsec->unsafe = 1;
2109 return;
2110 }
2111 }
2112 tsec->sid = sid;
2113 }
2114}
2115
2116/*
2117 * called after apply_creds without the task lock held
2118 */
2119static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2120{
2121 struct task_security_struct *tsec;
2122 struct rlimit *rlim, *initrlim;
2123 struct itimerval itimer;
2124 struct bprm_security_struct *bsec;
2125 int rc, i;
2126
2127 tsec = current->security;
2128 bsec = bprm->security;
2129
2130 if (bsec->unsafe) {
2131 force_sig_specific(SIGKILL, current);
2132 return;
2133 }
2134 if (tsec->osid == tsec->sid)
2135 return;
2136
2137 /* Close files for which the new task SID is not authorized. */
2138 flush_unauthorized_files(current->files);
2139
2140 /* Check whether the new SID can inherit signal state
2141 from the old SID. If not, clear itimers to avoid
2142 subsequent signal generation and flush and unblock
2143 signals. This must occur _after_ the task SID has
2144 been updated so that any kill done after the flush
2145 will be checked against the new SID. */
2146 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2147 PROCESS__SIGINH, NULL);
2148 if (rc) {
2149 memset(&itimer, 0, sizeof itimer);
2150 for (i = 0; i < 3; i++)
2151 do_setitimer(i, &itimer, NULL);
2152 flush_signals(current);
2153 spin_lock_irq(&current->sighand->siglock);
2154 flush_signal_handlers(current, 1);
2155 sigemptyset(&current->blocked);
2156 recalc_sigpending();
2157 spin_unlock_irq(&current->sighand->siglock);
2158 }
2159
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002160 /* Always clear parent death signal on SID transitions. */
2161 current->pdeath_signal = 0;
2162
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 /* Check whether the new SID can inherit resource limits
2164 from the old SID. If not, reset all soft limits to
2165 the lower of the current task's hard limit and the init
2166 task's soft limit. Note that the setting of hard limits
2167 (even to lower them) can be controlled by the setrlimit
2168 check. The inclusion of the init task's soft limit into
2169 the computation is to avoid resetting soft limits higher
2170 than the default soft limit for cases where the default
2171 is lower than the hard limit, e.g. RLIMIT_CORE or
2172 RLIMIT_STACK.*/
2173 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2174 PROCESS__RLIMITINH, NULL);
2175 if (rc) {
2176 for (i = 0; i < RLIM_NLIMITS; i++) {
2177 rlim = current->signal->rlim + i;
2178 initrlim = init_task.signal->rlim+i;
2179 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
2180 }
2181 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2182 /*
2183 * This will cause RLIMIT_CPU calculations
2184 * to be refigured.
2185 */
2186 current->it_prof_expires = jiffies_to_cputime(1);
2187 }
2188 }
2189
2190 /* Wake up the parent if it is waiting so that it can
2191 recheck wait permission to the new task SID. */
2192 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2193}
2194
2195/* superblock security operations */
2196
2197static int selinux_sb_alloc_security(struct super_block *sb)
2198{
2199 return superblock_alloc_security(sb);
2200}
2201
2202static void selinux_sb_free_security(struct super_block *sb)
2203{
2204 superblock_free_security(sb);
2205}
2206
2207static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2208{
2209 if (plen > olen)
2210 return 0;
2211
2212 return !memcmp(prefix, option, plen);
2213}
2214
2215static inline int selinux_option(char *option, int len)
2216{
2217 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
2218 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
Eric Paris08089252006-07-10 04:43:55 -07002219 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
2220 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221}
2222
2223static inline void take_option(char **to, char *from, int *first, int len)
2224{
2225 if (!*first) {
2226 **to = ',';
2227 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002228 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 *first = 0;
2230 memcpy(*to, from, len);
2231 *to += len;
2232}
2233
Cory Olmo3528a952006-09-29 01:58:44 -07002234static inline void take_selinux_option(char **to, char *from, int *first,
2235 int len)
2236{
2237 int current_size = 0;
2238
2239 if (!*first) {
2240 **to = '|';
2241 *to += 1;
2242 }
2243 else
2244 *first = 0;
2245
2246 while (current_size < len) {
2247 if (*from != '"') {
2248 **to = *from;
2249 *to += 1;
2250 }
2251 from += 1;
2252 current_size += 1;
2253 }
2254}
2255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
2257{
2258 int fnosec, fsec, rc = 0;
2259 char *in_save, *in_curr, *in_end;
2260 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002261 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 in_curr = orig;
2264 sec_curr = copy;
2265
2266 /* Binary mount data: just copy */
2267 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2268 copy_page(sec_curr, in_curr);
2269 goto out;
2270 }
2271
2272 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2273 if (!nosec) {
2274 rc = -ENOMEM;
2275 goto out;
2276 }
2277
2278 nosec_save = nosec;
2279 fnosec = fsec = 1;
2280 in_save = in_end = orig;
2281
2282 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002283 if (*in_end == '"')
2284 open_quote = !open_quote;
2285 if ((*in_end == ',' && open_quote == 0) ||
2286 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 int len = in_end - in_curr;
2288
2289 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002290 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 else
2292 take_option(&nosec, in_curr, &fnosec, len);
2293
2294 in_curr = in_end + 1;
2295 }
2296 } while (*in_end++);
2297
Eric Paris6931dfc2005-06-30 02:58:51 -07002298 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002299 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300out:
2301 return rc;
2302}
2303
2304static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2305{
2306 struct avc_audit_data ad;
2307 int rc;
2308
2309 rc = superblock_doinit(sb, data);
2310 if (rc)
2311 return rc;
2312
2313 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002314 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2316}
2317
David Howells726c3342006-06-23 02:02:58 -07002318static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319{
2320 struct avc_audit_data ad;
2321
2322 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002323 ad.u.fs.path.dentry = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002324 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325}
2326
2327static int selinux_mount(char * dev_name,
2328 struct nameidata *nd,
2329 char * type,
2330 unsigned long flags,
2331 void * data)
2332{
2333 int rc;
2334
2335 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2336 if (rc)
2337 return rc;
2338
2339 if (flags & MS_REMOUNT)
Jan Blunck4ac91372008-02-14 19:34:32 -08002340 return superblock_has_perm(current, nd->path.mnt->mnt_sb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 FILESYSTEM__REMOUNT, NULL);
2342 else
Jan Blunck4ac91372008-02-14 19:34:32 -08002343 return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 FILE__MOUNTON);
2345}
2346
2347static int selinux_umount(struct vfsmount *mnt, int flags)
2348{
2349 int rc;
2350
2351 rc = secondary_ops->sb_umount(mnt, flags);
2352 if (rc)
2353 return rc;
2354
2355 return superblock_has_perm(current,mnt->mnt_sb,
2356 FILESYSTEM__UNMOUNT,NULL);
2357}
2358
2359/* inode security operations */
2360
2361static int selinux_inode_alloc_security(struct inode *inode)
2362{
2363 return inode_alloc_security(inode);
2364}
2365
2366static void selinux_inode_free_security(struct inode *inode)
2367{
2368 inode_free_security(inode);
2369}
2370
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002371static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2372 char **name, void **value,
2373 size_t *len)
2374{
2375 struct task_security_struct *tsec;
2376 struct inode_security_struct *dsec;
2377 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002378 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002379 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002380 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002381
2382 tsec = current->security;
2383 dsec = dir->i_security;
2384 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002385
2386 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2387 newsid = tsec->create_sid;
2388 } else {
2389 rc = security_transition_sid(tsec->sid, dsec->sid,
2390 inode_mode_to_security_class(inode->i_mode),
2391 &newsid);
2392 if (rc) {
2393 printk(KERN_WARNING "%s: "
2394 "security_transition_sid failed, rc=%d (dev=%s "
2395 "ino=%ld)\n",
2396 __FUNCTION__,
2397 -rc, inode->i_sb->s_id, inode->i_ino);
2398 return rc;
2399 }
2400 }
2401
Eric Paris296fddf2006-09-25 23:32:00 -07002402 /* Possibly defer initialization to selinux_complete_init. */
2403 if (sbsec->initialized) {
2404 struct inode_security_struct *isec = inode->i_security;
2405 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2406 isec->sid = newsid;
2407 isec->initialized = 1;
2408 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002409
Stephen Smalley8aad3872006-03-22 00:09:13 -08002410 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002411 return -EOPNOTSUPP;
2412
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002413 if (name) {
2414 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
2415 if (!namep)
2416 return -ENOMEM;
2417 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002418 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002419
2420 if (value && len) {
2421 rc = security_sid_to_context(newsid, &context, &clen);
2422 if (rc) {
2423 kfree(namep);
2424 return rc;
2425 }
2426 *value = context;
2427 *len = clen;
2428 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002429
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002430 return 0;
2431}
2432
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2434{
2435 return may_create(dir, dentry, SECCLASS_FILE);
2436}
2437
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2439{
2440 int rc;
2441
2442 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2443 if (rc)
2444 return rc;
2445 return may_link(dir, old_dentry, MAY_LINK);
2446}
2447
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2449{
2450 int rc;
2451
2452 rc = secondary_ops->inode_unlink(dir, dentry);
2453 if (rc)
2454 return rc;
2455 return may_link(dir, dentry, MAY_UNLINK);
2456}
2457
2458static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2459{
2460 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2461}
2462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2464{
2465 return may_create(dir, dentry, SECCLASS_DIR);
2466}
2467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2469{
2470 return may_link(dir, dentry, MAY_RMDIR);
2471}
2472
2473static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2474{
2475 int rc;
2476
2477 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2478 if (rc)
2479 return rc;
2480
2481 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2482}
2483
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2485 struct inode *new_inode, struct dentry *new_dentry)
2486{
2487 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2488}
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490static int selinux_inode_readlink(struct dentry *dentry)
2491{
2492 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2493}
2494
2495static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2496{
2497 int rc;
2498
2499 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2500 if (rc)
2501 return rc;
2502 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2503}
2504
2505static int selinux_inode_permission(struct inode *inode, int mask,
2506 struct nameidata *nd)
2507{
2508 int rc;
2509
2510 rc = secondary_ops->inode_permission(inode, mask, nd);
2511 if (rc)
2512 return rc;
2513
2514 if (!mask) {
2515 /* No permission to check. Existence test. */
2516 return 0;
2517 }
2518
2519 return inode_has_perm(current, inode,
2520 file_mask_to_av(inode->i_mode, mask), NULL);
2521}
2522
2523static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2524{
2525 int rc;
2526
2527 rc = secondary_ops->inode_setattr(dentry, iattr);
2528 if (rc)
2529 return rc;
2530
2531 if (iattr->ia_valid & ATTR_FORCE)
2532 return 0;
2533
2534 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2535 ATTR_ATIME_SET | ATTR_MTIME_SET))
2536 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2537
2538 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2539}
2540
2541static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2542{
2543 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2544}
2545
Serge E. Hallynb5376772007-10-16 23:31:36 -07002546static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2547{
2548 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2549 sizeof XATTR_SECURITY_PREFIX - 1)) {
2550 if (!strcmp(name, XATTR_NAME_CAPS)) {
2551 if (!capable(CAP_SETFCAP))
2552 return -EPERM;
2553 } else if (!capable(CAP_SYS_ADMIN)) {
2554 /* A different attribute in the security namespace.
2555 Restrict to administrator. */
2556 return -EPERM;
2557 }
2558 }
2559
2560 /* Not an attribute we recognize, so just check the
2561 ordinary setattr permission. */
2562 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2563}
2564
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2566{
2567 struct task_security_struct *tsec = current->security;
2568 struct inode *inode = dentry->d_inode;
2569 struct inode_security_struct *isec = inode->i_security;
2570 struct superblock_security_struct *sbsec;
2571 struct avc_audit_data ad;
2572 u32 newsid;
2573 int rc = 0;
2574
Serge E. Hallynb5376772007-10-16 23:31:36 -07002575 if (strcmp(name, XATTR_NAME_SELINUX))
2576 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
2578 sbsec = inode->i_sb->s_security;
2579 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2580 return -EOPNOTSUPP;
2581
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302582 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 return -EPERM;
2584
2585 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002586 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
2588 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2589 FILE__RELABELFROM, &ad);
2590 if (rc)
2591 return rc;
2592
2593 rc = security_context_to_sid(value, size, &newsid);
2594 if (rc)
2595 return rc;
2596
2597 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2598 FILE__RELABELTO, &ad);
2599 if (rc)
2600 return rc;
2601
2602 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2603 isec->sclass);
2604 if (rc)
2605 return rc;
2606
2607 return avc_has_perm(newsid,
2608 sbsec->sid,
2609 SECCLASS_FILESYSTEM,
2610 FILESYSTEM__ASSOCIATE,
2611 &ad);
2612}
2613
2614static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2615 void *value, size_t size, int flags)
2616{
2617 struct inode *inode = dentry->d_inode;
2618 struct inode_security_struct *isec = inode->i_security;
2619 u32 newsid;
2620 int rc;
2621
2622 if (strcmp(name, XATTR_NAME_SELINUX)) {
2623 /* Not an attribute we recognize, so nothing to do. */
2624 return;
2625 }
2626
2627 rc = security_context_to_sid(value, size, &newsid);
2628 if (rc) {
2629 printk(KERN_WARNING "%s: unable to obtain SID for context "
2630 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2631 return;
2632 }
2633
2634 isec->sid = newsid;
2635 return;
2636}
2637
2638static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2639{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2641}
2642
2643static int selinux_inode_listxattr (struct dentry *dentry)
2644{
2645 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2646}
2647
2648static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2649{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002650 if (strcmp(name, XATTR_NAME_SELINUX))
2651 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
2653 /* No one is allowed to remove a SELinux security label.
2654 You can change the label, but all data must be labeled. */
2655 return -EACCES;
2656}
2657
James Morrisd381d8a2005-10-30 14:59:22 -08002658/*
2659 * Copy the in-core inode security context value to the user. If the
2660 * getxattr() prior to this succeeded, check to see if we need to
2661 * canonicalize the value to be finally returned to the user.
2662 *
2663 * Permission check is handled by selinux_inode_getxattr hook.
2664 */
David P. Quigley42492592008-02-04 22:29:39 -08002665static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666{
David P. Quigley42492592008-02-04 22:29:39 -08002667 u32 size;
2668 int error;
2669 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002672 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2673 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
David P. Quigley42492592008-02-04 22:29:39 -08002675 error = security_sid_to_context(isec->sid, &context, &size);
2676 if (error)
2677 return error;
2678 error = size;
2679 if (alloc) {
2680 *buffer = context;
2681 goto out_nofree;
2682 }
2683 kfree(context);
2684out_nofree:
2685 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
2688static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2689 const void *value, size_t size, int flags)
2690{
2691 struct inode_security_struct *isec = inode->i_security;
2692 u32 newsid;
2693 int rc;
2694
2695 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2696 return -EOPNOTSUPP;
2697
2698 if (!value || !size)
2699 return -EACCES;
2700
2701 rc = security_context_to_sid((void*)value, size, &newsid);
2702 if (rc)
2703 return rc;
2704
2705 isec->sid = newsid;
2706 return 0;
2707}
2708
2709static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2710{
2711 const int len = sizeof(XATTR_NAME_SELINUX);
2712 if (buffer && len <= buffer_size)
2713 memcpy(buffer, XATTR_NAME_SELINUX, len);
2714 return len;
2715}
2716
Serge E. Hallynb5376772007-10-16 23:31:36 -07002717static int selinux_inode_need_killpriv(struct dentry *dentry)
2718{
2719 return secondary_ops->inode_need_killpriv(dentry);
2720}
2721
2722static int selinux_inode_killpriv(struct dentry *dentry)
2723{
2724 return secondary_ops->inode_killpriv(dentry);
2725}
2726
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727/* file security operations */
2728
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002729static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002731 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002732 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
2734 if (!mask) {
2735 /* No permission to check. Existence test. */
2736 return 0;
2737 }
2738
2739 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2740 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2741 mask |= MAY_APPEND;
2742
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002743 rc = file_has_perm(current, file,
2744 file_mask_to_av(inode->i_mode, mask));
2745 if (rc)
2746 return rc;
2747
2748 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749}
2750
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002751static int selinux_file_permission(struct file *file, int mask)
2752{
2753 struct inode *inode = file->f_path.dentry->d_inode;
2754 struct task_security_struct *tsec = current->security;
2755 struct file_security_struct *fsec = file->f_security;
2756 struct inode_security_struct *isec = inode->i_security;
2757
2758 if (!mask) {
2759 /* No permission to check. Existence test. */
2760 return 0;
2761 }
2762
2763 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2764 && fsec->pseqno == avc_policy_seqno())
2765 return selinux_netlbl_inode_permission(inode, mask);
2766
2767 return selinux_revalidate_file_permission(file, mask);
2768}
2769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770static int selinux_file_alloc_security(struct file *file)
2771{
2772 return file_alloc_security(file);
2773}
2774
2775static void selinux_file_free_security(struct file *file)
2776{
2777 file_free_security(file);
2778}
2779
2780static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2781 unsigned long arg)
2782{
2783 int error = 0;
2784
2785 switch (cmd) {
2786 case FIONREAD:
2787 /* fall through */
2788 case FIBMAP:
2789 /* fall through */
2790 case FIGETBSZ:
2791 /* fall through */
2792 case EXT2_IOC_GETFLAGS:
2793 /* fall through */
2794 case EXT2_IOC_GETVERSION:
2795 error = file_has_perm(current, file, FILE__GETATTR);
2796 break;
2797
2798 case EXT2_IOC_SETFLAGS:
2799 /* fall through */
2800 case EXT2_IOC_SETVERSION:
2801 error = file_has_perm(current, file, FILE__SETATTR);
2802 break;
2803
2804 /* sys_ioctl() checks */
2805 case FIONBIO:
2806 /* fall through */
2807 case FIOASYNC:
2808 error = file_has_perm(current, file, 0);
2809 break;
2810
2811 case KDSKBENT:
2812 case KDSKBSENT:
2813 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2814 break;
2815
2816 /* default case assumes that the command will go
2817 * to the file's ioctl() function.
2818 */
2819 default:
2820 error = file_has_perm(current, file, FILE__IOCTL);
2821
2822 }
2823 return error;
2824}
2825
2826static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2827{
2828#ifndef CONFIG_PPC32
2829 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2830 /*
2831 * We are making executable an anonymous mapping or a
2832 * private file mapping that will also be writable.
2833 * This has an additional check.
2834 */
2835 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2836 if (rc)
2837 return rc;
2838 }
2839#endif
2840
2841 if (file) {
2842 /* read access is always possible with a mapping */
2843 u32 av = FILE__READ;
2844
2845 /* write access only matters if the mapping is shared */
2846 if (shared && (prot & PROT_WRITE))
2847 av |= FILE__WRITE;
2848
2849 if (prot & PROT_EXEC)
2850 av |= FILE__EXECUTE;
2851
2852 return file_has_perm(current, file, av);
2853 }
2854 return 0;
2855}
2856
2857static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002858 unsigned long prot, unsigned long flags,
2859 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
Eric Parised032182007-06-28 15:55:21 -04002861 int rc = 0;
2862 u32 sid = ((struct task_security_struct*)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
Eric Parised032182007-06-28 15:55:21 -04002864 if (addr < mmap_min_addr)
2865 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2866 MEMPROTECT__MMAP_ZERO, NULL);
2867 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 return rc;
2869
2870 if (selinux_checkreqprot)
2871 prot = reqprot;
2872
2873 return file_map_prot_check(file, prot,
2874 (flags & MAP_TYPE) == MAP_SHARED);
2875}
2876
2877static int selinux_file_mprotect(struct vm_area_struct *vma,
2878 unsigned long reqprot,
2879 unsigned long prot)
2880{
2881 int rc;
2882
2883 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2884 if (rc)
2885 return rc;
2886
2887 if (selinux_checkreqprot)
2888 prot = reqprot;
2889
2890#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002891 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2892 rc = 0;
2893 if (vma->vm_start >= vma->vm_mm->start_brk &&
2894 vma->vm_end <= vma->vm_mm->brk) {
2895 rc = task_has_perm(current, current,
2896 PROCESS__EXECHEAP);
2897 } else if (!vma->vm_file &&
2898 vma->vm_start <= vma->vm_mm->start_stack &&
2899 vma->vm_end >= vma->vm_mm->start_stack) {
2900 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2901 } else if (vma->vm_file && vma->anon_vma) {
2902 /*
2903 * We are making executable a file mapping that has
2904 * had some COW done. Since pages might have been
2905 * written, check ability to execute the possibly
2906 * modified content. This typically should only
2907 * occur for text relocations.
2908 */
2909 rc = file_has_perm(current, vma->vm_file,
2910 FILE__EXECMOD);
2911 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002912 if (rc)
2913 return rc;
2914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915#endif
2916
2917 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2918}
2919
2920static int selinux_file_lock(struct file *file, unsigned int cmd)
2921{
2922 return file_has_perm(current, file, FILE__LOCK);
2923}
2924
2925static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2926 unsigned long arg)
2927{
2928 int err = 0;
2929
2930 switch (cmd) {
2931 case F_SETFL:
Josef Sipek3d5ff522006-12-08 02:37:38 -08002932 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 err = -EINVAL;
2934 break;
2935 }
2936
2937 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2938 err = file_has_perm(current, file,FILE__WRITE);
2939 break;
2940 }
2941 /* fall through */
2942 case F_SETOWN:
2943 case F_SETSIG:
2944 case F_GETFL:
2945 case F_GETOWN:
2946 case F_GETSIG:
2947 /* Just check FD__USE permission */
2948 err = file_has_perm(current, file, 0);
2949 break;
2950 case F_GETLK:
2951 case F_SETLK:
2952 case F_SETLKW:
2953#if BITS_PER_LONG == 32
2954 case F_GETLK64:
2955 case F_SETLK64:
2956 case F_SETLKW64:
2957#endif
Josef Sipek3d5ff522006-12-08 02:37:38 -08002958 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 err = -EINVAL;
2960 break;
2961 }
2962 err = file_has_perm(current, file, FILE__LOCK);
2963 break;
2964 }
2965
2966 return err;
2967}
2968
2969static int selinux_file_set_fowner(struct file *file)
2970{
2971 struct task_security_struct *tsec;
2972 struct file_security_struct *fsec;
2973
2974 tsec = current->security;
2975 fsec = file->f_security;
2976 fsec->fown_sid = tsec->sid;
2977
2978 return 0;
2979}
2980
2981static int selinux_file_send_sigiotask(struct task_struct *tsk,
2982 struct fown_struct *fown, int signum)
2983{
2984 struct file *file;
2985 u32 perm;
2986 struct task_security_struct *tsec;
2987 struct file_security_struct *fsec;
2988
2989 /* struct fown_struct is never outside the context of a struct file */
Robert P. J. Dayb385a142007-02-10 01:46:25 -08002990 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 tsec = tsk->security;
2993 fsec = file->f_security;
2994
2995 if (!signum)
2996 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
2997 else
2998 perm = signal_to_av(signum);
2999
3000 return avc_has_perm(fsec->fown_sid, tsec->sid,
3001 SECCLASS_PROCESS, perm, NULL);
3002}
3003
3004static int selinux_file_receive(struct file *file)
3005{
3006 return file_has_perm(current, file, file_to_av(file));
3007}
3008
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003009static int selinux_dentry_open(struct file *file)
3010{
3011 struct file_security_struct *fsec;
3012 struct inode *inode;
3013 struct inode_security_struct *isec;
3014 inode = file->f_path.dentry->d_inode;
3015 fsec = file->f_security;
3016 isec = inode->i_security;
3017 /*
3018 * Save inode label and policy sequence number
3019 * at open-time so that selinux_file_permission
3020 * can determine whether revalidation is necessary.
3021 * Task label is already saved in the file security
3022 * struct as its SID.
3023 */
3024 fsec->isid = isec->sid;
3025 fsec->pseqno = avc_policy_seqno();
3026 /*
3027 * Since the inode label or policy seqno may have changed
3028 * between the selinux_inode_permission check and the saving
3029 * of state above, recheck that access is still permitted.
3030 * Otherwise, access might never be revalidated against the
3031 * new inode label or new policy.
3032 * This check is not redundant - do not remove.
3033 */
3034 return inode_has_perm(current, inode, file_to_av(file), NULL);
3035}
3036
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037/* task security operations */
3038
3039static int selinux_task_create(unsigned long clone_flags)
3040{
3041 int rc;
3042
3043 rc = secondary_ops->task_create(clone_flags);
3044 if (rc)
3045 return rc;
3046
3047 return task_has_perm(current, current, PROCESS__FORK);
3048}
3049
3050static int selinux_task_alloc_security(struct task_struct *tsk)
3051{
3052 struct task_security_struct *tsec1, *tsec2;
3053 int rc;
3054
3055 tsec1 = current->security;
3056
3057 rc = task_alloc_security(tsk);
3058 if (rc)
3059 return rc;
3060 tsec2 = tsk->security;
3061
3062 tsec2->osid = tsec1->osid;
3063 tsec2->sid = tsec1->sid;
3064
Michael LeMay28eba5b2006-06-27 02:53:42 -07003065 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 tsec2->exec_sid = tsec1->exec_sid;
3067 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003068 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003069 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
3071 /* Retain ptracer SID across fork, if any.
3072 This will be reset by the ptrace hook upon any
3073 subsequent ptrace_attach operations. */
3074 tsec2->ptrace_sid = tsec1->ptrace_sid;
3075
3076 return 0;
3077}
3078
3079static void selinux_task_free_security(struct task_struct *tsk)
3080{
3081 task_free_security(tsk);
3082}
3083
3084static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3085{
3086 /* Since setuid only affects the current process, and
3087 since the SELinux controls are not based on the Linux
3088 identity attributes, SELinux does not need to control
3089 this operation. However, SELinux does control the use
3090 of the CAP_SETUID and CAP_SETGID capabilities using the
3091 capable hook. */
3092 return 0;
3093}
3094
3095static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3096{
3097 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
3098}
3099
3100static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3101{
3102 /* See the comment for setuid above. */
3103 return 0;
3104}
3105
3106static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3107{
3108 return task_has_perm(current, p, PROCESS__SETPGID);
3109}
3110
3111static int selinux_task_getpgid(struct task_struct *p)
3112{
3113 return task_has_perm(current, p, PROCESS__GETPGID);
3114}
3115
3116static int selinux_task_getsid(struct task_struct *p)
3117{
3118 return task_has_perm(current, p, PROCESS__GETSESSION);
3119}
3120
David Quigleyf9008e42006-06-30 01:55:46 -07003121static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3122{
3123 selinux_get_task_sid(p, secid);
3124}
3125
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126static int selinux_task_setgroups(struct group_info *group_info)
3127{
3128 /* See the comment for setuid above. */
3129 return 0;
3130}
3131
3132static int selinux_task_setnice(struct task_struct *p, int nice)
3133{
3134 int rc;
3135
3136 rc = secondary_ops->task_setnice(p, nice);
3137 if (rc)
3138 return rc;
3139
3140 return task_has_perm(current,p, PROCESS__SETSCHED);
3141}
3142
James Morris03e68062006-06-23 02:03:58 -07003143static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3144{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003145 int rc;
3146
3147 rc = secondary_ops->task_setioprio(p, ioprio);
3148 if (rc)
3149 return rc;
3150
James Morris03e68062006-06-23 02:03:58 -07003151 return task_has_perm(current, p, PROCESS__SETSCHED);
3152}
3153
David Quigleya1836a42006-06-30 01:55:49 -07003154static int selinux_task_getioprio(struct task_struct *p)
3155{
3156 return task_has_perm(current, p, PROCESS__GETSCHED);
3157}
3158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3160{
3161 struct rlimit *old_rlim = current->signal->rlim + resource;
3162 int rc;
3163
3164 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3165 if (rc)
3166 return rc;
3167
3168 /* Control the ability to change the hard limit (whether
3169 lowering or raising it), so that the hard limit can
3170 later be used as a safe reset point for the soft limit
3171 upon context transitions. See selinux_bprm_apply_creds. */
3172 if (old_rlim->rlim_max != new_rlim->rlim_max)
3173 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3174
3175 return 0;
3176}
3177
3178static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3179{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003180 int rc;
3181
3182 rc = secondary_ops->task_setscheduler(p, policy, lp);
3183 if (rc)
3184 return rc;
3185
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return task_has_perm(current, p, PROCESS__SETSCHED);
3187}
3188
3189static int selinux_task_getscheduler(struct task_struct *p)
3190{
3191 return task_has_perm(current, p, PROCESS__GETSCHED);
3192}
3193
David Quigley35601542006-06-23 02:04:01 -07003194static int selinux_task_movememory(struct task_struct *p)
3195{
3196 return task_has_perm(current, p, PROCESS__SETSCHED);
3197}
3198
David Quigleyf9008e42006-06-30 01:55:46 -07003199static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3200 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201{
3202 u32 perm;
3203 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003204 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
David Quigleyf9008e42006-06-30 01:55:46 -07003206 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 if (rc)
3208 return rc;
3209
Oleg Nesterov621d3122005-10-30 15:03:45 -08003210 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 return 0;
3212
3213 if (!sig)
3214 perm = PROCESS__SIGNULL; /* null signal; existence test */
3215 else
3216 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003217 tsec = p->security;
3218 if (secid)
3219 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3220 else
3221 rc = task_has_perm(current, p, perm);
3222 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223}
3224
3225static int selinux_task_prctl(int option,
3226 unsigned long arg2,
3227 unsigned long arg3,
3228 unsigned long arg4,
3229 unsigned long arg5)
3230{
3231 /* The current prctl operations do not appear to require
3232 any SELinux controls since they merely observe or modify
3233 the state of the current process. */
3234 return 0;
3235}
3236
3237static int selinux_task_wait(struct task_struct *p)
3238{
Eric Paris8a535142007-10-22 16:10:31 -04003239 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240}
3241
3242static void selinux_task_reparent_to_init(struct task_struct *p)
3243{
3244 struct task_security_struct *tsec;
3245
3246 secondary_ops->task_reparent_to_init(p);
3247
3248 tsec = p->security;
3249 tsec->osid = tsec->sid;
3250 tsec->sid = SECINITSID_KERNEL;
3251 return;
3252}
3253
3254static void selinux_task_to_inode(struct task_struct *p,
3255 struct inode *inode)
3256{
3257 struct task_security_struct *tsec = p->security;
3258 struct inode_security_struct *isec = inode->i_security;
3259
3260 isec->sid = tsec->sid;
3261 isec->initialized = 1;
3262 return;
3263}
3264
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003266static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3267 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268{
3269 int offset, ihlen, ret = -EINVAL;
3270 struct iphdr _iph, *ih;
3271
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003272 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3274 if (ih == NULL)
3275 goto out;
3276
3277 ihlen = ih->ihl * 4;
3278 if (ihlen < sizeof(_iph))
3279 goto out;
3280
3281 ad->u.net.v4info.saddr = ih->saddr;
3282 ad->u.net.v4info.daddr = ih->daddr;
3283 ret = 0;
3284
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003285 if (proto)
3286 *proto = ih->protocol;
3287
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 switch (ih->protocol) {
3289 case IPPROTO_TCP: {
3290 struct tcphdr _tcph, *th;
3291
3292 if (ntohs(ih->frag_off) & IP_OFFSET)
3293 break;
3294
3295 offset += ihlen;
3296 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3297 if (th == NULL)
3298 break;
3299
3300 ad->u.net.sport = th->source;
3301 ad->u.net.dport = th->dest;
3302 break;
3303 }
3304
3305 case IPPROTO_UDP: {
3306 struct udphdr _udph, *uh;
3307
3308 if (ntohs(ih->frag_off) & IP_OFFSET)
3309 break;
3310
3311 offset += ihlen;
3312 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3313 if (uh == NULL)
3314 break;
3315
3316 ad->u.net.sport = uh->source;
3317 ad->u.net.dport = uh->dest;
3318 break;
3319 }
3320
James Morris2ee92d42006-11-13 16:09:01 -08003321 case IPPROTO_DCCP: {
3322 struct dccp_hdr _dccph, *dh;
3323
3324 if (ntohs(ih->frag_off) & IP_OFFSET)
3325 break;
3326
3327 offset += ihlen;
3328 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3329 if (dh == NULL)
3330 break;
3331
3332 ad->u.net.sport = dh->dccph_sport;
3333 ad->u.net.dport = dh->dccph_dport;
3334 break;
3335 }
3336
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 default:
3338 break;
3339 }
3340out:
3341 return ret;
3342}
3343
3344#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3345
3346/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003347static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3348 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349{
3350 u8 nexthdr;
3351 int ret = -EINVAL, offset;
3352 struct ipv6hdr _ipv6h, *ip6;
3353
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003354 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3356 if (ip6 == NULL)
3357 goto out;
3358
3359 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3360 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3361 ret = 0;
3362
3363 nexthdr = ip6->nexthdr;
3364 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003365 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 if (offset < 0)
3367 goto out;
3368
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003369 if (proto)
3370 *proto = nexthdr;
3371
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 switch (nexthdr) {
3373 case IPPROTO_TCP: {
3374 struct tcphdr _tcph, *th;
3375
3376 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3377 if (th == NULL)
3378 break;
3379
3380 ad->u.net.sport = th->source;
3381 ad->u.net.dport = th->dest;
3382 break;
3383 }
3384
3385 case IPPROTO_UDP: {
3386 struct udphdr _udph, *uh;
3387
3388 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3389 if (uh == NULL)
3390 break;
3391
3392 ad->u.net.sport = uh->source;
3393 ad->u.net.dport = uh->dest;
3394 break;
3395 }
3396
James Morris2ee92d42006-11-13 16:09:01 -08003397 case IPPROTO_DCCP: {
3398 struct dccp_hdr _dccph, *dh;
3399
3400 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3401 if (dh == NULL)
3402 break;
3403
3404 ad->u.net.sport = dh->dccph_sport;
3405 ad->u.net.dport = dh->dccph_dport;
3406 break;
3407 }
3408
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 /* includes fragments */
3410 default:
3411 break;
3412 }
3413out:
3414 return ret;
3415}
3416
3417#endif /* IPV6 */
3418
3419static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003420 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421{
3422 int ret = 0;
3423
3424 switch (ad->u.net.family) {
3425 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003426 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 if (ret || !addrp)
3428 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3430 &ad->u.net.v4info.daddr);
3431 break;
3432
3433#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3434 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003435 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 if (ret || !addrp)
3437 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3439 &ad->u.net.v6info.daddr);
3440 break;
3441#endif /* IPV6 */
3442 default:
3443 break;
3444 }
3445
Paul Moore71f1cb02008-01-29 08:51:16 -05003446 if (unlikely(ret))
3447 printk(KERN_WARNING
3448 "SELinux: failure in selinux_parse_skb(),"
3449 " unable to parse packet\n");
3450
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 return ret;
3452}
3453
Paul Moore4f6a9932007-03-01 14:35:22 -05003454/**
Paul Moore220deb92008-01-29 08:38:23 -05003455 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003456 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003457 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003458 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003459 *
3460 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003461 * Check the various different forms of network peer labeling and determine
3462 * the peer label/SID for the packet; most of the magic actually occurs in
3463 * the security server function security_net_peersid_cmp(). The function
3464 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3465 * or -EACCES if @sid is invalid due to inconsistencies with the different
3466 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003467 *
3468 */
Paul Moore220deb92008-01-29 08:38:23 -05003469static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003470{
Paul Moore71f1cb02008-01-29 08:51:16 -05003471 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003472 u32 xfrm_sid;
3473 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003474 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003475
3476 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003477 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003478
Paul Moore71f1cb02008-01-29 08:51:16 -05003479 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3480 if (unlikely(err)) {
3481 printk(KERN_WARNING
3482 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3483 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003484 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003485 }
Paul Moore220deb92008-01-29 08:38:23 -05003486
3487 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003488}
3489
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490/* socket security operations */
3491static int socket_has_perm(struct task_struct *task, struct socket *sock,
3492 u32 perms)
3493{
3494 struct inode_security_struct *isec;
3495 struct task_security_struct *tsec;
3496 struct avc_audit_data ad;
3497 int err = 0;
3498
3499 tsec = task->security;
3500 isec = SOCK_INODE(sock)->i_security;
3501
3502 if (isec->sid == SECINITSID_KERNEL)
3503 goto out;
3504
3505 AVC_AUDIT_DATA_INIT(&ad,NET);
3506 ad.u.net.sk = sock->sk;
3507 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3508
3509out:
3510 return err;
3511}
3512
3513static int selinux_socket_create(int family, int type,
3514 int protocol, int kern)
3515{
3516 int err = 0;
3517 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003518 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
3520 if (kern)
3521 goto out;
3522
3523 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003524 newsid = tsec->sockcreate_sid ? : tsec->sid;
3525 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 socket_type_to_security_class(family, type,
3527 protocol), SOCKET__CREATE, NULL);
3528
3529out:
3530 return err;
3531}
3532
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003533static int selinux_socket_post_create(struct socket *sock, int family,
3534 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003536 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 struct inode_security_struct *isec;
3538 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003539 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003540 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
3542 isec = SOCK_INODE(sock)->i_security;
3543
3544 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003545 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003547 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 isec->initialized = 1;
3549
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003550 if (sock->sk) {
3551 sksec = sock->sk->sk_security;
3552 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003553 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003554 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003555 }
3556
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003557 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558}
3559
3560/* Range of port numbers used to automatically bind.
3561 Need to determine whether we should perform a name_bind
3562 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563
3564static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3565{
3566 u16 family;
3567 int err;
3568
3569 err = socket_has_perm(current, sock, SOCKET__BIND);
3570 if (err)
3571 goto out;
3572
3573 /*
3574 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003575 * Multiple address binding for SCTP is not supported yet: we just
3576 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 */
3578 family = sock->sk->sk_family;
3579 if (family == PF_INET || family == PF_INET6) {
3580 char *addrp;
3581 struct inode_security_struct *isec;
3582 struct task_security_struct *tsec;
3583 struct avc_audit_data ad;
3584 struct sockaddr_in *addr4 = NULL;
3585 struct sockaddr_in6 *addr6 = NULL;
3586 unsigned short snum;
3587 struct sock *sk = sock->sk;
3588 u32 sid, node_perm, addrlen;
3589
3590 tsec = current->security;
3591 isec = SOCK_INODE(sock)->i_security;
3592
3593 if (family == PF_INET) {
3594 addr4 = (struct sockaddr_in *)address;
3595 snum = ntohs(addr4->sin_port);
3596 addrlen = sizeof(addr4->sin_addr.s_addr);
3597 addrp = (char *)&addr4->sin_addr.s_addr;
3598 } else {
3599 addr6 = (struct sockaddr_in6 *)address;
3600 snum = ntohs(addr6->sin6_port);
3601 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3602 addrp = (char *)&addr6->sin6_addr.s6_addr;
3603 }
3604
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003605 if (snum) {
3606 int low, high;
3607
3608 inet_get_local_port_range(&low, &high);
3609
3610 if (snum < max(PROT_SOCK, low) || snum > high) {
3611 err = security_port_sid(sk->sk_family,
3612 sk->sk_type,
3613 sk->sk_protocol, snum,
3614 &sid);
3615 if (err)
3616 goto out;
3617 AVC_AUDIT_DATA_INIT(&ad,NET);
3618 ad.u.net.sport = htons(snum);
3619 ad.u.net.family = family;
3620 err = avc_has_perm(isec->sid, sid,
3621 isec->sclass,
3622 SOCKET__NAME_BIND, &ad);
3623 if (err)
3624 goto out;
3625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 }
3627
James Morris13402582005-09-30 14:24:34 -04003628 switch(isec->sclass) {
3629 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 node_perm = TCP_SOCKET__NODE_BIND;
3631 break;
3632
James Morris13402582005-09-30 14:24:34 -04003633 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 node_perm = UDP_SOCKET__NODE_BIND;
3635 break;
James Morris2ee92d42006-11-13 16:09:01 -08003636
3637 case SECCLASS_DCCP_SOCKET:
3638 node_perm = DCCP_SOCKET__NODE_BIND;
3639 break;
3640
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 default:
3642 node_perm = RAWIP_SOCKET__NODE_BIND;
3643 break;
3644 }
3645
Paul Moore224dfbd2008-01-29 08:38:13 -05003646 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 if (err)
3648 goto out;
3649
3650 AVC_AUDIT_DATA_INIT(&ad,NET);
3651 ad.u.net.sport = htons(snum);
3652 ad.u.net.family = family;
3653
3654 if (family == PF_INET)
3655 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3656 else
3657 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3658
3659 err = avc_has_perm(isec->sid, sid,
3660 isec->sclass, node_perm, &ad);
3661 if (err)
3662 goto out;
3663 }
3664out:
3665 return err;
3666}
3667
3668static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3669{
3670 struct inode_security_struct *isec;
3671 int err;
3672
3673 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3674 if (err)
3675 return err;
3676
3677 /*
James Morris2ee92d42006-11-13 16:09:01 -08003678 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 */
3680 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003681 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3682 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683 struct sock *sk = sock->sk;
3684 struct avc_audit_data ad;
3685 struct sockaddr_in *addr4 = NULL;
3686 struct sockaddr_in6 *addr6 = NULL;
3687 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003688 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689
3690 if (sk->sk_family == PF_INET) {
3691 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003692 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 return -EINVAL;
3694 snum = ntohs(addr4->sin_port);
3695 } else {
3696 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003697 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 return -EINVAL;
3699 snum = ntohs(addr6->sin6_port);
3700 }
3701
3702 err = security_port_sid(sk->sk_family, sk->sk_type,
3703 sk->sk_protocol, snum, &sid);
3704 if (err)
3705 goto out;
3706
James Morris2ee92d42006-11-13 16:09:01 -08003707 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3708 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3709
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 AVC_AUDIT_DATA_INIT(&ad,NET);
3711 ad.u.net.dport = htons(snum);
3712 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003713 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 if (err)
3715 goto out;
3716 }
3717
3718out:
3719 return err;
3720}
3721
3722static int selinux_socket_listen(struct socket *sock, int backlog)
3723{
3724 return socket_has_perm(current, sock, SOCKET__LISTEN);
3725}
3726
3727static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3728{
3729 int err;
3730 struct inode_security_struct *isec;
3731 struct inode_security_struct *newisec;
3732
3733 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3734 if (err)
3735 return err;
3736
3737 newisec = SOCK_INODE(newsock)->i_security;
3738
3739 isec = SOCK_INODE(sock)->i_security;
3740 newisec->sclass = isec->sclass;
3741 newisec->sid = isec->sid;
3742 newisec->initialized = 1;
3743
3744 return 0;
3745}
3746
3747static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3748 int size)
3749{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003750 int rc;
3751
3752 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3753 if (rc)
3754 return rc;
3755
3756 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757}
3758
3759static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3760 int size, int flags)
3761{
3762 return socket_has_perm(current, sock, SOCKET__READ);
3763}
3764
3765static int selinux_socket_getsockname(struct socket *sock)
3766{
3767 return socket_has_perm(current, sock, SOCKET__GETATTR);
3768}
3769
3770static int selinux_socket_getpeername(struct socket *sock)
3771{
3772 return socket_has_perm(current, sock, SOCKET__GETATTR);
3773}
3774
3775static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3776{
Paul Mooref8687af2006-10-30 15:22:15 -08003777 int err;
3778
3779 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3780 if (err)
3781 return err;
3782
3783 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784}
3785
3786static int selinux_socket_getsockopt(struct socket *sock, int level,
3787 int optname)
3788{
3789 return socket_has_perm(current, sock, SOCKET__GETOPT);
3790}
3791
3792static int selinux_socket_shutdown(struct socket *sock, int how)
3793{
3794 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3795}
3796
3797static int selinux_socket_unix_stream_connect(struct socket *sock,
3798 struct socket *other,
3799 struct sock *newsk)
3800{
3801 struct sk_security_struct *ssec;
3802 struct inode_security_struct *isec;
3803 struct inode_security_struct *other_isec;
3804 struct avc_audit_data ad;
3805 int err;
3806
3807 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3808 if (err)
3809 return err;
3810
3811 isec = SOCK_INODE(sock)->i_security;
3812 other_isec = SOCK_INODE(other)->i_security;
3813
3814 AVC_AUDIT_DATA_INIT(&ad,NET);
3815 ad.u.net.sk = other->sk;
3816
3817 err = avc_has_perm(isec->sid, other_isec->sid,
3818 isec->sclass,
3819 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3820 if (err)
3821 return err;
3822
3823 /* connecting socket */
3824 ssec = sock->sk->sk_security;
3825 ssec->peer_sid = other_isec->sid;
3826
3827 /* server child socket */
3828 ssec = newsk->sk_security;
3829 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003830 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3831
3832 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833}
3834
3835static int selinux_socket_unix_may_send(struct socket *sock,
3836 struct socket *other)
3837{
3838 struct inode_security_struct *isec;
3839 struct inode_security_struct *other_isec;
3840 struct avc_audit_data ad;
3841 int err;
3842
3843 isec = SOCK_INODE(sock)->i_security;
3844 other_isec = SOCK_INODE(other)->i_security;
3845
3846 AVC_AUDIT_DATA_INIT(&ad,NET);
3847 ad.u.net.sk = other->sk;
3848
3849 err = avc_has_perm(isec->sid, other_isec->sid,
3850 isec->sclass, SOCKET__SENDTO, &ad);
3851 if (err)
3852 return err;
3853
3854 return 0;
3855}
3856
Paul Mooreeffad8d2008-01-29 08:49:27 -05003857static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3858 u32 peer_sid,
3859 struct avc_audit_data *ad)
3860{
3861 int err;
3862 u32 if_sid;
3863 u32 node_sid;
3864
3865 err = sel_netif_sid(ifindex, &if_sid);
3866 if (err)
3867 return err;
3868 err = avc_has_perm(peer_sid, if_sid,
3869 SECCLASS_NETIF, NETIF__INGRESS, ad);
3870 if (err)
3871 return err;
3872
3873 err = sel_netnode_sid(addrp, family, &node_sid);
3874 if (err)
3875 return err;
3876 return avc_has_perm(peer_sid, node_sid,
3877 SECCLASS_NODE, NODE__RECVFROM, ad);
3878}
3879
Paul Moore220deb92008-01-29 08:38:23 -05003880static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3881 struct sk_buff *skb,
3882 struct avc_audit_data *ad,
3883 u16 family,
3884 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885{
Paul Moore220deb92008-01-29 08:38:23 -05003886 int err;
3887 struct sk_security_struct *sksec = sk->sk_security;
3888 u16 sk_class;
3889 u32 netif_perm, node_perm, recv_perm;
3890 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003891
Paul Moore220deb92008-01-29 08:38:23 -05003892 sk_sid = sksec->sid;
3893 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Paul Moore220deb92008-01-29 08:38:23 -05003895 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 case SECCLASS_UDP_SOCKET:
3897 netif_perm = NETIF__UDP_RECV;
3898 node_perm = NODE__UDP_RECV;
3899 recv_perm = UDP_SOCKET__RECV_MSG;
3900 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 case SECCLASS_TCP_SOCKET:
3902 netif_perm = NETIF__TCP_RECV;
3903 node_perm = NODE__TCP_RECV;
3904 recv_perm = TCP_SOCKET__RECV_MSG;
3905 break;
James Morris2ee92d42006-11-13 16:09:01 -08003906 case SECCLASS_DCCP_SOCKET:
3907 netif_perm = NETIF__DCCP_RECV;
3908 node_perm = NODE__DCCP_RECV;
3909 recv_perm = DCCP_SOCKET__RECV_MSG;
3910 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 default:
3912 netif_perm = NETIF__RAWIP_RECV;
3913 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003914 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 break;
3916 }
3917
Paul Moore220deb92008-01-29 08:38:23 -05003918 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003920 return err;
3921 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3922 if (err)
3923 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
Paul Moore224dfbd2008-01-29 08:38:13 -05003925 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003927 return err;
3928 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003930 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
Paul Moore220deb92008-01-29 08:38:23 -05003932 if (!recv_perm)
3933 return 0;
3934 err = security_port_sid(sk->sk_family, sk->sk_type,
3935 sk->sk_protocol, ntohs(ad->u.net.sport),
3936 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05003937 if (unlikely(err)) {
3938 printk(KERN_WARNING
3939 "SELinux: failure in"
3940 " selinux_sock_rcv_skb_iptables_compat(),"
3941 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05003942 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05003943 }
Paul Moore220deb92008-01-29 08:38:23 -05003944 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3945}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Paul Moore220deb92008-01-29 08:38:23 -05003947static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3948 struct avc_audit_data *ad,
3949 u16 family, char *addrp)
3950{
3951 int err;
3952 struct sk_security_struct *sksec = sk->sk_security;
3953 u32 peer_sid;
3954 u32 sk_sid = sksec->sid;
3955
3956 if (selinux_compat_net)
3957 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3958 family, addrp);
3959 else
3960 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3961 PACKET__RECV, ad);
3962 if (err)
3963 return err;
3964
3965 if (selinux_policycap_netpeer) {
3966 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003968 return err;
3969 err = avc_has_perm(sk_sid, peer_sid,
3970 SECCLASS_PEER, PEER__RECV, ad);
3971 } else {
3972 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3973 if (err)
3974 return err;
3975 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003977
James Morris4e5ab4c2006-06-09 00:33:33 -07003978 return err;
3979}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003980
James Morris4e5ab4c2006-06-09 00:33:33 -07003981static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3982{
Paul Moore220deb92008-01-29 08:38:23 -05003983 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003984 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05003985 u16 family = sk->sk_family;
3986 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003987 struct avc_audit_data ad;
3988 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07003989
James Morris4e5ab4c2006-06-09 00:33:33 -07003990 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05003991 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07003992
3993 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00003994 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07003995 family = PF_INET;
3996
James Morris4e5ab4c2006-06-09 00:33:33 -07003997 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05003998 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07003999 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004000 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004001 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004002 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004003
Paul Moore220deb92008-01-29 08:38:23 -05004004 /* If any sort of compatibility mode is enabled then handoff processing
4005 * to the selinux_sock_rcv_skb_compat() function to deal with the
4006 * special handling. We do this in an attempt to keep this function
4007 * as fast and as clean as possible. */
4008 if (selinux_compat_net || !selinux_policycap_netpeer)
4009 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4010 family, addrp);
4011
Paul Moored621d352008-01-29 08:43:36 -05004012 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4013 u32 peer_sid;
4014
4015 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4016 if (err)
4017 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004018 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4019 peer_sid, &ad);
4020 if (err)
4021 return err;
Paul Moored621d352008-01-29 08:43:36 -05004022 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4023 PEER__RECV, &ad);
4024 }
4025
Paul Mooreeffad8d2008-01-29 08:49:27 -05004026 if (selinux_secmark_enabled()) {
4027 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4028 PACKET__RECV, &ad);
4029 if (err)
4030 return err;
4031 }
4032
Paul Moored621d352008-01-29 08:43:36 -05004033 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034}
4035
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004036static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4037 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038{
4039 int err = 0;
4040 char *scontext;
4041 u32 scontext_len;
4042 struct sk_security_struct *ssec;
4043 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004044 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
4046 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004047
Paul Moore3de4bab2006-11-17 17:38:54 -05004048 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4049 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004050 ssec = sock->sk->sk_security;
4051 peer_sid = ssec->peer_sid;
4052 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004053 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 err = -ENOPROTOOPT;
4055 goto out;
4056 }
4057
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004058 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4059
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (err)
4061 goto out;
4062
4063 if (scontext_len > len) {
4064 err = -ERANGE;
4065 goto out_len;
4066 }
4067
4068 if (copy_to_user(optval, scontext, scontext_len))
4069 err = -EFAULT;
4070
4071out_len:
4072 if (put_user(scontext_len, optlen))
4073 err = -EFAULT;
4074
4075 kfree(scontext);
4076out:
4077 return err;
4078}
4079
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004080static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004081{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004082 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004083 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004084
Paul Moore75e22912008-01-29 08:38:04 -05004085 if (sock)
4086 family = sock->sk->sk_family;
4087 else if (skb && skb->sk)
4088 family = skb->sk->sk_family;
4089 else
4090 goto out;
4091
4092 if (sock && family == PF_UNIX)
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004093 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004094 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004095 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004096
Paul Moore75e22912008-01-29 08:38:04 -05004097out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004098 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004099 if (peer_secid == SECSID_NULL)
4100 return -EINVAL;
4101 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004102}
4103
Al Viro7d877f32005-10-21 03:20:43 -04004104static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105{
4106 return sk_alloc_security(sk, family, priority);
4107}
4108
4109static void selinux_sk_free_security(struct sock *sk)
4110{
4111 sk_free_security(sk);
4112}
4113
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004114static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4115{
4116 struct sk_security_struct *ssec = sk->sk_security;
4117 struct sk_security_struct *newssec = newsk->sk_security;
4118
4119 newssec->sid = ssec->sid;
4120 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004121 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004122
Paul Moore9f2ad662006-11-17 17:38:53 -05004123 selinux_netlbl_sk_security_clone(ssec, newssec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004124}
4125
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004126static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004127{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004128 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004129 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004130 else {
4131 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004132
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004133 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004134 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004135}
4136
Adrian Bunk9a673e52006-08-15 00:03:53 -07004137static void selinux_sock_graft(struct sock* sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004138{
4139 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4140 struct sk_security_struct *sksec = sk->sk_security;
4141
David Woodhouse2148ccc2006-09-29 15:50:25 -07004142 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4143 sk->sk_family == PF_UNIX)
4144 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004145 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004146
4147 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004148}
4149
Adrian Bunk9a673e52006-08-15 00:03:53 -07004150static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4151 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004152{
4153 struct sk_security_struct *sksec = sk->sk_security;
4154 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004155 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004156 u32 peersid;
4157
Paul Moore220deb92008-01-29 08:38:23 -05004158 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4159 if (err)
4160 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004161 if (peersid == SECSID_NULL) {
4162 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004163 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004164 return 0;
4165 }
4166
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004167 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4168 if (err)
4169 return err;
4170
4171 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004172 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004173 return 0;
4174}
4175
Adrian Bunk9a673e52006-08-15 00:03:53 -07004176static void selinux_inet_csk_clone(struct sock *newsk,
4177 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004178{
4179 struct sk_security_struct *newsksec = newsk->sk_security;
4180
4181 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004182 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004183 /* NOTE: Ideally, we should also get the isec->sid for the
4184 new socket in sync, but we don't have the isec available yet.
4185 So we will wait until sock_graft to do it, by which
4186 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004187
Paul Moore9f2ad662006-11-17 17:38:53 -05004188 /* We don't need to take any sort of lock here as we are the only
4189 * thread with access to newsksec */
4190 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004191}
4192
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004193static void selinux_inet_conn_established(struct sock *sk,
4194 struct sk_buff *skb)
4195{
4196 struct sk_security_struct *sksec = sk->sk_security;
4197
Paul Moore220deb92008-01-29 08:38:23 -05004198 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004199}
4200
Adrian Bunk9a673e52006-08-15 00:03:53 -07004201static void selinux_req_classify_flow(const struct request_sock *req,
4202 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004203{
4204 fl->secid = req->secid;
4205}
4206
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4208{
4209 int err = 0;
4210 u32 perm;
4211 struct nlmsghdr *nlh;
4212 struct socket *sock = sk->sk_socket;
4213 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4214
4215 if (skb->len < NLMSG_SPACE(0)) {
4216 err = -EINVAL;
4217 goto out;
4218 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004219 nlh = nlmsg_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220
4221 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4222 if (err) {
4223 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004224 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 "SELinux: unrecognized netlink message"
4226 " type=%hu for sclass=%hu\n",
4227 nlh->nlmsg_type, isec->sclass);
4228 if (!selinux_enforcing)
4229 err = 0;
4230 }
4231
4232 /* Ignore */
4233 if (err == -ENOENT)
4234 err = 0;
4235 goto out;
4236 }
4237
4238 err = socket_has_perm(current, sock, perm);
4239out:
4240 return err;
4241}
4242
4243#ifdef CONFIG_NETFILTER
4244
Paul Mooreeffad8d2008-01-29 08:49:27 -05004245static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4246 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004248 char *addrp;
4249 u32 peer_sid;
4250 struct avc_audit_data ad;
4251 u8 secmark_active;
4252 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004253
Paul Mooreeffad8d2008-01-29 08:49:27 -05004254 if (!selinux_policycap_netpeer)
4255 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004256
Paul Mooreeffad8d2008-01-29 08:49:27 -05004257 secmark_active = selinux_secmark_enabled();
4258 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4259 if (!secmark_active && !peerlbl_active)
4260 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004261
Paul Mooreeffad8d2008-01-29 08:49:27 -05004262 AVC_AUDIT_DATA_INIT(&ad, NET);
4263 ad.u.net.netif = ifindex;
4264 ad.u.net.family = family;
4265 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4266 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Paul Mooreeffad8d2008-01-29 08:49:27 -05004268 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4269 return NF_DROP;
4270
4271 if (peerlbl_active)
4272 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4273 peer_sid, &ad) != 0)
4274 return NF_DROP;
4275
4276 if (secmark_active)
4277 if (avc_has_perm(peer_sid, skb->secmark,
4278 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4279 return NF_DROP;
4280
4281 return NF_ACCEPT;
4282}
4283
4284static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4285 struct sk_buff *skb,
4286 const struct net_device *in,
4287 const struct net_device *out,
4288 int (*okfn)(struct sk_buff *))
4289{
4290 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4291}
4292
4293#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4294static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4295 struct sk_buff *skb,
4296 const struct net_device *in,
4297 const struct net_device *out,
4298 int (*okfn)(struct sk_buff *))
4299{
4300 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4301}
4302#endif /* IPV6 */
4303
4304static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4305 int ifindex,
4306 struct avc_audit_data *ad,
4307 u16 family, char *addrp)
4308{
4309 int err;
4310 struct sk_security_struct *sksec = sk->sk_security;
4311 u16 sk_class;
4312 u32 netif_perm, node_perm, send_perm;
4313 u32 port_sid, node_sid, if_sid, sk_sid;
4314
4315 sk_sid = sksec->sid;
4316 sk_class = sksec->sclass;
4317
4318 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 case SECCLASS_UDP_SOCKET:
4320 netif_perm = NETIF__UDP_SEND;
4321 node_perm = NODE__UDP_SEND;
4322 send_perm = UDP_SOCKET__SEND_MSG;
4323 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 case SECCLASS_TCP_SOCKET:
4325 netif_perm = NETIF__TCP_SEND;
4326 node_perm = NODE__TCP_SEND;
4327 send_perm = TCP_SOCKET__SEND_MSG;
4328 break;
James Morris2ee92d42006-11-13 16:09:01 -08004329 case SECCLASS_DCCP_SOCKET:
4330 netif_perm = NETIF__DCCP_SEND;
4331 node_perm = NODE__DCCP_SEND;
4332 send_perm = DCCP_SOCKET__SEND_MSG;
4333 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 default:
4335 netif_perm = NETIF__RAWIP_SEND;
4336 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004337 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 break;
4339 }
4340
Paul Mooreeffad8d2008-01-29 08:49:27 -05004341 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004342 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004343 return err;
4344 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4345 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Paul Moore224dfbd2008-01-29 08:38:13 -05004347 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004348 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004349 return err;
4350 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004351 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004352 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353
Paul Mooreeffad8d2008-01-29 08:49:27 -05004354 if (send_perm != 0)
4355 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356
Paul Mooreeffad8d2008-01-29 08:49:27 -05004357 err = security_port_sid(sk->sk_family, sk->sk_type,
4358 sk->sk_protocol, ntohs(ad->u.net.dport),
4359 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004360 if (unlikely(err)) {
4361 printk(KERN_WARNING
4362 "SELinux: failure in"
4363 " selinux_ip_postroute_iptables_compat(),"
4364 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004365 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004366 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004367 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004368}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
Paul Mooreeffad8d2008-01-29 08:49:27 -05004370static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4371 int ifindex,
4372 struct avc_audit_data *ad,
4373 u16 family,
4374 char *addrp,
4375 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004376{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004377 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004378 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004379
Paul Mooreeffad8d2008-01-29 08:49:27 -05004380 if (sk == NULL)
4381 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004382 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004383
Paul Mooreeffad8d2008-01-29 08:49:27 -05004384 if (selinux_compat_net) {
4385 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4386 ad, family, addrp))
4387 return NF_DROP;
4388 } else {
4389 if (avc_has_perm(sksec->sid, skb->secmark,
4390 SECCLASS_PACKET, PACKET__SEND, ad))
4391 return NF_DROP;
4392 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004393
Paul Mooreeffad8d2008-01-29 08:49:27 -05004394 if (selinux_policycap_netpeer)
4395 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4396 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004397
Paul Mooreeffad8d2008-01-29 08:49:27 -05004398 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399}
4400
Paul Mooreeffad8d2008-01-29 08:49:27 -05004401static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4402 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004404 u32 secmark_perm;
4405 u32 peer_sid;
4406 struct sock *sk;
4407 struct avc_audit_data ad;
4408 char *addrp;
4409 u8 proto;
4410 u8 secmark_active;
4411 u8 peerlbl_active;
4412
4413 AVC_AUDIT_DATA_INIT(&ad, NET);
4414 ad.u.net.netif = ifindex;
4415 ad.u.net.family = family;
4416 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4417 return NF_DROP;
4418
4419 /* If any sort of compatibility mode is enabled then handoff processing
4420 * to the selinux_ip_postroute_compat() function to deal with the
4421 * special handling. We do this in an attempt to keep this function
4422 * as fast and as clean as possible. */
4423 if (selinux_compat_net || !selinux_policycap_netpeer)
4424 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4425 family, addrp, proto);
4426
4427 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4428 * packet transformation so allow the packet to pass without any checks
4429 * since we'll have another chance to perform access control checks
4430 * when the packet is on it's final way out.
4431 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4432 * is NULL, in this case go ahead and apply access control. */
4433 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4434 return NF_ACCEPT;
4435
4436 secmark_active = selinux_secmark_enabled();
4437 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4438 if (!secmark_active && !peerlbl_active)
4439 return NF_ACCEPT;
4440
4441 /* if the packet is locally generated (skb->sk != NULL) then use the
4442 * socket's label as the peer label, otherwise the packet is being
4443 * forwarded through this system and we need to fetch the peer label
4444 * directly from the packet */
4445 sk = skb->sk;
4446 if (sk) {
4447 struct sk_security_struct *sksec = sk->sk_security;
4448 peer_sid = sksec->sid;
4449 secmark_perm = PACKET__SEND;
4450 } else {
4451 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4452 return NF_DROP;
4453 secmark_perm = PACKET__FORWARD_OUT;
4454 }
4455
4456 if (secmark_active)
4457 if (avc_has_perm(peer_sid, skb->secmark,
4458 SECCLASS_PACKET, secmark_perm, &ad))
4459 return NF_DROP;
4460
4461 if (peerlbl_active) {
4462 u32 if_sid;
4463 u32 node_sid;
4464
4465 if (sel_netif_sid(ifindex, &if_sid))
4466 return NF_DROP;
4467 if (avc_has_perm(peer_sid, if_sid,
4468 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4469 return NF_DROP;
4470
4471 if (sel_netnode_sid(addrp, family, &node_sid))
4472 return NF_DROP;
4473 if (avc_has_perm(peer_sid, node_sid,
4474 SECCLASS_NODE, NODE__SENDTO, &ad))
4475 return NF_DROP;
4476 }
4477
4478 return NF_ACCEPT;
4479}
4480
4481static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4482 struct sk_buff *skb,
4483 const struct net_device *in,
4484 const struct net_device *out,
4485 int (*okfn)(struct sk_buff *))
4486{
4487 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488}
4489
4490#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004491static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4492 struct sk_buff *skb,
4493 const struct net_device *in,
4494 const struct net_device *out,
4495 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004497 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499#endif /* IPV6 */
4500
4501#endif /* CONFIG_NETFILTER */
4502
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4504{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505 int err;
4506
4507 err = secondary_ops->netlink_send(sk, skb);
4508 if (err)
4509 return err;
4510
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4512 err = selinux_nlmsg_perm(sk, skb);
4513
4514 return err;
4515}
4516
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004517static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004519 int err;
4520 struct avc_audit_data ad;
4521
4522 err = secondary_ops->netlink_recv(skb, capability);
4523 if (err)
4524 return err;
4525
4526 AVC_AUDIT_DATA_INIT(&ad, CAP);
4527 ad.u.cap = capability;
4528
4529 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
4530 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531}
4532
4533static int ipc_alloc_security(struct task_struct *task,
4534 struct kern_ipc_perm *perm,
4535 u16 sclass)
4536{
4537 struct task_security_struct *tsec = task->security;
4538 struct ipc_security_struct *isec;
4539
James Morris89d155e2005-10-30 14:59:21 -08004540 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 if (!isec)
4542 return -ENOMEM;
4543
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 isec->sclass = sclass;
4545 isec->ipc_perm = perm;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004546 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 perm->security = isec;
4548
4549 return 0;
4550}
4551
4552static void ipc_free_security(struct kern_ipc_perm *perm)
4553{
4554 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 perm->security = NULL;
4556 kfree(isec);
4557}
4558
4559static int msg_msg_alloc_security(struct msg_msg *msg)
4560{
4561 struct msg_security_struct *msec;
4562
James Morris89d155e2005-10-30 14:59:21 -08004563 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 if (!msec)
4565 return -ENOMEM;
4566
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 msec->msg = msg;
4568 msec->sid = SECINITSID_UNLABELED;
4569 msg->security = msec;
4570
4571 return 0;
4572}
4573
4574static void msg_msg_free_security(struct msg_msg *msg)
4575{
4576 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577
4578 msg->security = NULL;
4579 kfree(msec);
4580}
4581
4582static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004583 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584{
4585 struct task_security_struct *tsec;
4586 struct ipc_security_struct *isec;
4587 struct avc_audit_data ad;
4588
4589 tsec = current->security;
4590 isec = ipc_perms->security;
4591
4592 AVC_AUDIT_DATA_INIT(&ad, IPC);
4593 ad.u.ipc_id = ipc_perms->key;
4594
Stephen Smalley6af963f2005-05-01 08:58:39 -07004595 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596}
4597
4598static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4599{
4600 return msg_msg_alloc_security(msg);
4601}
4602
4603static void selinux_msg_msg_free_security(struct msg_msg *msg)
4604{
4605 msg_msg_free_security(msg);
4606}
4607
4608/* message queue security operations */
4609static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4610{
4611 struct task_security_struct *tsec;
4612 struct ipc_security_struct *isec;
4613 struct avc_audit_data ad;
4614 int rc;
4615
4616 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4617 if (rc)
4618 return rc;
4619
4620 tsec = current->security;
4621 isec = msq->q_perm.security;
4622
4623 AVC_AUDIT_DATA_INIT(&ad, IPC);
4624 ad.u.ipc_id = msq->q_perm.key;
4625
4626 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4627 MSGQ__CREATE, &ad);
4628 if (rc) {
4629 ipc_free_security(&msq->q_perm);
4630 return rc;
4631 }
4632 return 0;
4633}
4634
4635static void selinux_msg_queue_free_security(struct msg_queue *msq)
4636{
4637 ipc_free_security(&msq->q_perm);
4638}
4639
4640static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4641{
4642 struct task_security_struct *tsec;
4643 struct ipc_security_struct *isec;
4644 struct avc_audit_data ad;
4645
4646 tsec = current->security;
4647 isec = msq->q_perm.security;
4648
4649 AVC_AUDIT_DATA_INIT(&ad, IPC);
4650 ad.u.ipc_id = msq->q_perm.key;
4651
4652 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4653 MSGQ__ASSOCIATE, &ad);
4654}
4655
4656static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4657{
4658 int err;
4659 int perms;
4660
4661 switch(cmd) {
4662 case IPC_INFO:
4663 case MSG_INFO:
4664 /* No specific object, just general system-wide information. */
4665 return task_has_system(current, SYSTEM__IPC_INFO);
4666 case IPC_STAT:
4667 case MSG_STAT:
4668 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4669 break;
4670 case IPC_SET:
4671 perms = MSGQ__SETATTR;
4672 break;
4673 case IPC_RMID:
4674 perms = MSGQ__DESTROY;
4675 break;
4676 default:
4677 return 0;
4678 }
4679
Stephen Smalley6af963f2005-05-01 08:58:39 -07004680 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681 return err;
4682}
4683
4684static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4685{
4686 struct task_security_struct *tsec;
4687 struct ipc_security_struct *isec;
4688 struct msg_security_struct *msec;
4689 struct avc_audit_data ad;
4690 int rc;
4691
4692 tsec = current->security;
4693 isec = msq->q_perm.security;
4694 msec = msg->security;
4695
4696 /*
4697 * First time through, need to assign label to the message
4698 */
4699 if (msec->sid == SECINITSID_UNLABELED) {
4700 /*
4701 * Compute new sid based on current process and
4702 * message queue this message will be stored in
4703 */
4704 rc = security_transition_sid(tsec->sid,
4705 isec->sid,
4706 SECCLASS_MSG,
4707 &msec->sid);
4708 if (rc)
4709 return rc;
4710 }
4711
4712 AVC_AUDIT_DATA_INIT(&ad, IPC);
4713 ad.u.ipc_id = msq->q_perm.key;
4714
4715 /* Can this process write to the queue? */
4716 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4717 MSGQ__WRITE, &ad);
4718 if (!rc)
4719 /* Can this process send the message */
4720 rc = avc_has_perm(tsec->sid, msec->sid,
4721 SECCLASS_MSG, MSG__SEND, &ad);
4722 if (!rc)
4723 /* Can the message be put in the queue? */
4724 rc = avc_has_perm(msec->sid, isec->sid,
4725 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4726
4727 return rc;
4728}
4729
4730static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4731 struct task_struct *target,
4732 long type, int mode)
4733{
4734 struct task_security_struct *tsec;
4735 struct ipc_security_struct *isec;
4736 struct msg_security_struct *msec;
4737 struct avc_audit_data ad;
4738 int rc;
4739
4740 tsec = target->security;
4741 isec = msq->q_perm.security;
4742 msec = msg->security;
4743
4744 AVC_AUDIT_DATA_INIT(&ad, IPC);
4745 ad.u.ipc_id = msq->q_perm.key;
4746
4747 rc = avc_has_perm(tsec->sid, isec->sid,
4748 SECCLASS_MSGQ, MSGQ__READ, &ad);
4749 if (!rc)
4750 rc = avc_has_perm(tsec->sid, msec->sid,
4751 SECCLASS_MSG, MSG__RECEIVE, &ad);
4752 return rc;
4753}
4754
4755/* Shared Memory security operations */
4756static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4757{
4758 struct task_security_struct *tsec;
4759 struct ipc_security_struct *isec;
4760 struct avc_audit_data ad;
4761 int rc;
4762
4763 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4764 if (rc)
4765 return rc;
4766
4767 tsec = current->security;
4768 isec = shp->shm_perm.security;
4769
4770 AVC_AUDIT_DATA_INIT(&ad, IPC);
4771 ad.u.ipc_id = shp->shm_perm.key;
4772
4773 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4774 SHM__CREATE, &ad);
4775 if (rc) {
4776 ipc_free_security(&shp->shm_perm);
4777 return rc;
4778 }
4779 return 0;
4780}
4781
4782static void selinux_shm_free_security(struct shmid_kernel *shp)
4783{
4784 ipc_free_security(&shp->shm_perm);
4785}
4786
4787static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4788{
4789 struct task_security_struct *tsec;
4790 struct ipc_security_struct *isec;
4791 struct avc_audit_data ad;
4792
4793 tsec = current->security;
4794 isec = shp->shm_perm.security;
4795
4796 AVC_AUDIT_DATA_INIT(&ad, IPC);
4797 ad.u.ipc_id = shp->shm_perm.key;
4798
4799 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4800 SHM__ASSOCIATE, &ad);
4801}
4802
4803/* Note, at this point, shp is locked down */
4804static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4805{
4806 int perms;
4807 int err;
4808
4809 switch(cmd) {
4810 case IPC_INFO:
4811 case SHM_INFO:
4812 /* No specific object, just general system-wide information. */
4813 return task_has_system(current, SYSTEM__IPC_INFO);
4814 case IPC_STAT:
4815 case SHM_STAT:
4816 perms = SHM__GETATTR | SHM__ASSOCIATE;
4817 break;
4818 case IPC_SET:
4819 perms = SHM__SETATTR;
4820 break;
4821 case SHM_LOCK:
4822 case SHM_UNLOCK:
4823 perms = SHM__LOCK;
4824 break;
4825 case IPC_RMID:
4826 perms = SHM__DESTROY;
4827 break;
4828 default:
4829 return 0;
4830 }
4831
Stephen Smalley6af963f2005-05-01 08:58:39 -07004832 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833 return err;
4834}
4835
4836static int selinux_shm_shmat(struct shmid_kernel *shp,
4837 char __user *shmaddr, int shmflg)
4838{
4839 u32 perms;
4840 int rc;
4841
4842 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4843 if (rc)
4844 return rc;
4845
4846 if (shmflg & SHM_RDONLY)
4847 perms = SHM__READ;
4848 else
4849 perms = SHM__READ | SHM__WRITE;
4850
Stephen Smalley6af963f2005-05-01 08:58:39 -07004851 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852}
4853
4854/* Semaphore security operations */
4855static int selinux_sem_alloc_security(struct sem_array *sma)
4856{
4857 struct task_security_struct *tsec;
4858 struct ipc_security_struct *isec;
4859 struct avc_audit_data ad;
4860 int rc;
4861
4862 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4863 if (rc)
4864 return rc;
4865
4866 tsec = current->security;
4867 isec = sma->sem_perm.security;
4868
4869 AVC_AUDIT_DATA_INIT(&ad, IPC);
4870 ad.u.ipc_id = sma->sem_perm.key;
4871
4872 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4873 SEM__CREATE, &ad);
4874 if (rc) {
4875 ipc_free_security(&sma->sem_perm);
4876 return rc;
4877 }
4878 return 0;
4879}
4880
4881static void selinux_sem_free_security(struct sem_array *sma)
4882{
4883 ipc_free_security(&sma->sem_perm);
4884}
4885
4886static int selinux_sem_associate(struct sem_array *sma, int semflg)
4887{
4888 struct task_security_struct *tsec;
4889 struct ipc_security_struct *isec;
4890 struct avc_audit_data ad;
4891
4892 tsec = current->security;
4893 isec = sma->sem_perm.security;
4894
4895 AVC_AUDIT_DATA_INIT(&ad, IPC);
4896 ad.u.ipc_id = sma->sem_perm.key;
4897
4898 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4899 SEM__ASSOCIATE, &ad);
4900}
4901
4902/* Note, at this point, sma is locked down */
4903static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4904{
4905 int err;
4906 u32 perms;
4907
4908 switch(cmd) {
4909 case IPC_INFO:
4910 case SEM_INFO:
4911 /* No specific object, just general system-wide information. */
4912 return task_has_system(current, SYSTEM__IPC_INFO);
4913 case GETPID:
4914 case GETNCNT:
4915 case GETZCNT:
4916 perms = SEM__GETATTR;
4917 break;
4918 case GETVAL:
4919 case GETALL:
4920 perms = SEM__READ;
4921 break;
4922 case SETVAL:
4923 case SETALL:
4924 perms = SEM__WRITE;
4925 break;
4926 case IPC_RMID:
4927 perms = SEM__DESTROY;
4928 break;
4929 case IPC_SET:
4930 perms = SEM__SETATTR;
4931 break;
4932 case IPC_STAT:
4933 case SEM_STAT:
4934 perms = SEM__GETATTR | SEM__ASSOCIATE;
4935 break;
4936 default:
4937 return 0;
4938 }
4939
Stephen Smalley6af963f2005-05-01 08:58:39 -07004940 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 return err;
4942}
4943
4944static int selinux_sem_semop(struct sem_array *sma,
4945 struct sembuf *sops, unsigned nsops, int alter)
4946{
4947 u32 perms;
4948
4949 if (alter)
4950 perms = SEM__READ | SEM__WRITE;
4951 else
4952 perms = SEM__READ;
4953
Stephen Smalley6af963f2005-05-01 08:58:39 -07004954 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955}
4956
4957static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4958{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 u32 av = 0;
4960
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961 av = 0;
4962 if (flag & S_IRUGO)
4963 av |= IPC__UNIX_READ;
4964 if (flag & S_IWUGO)
4965 av |= IPC__UNIX_WRITE;
4966
4967 if (av == 0)
4968 return 0;
4969
Stephen Smalley6af963f2005-05-01 08:58:39 -07004970 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971}
4972
4973/* module stacking operations */
4974static int selinux_register_security (const char *name, struct security_operations *ops)
4975{
4976 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05004977 printk(KERN_ERR "%s: There is already a secondary security "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978 "module registered.\n", __FUNCTION__);
4979 return -EINVAL;
4980 }
4981
4982 secondary_ops = ops;
4983
4984 printk(KERN_INFO "%s: Registering secondary module %s\n",
4985 __FUNCTION__,
4986 name);
4987
4988 return 0;
4989}
4990
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
4992{
4993 if (inode)
4994 inode_doinit_with_dentry(inode, dentry);
4995}
4996
4997static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00004998 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999{
5000 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005001 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005003 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004
5005 if (current != p) {
5006 error = task_has_perm(current, p, PROCESS__GETATTR);
5007 if (error)
5008 return error;
5009 }
5010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 tsec = p->security;
5012
5013 if (!strcmp(name, "current"))
5014 sid = tsec->sid;
5015 else if (!strcmp(name, "prev"))
5016 sid = tsec->osid;
5017 else if (!strcmp(name, "exec"))
5018 sid = tsec->exec_sid;
5019 else if (!strcmp(name, "fscreate"))
5020 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005021 else if (!strcmp(name, "keycreate"))
5022 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005023 else if (!strcmp(name, "sockcreate"))
5024 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025 else
5026 return -EINVAL;
5027
5028 if (!sid)
5029 return 0;
5030
Al Viro04ff9702007-03-12 16:17:58 +00005031 error = security_sid_to_context(sid, value, &len);
5032 if (error)
5033 return error;
5034 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035}
5036
5037static int selinux_setprocattr(struct task_struct *p,
5038 char *name, void *value, size_t size)
5039{
5040 struct task_security_struct *tsec;
5041 u32 sid = 0;
5042 int error;
5043 char *str = value;
5044
5045 if (current != p) {
5046 /* SELinux only allows a process to change its own
5047 security attributes. */
5048 return -EACCES;
5049 }
5050
5051 /*
5052 * Basic control over ability to set these attributes at all.
5053 * current == p, but we'll pass them separately in case the
5054 * above restriction is ever removed.
5055 */
5056 if (!strcmp(name, "exec"))
5057 error = task_has_perm(current, p, PROCESS__SETEXEC);
5058 else if (!strcmp(name, "fscreate"))
5059 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005060 else if (!strcmp(name, "keycreate"))
5061 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005062 else if (!strcmp(name, "sockcreate"))
5063 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064 else if (!strcmp(name, "current"))
5065 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5066 else
5067 error = -EINVAL;
5068 if (error)
5069 return error;
5070
5071 /* Obtain a SID for the context, if one was specified. */
5072 if (size && str[1] && str[1] != '\n') {
5073 if (str[size-1] == '\n') {
5074 str[size-1] = 0;
5075 size--;
5076 }
5077 error = security_context_to_sid(value, size, &sid);
5078 if (error)
5079 return error;
5080 }
5081
5082 /* Permission checking based on the specified context is
5083 performed during the actual operation (execve,
5084 open/mkdir/...), when we know the full context of the
5085 operation. See selinux_bprm_set_security for the execve
5086 checks and may_create for the file creation checks. The
5087 operation will then fail if the context is not permitted. */
5088 tsec = p->security;
5089 if (!strcmp(name, "exec"))
5090 tsec->exec_sid = sid;
5091 else if (!strcmp(name, "fscreate"))
5092 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005093 else if (!strcmp(name, "keycreate")) {
5094 error = may_create_key(sid, p);
5095 if (error)
5096 return error;
5097 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005098 } else if (!strcmp(name, "sockcreate"))
5099 tsec->sockcreate_sid = sid;
5100 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101 struct av_decision avd;
5102
5103 if (sid == 0)
5104 return -EINVAL;
5105
5106 /* Only allow single threaded processes to change context */
5107 if (atomic_read(&p->mm->mm_users) != 1) {
5108 struct task_struct *g, *t;
5109 struct mm_struct *mm = p->mm;
5110 read_lock(&tasklist_lock);
5111 do_each_thread(g, t)
5112 if (t->mm == mm && t != p) {
5113 read_unlock(&tasklist_lock);
5114 return -EPERM;
5115 }
5116 while_each_thread(g, t);
5117 read_unlock(&tasklist_lock);
5118 }
5119
5120 /* Check permissions for the transition. */
5121 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
5122 PROCESS__DYNTRANSITION, NULL);
5123 if (error)
5124 return error;
5125
5126 /* Check for ptracing, and update the task SID if ok.
5127 Otherwise, leave SID unchanged and fail. */
5128 task_lock(p);
5129 if (p->ptrace & PT_PTRACED) {
5130 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
5131 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005132 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133 if (!error)
5134 tsec->sid = sid;
5135 task_unlock(p);
5136 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
5137 PROCESS__PTRACE, &avd, error, NULL);
5138 if (error)
5139 return error;
5140 } else {
5141 tsec->sid = sid;
5142 task_unlock(p);
5143 }
5144 }
5145 else
5146 return -EINVAL;
5147
5148 return size;
5149}
5150
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005151static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5152{
5153 return security_sid_to_context(secid, secdata, seclen);
5154}
5155
David Howells63cb3442008-01-15 23:47:35 +00005156static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
5157{
5158 return security_context_to_sid(secdata, seclen, secid);
5159}
5160
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005161static void selinux_release_secctx(char *secdata, u32 seclen)
5162{
Paul Moore088999e2007-08-01 11:12:58 -04005163 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005164}
5165
Michael LeMayd7200242006-06-22 14:47:17 -07005166#ifdef CONFIG_KEYS
5167
David Howells7e047ef2006-06-26 00:24:50 -07005168static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5169 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005170{
5171 struct task_security_struct *tsec = tsk->security;
5172 struct key_security_struct *ksec;
5173
5174 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5175 if (!ksec)
5176 return -ENOMEM;
5177
5178 ksec->obj = k;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005179 if (tsec->keycreate_sid)
5180 ksec->sid = tsec->keycreate_sid;
5181 else
5182 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005183 k->security = ksec;
5184
5185 return 0;
5186}
5187
5188static void selinux_key_free(struct key *k)
5189{
5190 struct key_security_struct *ksec = k->security;
5191
5192 k->security = NULL;
5193 kfree(ksec);
5194}
5195
5196static int selinux_key_permission(key_ref_t key_ref,
5197 struct task_struct *ctx,
5198 key_perm_t perm)
5199{
5200 struct key *key;
5201 struct task_security_struct *tsec;
5202 struct key_security_struct *ksec;
5203
5204 key = key_ref_to_ptr(key_ref);
5205
5206 tsec = ctx->security;
5207 ksec = key->security;
5208
5209 /* if no specific permissions are requested, we skip the
5210 permission check. No serious, additional covert channels
5211 appear to be created. */
5212 if (perm == 0)
5213 return 0;
5214
5215 return avc_has_perm(tsec->sid, ksec->sid,
5216 SECCLASS_KEY, perm, NULL);
5217}
5218
5219#endif
5220
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221static struct security_operations selinux_ops = {
5222 .ptrace = selinux_ptrace,
5223 .capget = selinux_capget,
5224 .capset_check = selinux_capset_check,
5225 .capset_set = selinux_capset_set,
5226 .sysctl = selinux_sysctl,
5227 .capable = selinux_capable,
5228 .quotactl = selinux_quotactl,
5229 .quota_on = selinux_quota_on,
5230 .syslog = selinux_syslog,
5231 .vm_enough_memory = selinux_vm_enough_memory,
5232
5233 .netlink_send = selinux_netlink_send,
5234 .netlink_recv = selinux_netlink_recv,
5235
5236 .bprm_alloc_security = selinux_bprm_alloc_security,
5237 .bprm_free_security = selinux_bprm_free_security,
5238 .bprm_apply_creds = selinux_bprm_apply_creds,
5239 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5240 .bprm_set_security = selinux_bprm_set_security,
5241 .bprm_check_security = selinux_bprm_check_security,
5242 .bprm_secureexec = selinux_bprm_secureexec,
5243
5244 .sb_alloc_security = selinux_sb_alloc_security,
5245 .sb_free_security = selinux_sb_free_security,
5246 .sb_copy_data = selinux_sb_copy_data,
5247 .sb_kern_mount = selinux_sb_kern_mount,
5248 .sb_statfs = selinux_sb_statfs,
5249 .sb_mount = selinux_mount,
5250 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005251 .sb_get_mnt_opts = selinux_get_mnt_opts,
5252 .sb_set_mnt_opts = selinux_set_mnt_opts,
5253 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254
5255 .inode_alloc_security = selinux_inode_alloc_security,
5256 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005257 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 .inode_unlink = selinux_inode_unlink,
5261 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263 .inode_rmdir = selinux_inode_rmdir,
5264 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 .inode_readlink = selinux_inode_readlink,
5267 .inode_follow_link = selinux_inode_follow_link,
5268 .inode_permission = selinux_inode_permission,
5269 .inode_setattr = selinux_inode_setattr,
5270 .inode_getattr = selinux_inode_getattr,
5271 .inode_setxattr = selinux_inode_setxattr,
5272 .inode_post_setxattr = selinux_inode_post_setxattr,
5273 .inode_getxattr = selinux_inode_getxattr,
5274 .inode_listxattr = selinux_inode_listxattr,
5275 .inode_removexattr = selinux_inode_removexattr,
5276 .inode_getsecurity = selinux_inode_getsecurity,
5277 .inode_setsecurity = selinux_inode_setsecurity,
5278 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005279 .inode_need_killpriv = selinux_inode_need_killpriv,
5280 .inode_killpriv = selinux_inode_killpriv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
5282 .file_permission = selinux_file_permission,
5283 .file_alloc_security = selinux_file_alloc_security,
5284 .file_free_security = selinux_file_free_security,
5285 .file_ioctl = selinux_file_ioctl,
5286 .file_mmap = selinux_file_mmap,
5287 .file_mprotect = selinux_file_mprotect,
5288 .file_lock = selinux_file_lock,
5289 .file_fcntl = selinux_file_fcntl,
5290 .file_set_fowner = selinux_file_set_fowner,
5291 .file_send_sigiotask = selinux_file_send_sigiotask,
5292 .file_receive = selinux_file_receive,
5293
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005294 .dentry_open = selinux_dentry_open,
5295
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296 .task_create = selinux_task_create,
5297 .task_alloc_security = selinux_task_alloc_security,
5298 .task_free_security = selinux_task_free_security,
5299 .task_setuid = selinux_task_setuid,
5300 .task_post_setuid = selinux_task_post_setuid,
5301 .task_setgid = selinux_task_setgid,
5302 .task_setpgid = selinux_task_setpgid,
5303 .task_getpgid = selinux_task_getpgid,
5304 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005305 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306 .task_setgroups = selinux_task_setgroups,
5307 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005308 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005309 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310 .task_setrlimit = selinux_task_setrlimit,
5311 .task_setscheduler = selinux_task_setscheduler,
5312 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005313 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314 .task_kill = selinux_task_kill,
5315 .task_wait = selinux_task_wait,
5316 .task_prctl = selinux_task_prctl,
5317 .task_reparent_to_init = selinux_task_reparent_to_init,
5318 .task_to_inode = selinux_task_to_inode,
5319
5320 .ipc_permission = selinux_ipc_permission,
5321
5322 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5323 .msg_msg_free_security = selinux_msg_msg_free_security,
5324
5325 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5326 .msg_queue_free_security = selinux_msg_queue_free_security,
5327 .msg_queue_associate = selinux_msg_queue_associate,
5328 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5329 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5330 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5331
5332 .shm_alloc_security = selinux_shm_alloc_security,
5333 .shm_free_security = selinux_shm_free_security,
5334 .shm_associate = selinux_shm_associate,
5335 .shm_shmctl = selinux_shm_shmctl,
5336 .shm_shmat = selinux_shm_shmat,
5337
5338 .sem_alloc_security = selinux_sem_alloc_security,
5339 .sem_free_security = selinux_sem_free_security,
5340 .sem_associate = selinux_sem_associate,
5341 .sem_semctl = selinux_sem_semctl,
5342 .sem_semop = selinux_sem_semop,
5343
5344 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
5346 .d_instantiate = selinux_d_instantiate,
5347
5348 .getprocattr = selinux_getprocattr,
5349 .setprocattr = selinux_setprocattr,
5350
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005351 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005352 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005353 .release_secctx = selinux_release_secctx,
5354
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355 .unix_stream_connect = selinux_socket_unix_stream_connect,
5356 .unix_may_send = selinux_socket_unix_may_send,
5357
5358 .socket_create = selinux_socket_create,
5359 .socket_post_create = selinux_socket_post_create,
5360 .socket_bind = selinux_socket_bind,
5361 .socket_connect = selinux_socket_connect,
5362 .socket_listen = selinux_socket_listen,
5363 .socket_accept = selinux_socket_accept,
5364 .socket_sendmsg = selinux_socket_sendmsg,
5365 .socket_recvmsg = selinux_socket_recvmsg,
5366 .socket_getsockname = selinux_socket_getsockname,
5367 .socket_getpeername = selinux_socket_getpeername,
5368 .socket_getsockopt = selinux_socket_getsockopt,
5369 .socket_setsockopt = selinux_socket_setsockopt,
5370 .socket_shutdown = selinux_socket_shutdown,
5371 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005372 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5373 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 .sk_alloc_security = selinux_sk_alloc_security,
5375 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005376 .sk_clone_security = selinux_sk_clone_security,
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005377 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005378 .sock_graft = selinux_sock_graft,
5379 .inet_conn_request = selinux_inet_conn_request,
5380 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005381 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005382 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005383
5384#ifdef CONFIG_SECURITY_NETWORK_XFRM
5385 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5386 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5387 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005388 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005389 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5390 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005391 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005392 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005393 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005394 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005396
5397#ifdef CONFIG_KEYS
5398 .key_alloc = selinux_key_alloc,
5399 .key_free = selinux_key_free,
5400 .key_permission = selinux_key_permission,
5401#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402};
5403
5404static __init int selinux_init(void)
5405{
5406 struct task_security_struct *tsec;
5407
5408 if (!selinux_enabled) {
5409 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5410 return 0;
5411 }
5412
5413 printk(KERN_INFO "SELinux: Initializing.\n");
5414
5415 /* Set the security state for the initial task. */
5416 if (task_alloc_security(current))
5417 panic("SELinux: Failed to initialize initial task.\n");
5418 tsec = current->security;
5419 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5420
James Morris7cae7e22006-03-22 00:09:22 -08005421 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5422 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005423 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424 avc_init();
5425
5426 original_ops = secondary_ops = security_ops;
5427 if (!secondary_ops)
5428 panic ("SELinux: No initial security operations\n");
5429 if (register_security (&selinux_ops))
5430 panic("SELinux: Unable to register with kernel.\n");
5431
5432 if (selinux_enforcing) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005433 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 } else {
Eric Parisfadcdb42007-02-22 18:11:31 -05005435 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436 }
Michael LeMayd7200242006-06-22 14:47:17 -07005437
5438#ifdef CONFIG_KEYS
5439 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005440 selinux_key_alloc(&root_user_keyring, current,
5441 KEY_ALLOC_NOT_IN_QUOTA);
5442 selinux_key_alloc(&root_session_keyring, current,
5443 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005444#endif
5445
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 return 0;
5447}
5448
5449void selinux_complete_init(void)
5450{
Eric Parisfadcdb42007-02-22 18:11:31 -05005451 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452
5453 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005454 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005455 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456 spin_lock(&sb_security_lock);
5457next_sb:
5458 if (!list_empty(&superblock_security_head)) {
5459 struct superblock_security_struct *sbsec =
5460 list_entry(superblock_security_head.next,
5461 struct superblock_security_struct,
5462 list);
5463 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005466 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467 down_read(&sb->s_umount);
5468 if (sb->s_root)
5469 superblock_doinit(sb, NULL);
5470 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005471 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472 spin_lock(&sb_security_lock);
5473 list_del_init(&sbsec->list);
5474 goto next_sb;
5475 }
5476 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005477 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478}
5479
5480/* SELinux requires early initialization in order to label
5481 all processes and objects when they are created. */
5482security_initcall(selinux_init);
5483
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005484#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005485
Paul Mooreeffad8d2008-01-29 08:49:27 -05005486static struct nf_hook_ops selinux_ipv4_ops[] = {
5487 {
5488 .hook = selinux_ipv4_postroute,
5489 .owner = THIS_MODULE,
5490 .pf = PF_INET,
5491 .hooknum = NF_INET_POST_ROUTING,
5492 .priority = NF_IP_PRI_SELINUX_LAST,
5493 },
5494 {
5495 .hook = selinux_ipv4_forward,
5496 .owner = THIS_MODULE,
5497 .pf = PF_INET,
5498 .hooknum = NF_INET_FORWARD,
5499 .priority = NF_IP_PRI_SELINUX_FIRST,
5500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501};
5502
5503#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5504
Paul Mooreeffad8d2008-01-29 08:49:27 -05005505static struct nf_hook_ops selinux_ipv6_ops[] = {
5506 {
5507 .hook = selinux_ipv6_postroute,
5508 .owner = THIS_MODULE,
5509 .pf = PF_INET6,
5510 .hooknum = NF_INET_POST_ROUTING,
5511 .priority = NF_IP6_PRI_SELINUX_LAST,
5512 },
5513 {
5514 .hook = selinux_ipv6_forward,
5515 .owner = THIS_MODULE,
5516 .pf = PF_INET6,
5517 .hooknum = NF_INET_FORWARD,
5518 .priority = NF_IP6_PRI_SELINUX_FIRST,
5519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520};
5521
5522#endif /* IPV6 */
5523
5524static int __init selinux_nf_ip_init(void)
5525{
5526 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005527 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528
5529 if (!selinux_enabled)
5530 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005531
5532 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5533
Paul Mooreeffad8d2008-01-29 08:49:27 -05005534 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5535 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5536 if (err)
5537 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5538 err);
5539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540
5541#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005542 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5543 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5544 if (err)
5545 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5546 err);
5547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005549
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550out:
5551 return err;
5552}
5553
5554__initcall(selinux_nf_ip_init);
5555
5556#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5557static void selinux_nf_ip_exit(void)
5558{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005559 u32 iter;
5560
Eric Parisfadcdb42007-02-22 18:11:31 -05005561 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562
Paul Mooreeffad8d2008-01-29 08:49:27 -05005563 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5564 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005566 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5567 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568#endif /* IPV6 */
5569}
5570#endif
5571
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005572#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
5574#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5575#define selinux_nf_ip_exit()
5576#endif
5577
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005578#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579
5580#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5581int selinux_disable(void)
5582{
5583 extern void exit_sel_fs(void);
5584 static int selinux_disabled = 0;
5585
5586 if (ss_initialized) {
5587 /* Not permitted after initial policy load. */
5588 return -EINVAL;
5589 }
5590
5591 if (selinux_disabled) {
5592 /* Only do this once. */
5593 return -EINVAL;
5594 }
5595
5596 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5597
5598 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005599 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600
5601 /* Reset security_ops to the secondary module, dummy or capability. */
5602 security_ops = secondary_ops;
5603
5604 /* Unregister netfilter hooks. */
5605 selinux_nf_ip_exit();
5606
5607 /* Unregister selinuxfs. */
5608 exit_sel_fs();
5609
5610 return 0;
5611}
5612#endif
5613
5614