blob: e5ed07510309edb0da10a151095cd3529bf41442 [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
1275/* Check whether a task is allowed to use a capability. */
1276static int task_has_capability(struct task_struct *tsk,
1277 int cap)
1278{
1279 struct task_security_struct *tsec;
1280 struct avc_audit_data ad;
1281
1282 tsec = tsk->security;
1283
1284 AVC_AUDIT_DATA_INIT(&ad,CAP);
1285 ad.tsk = tsk;
1286 ad.u.cap = cap;
1287
1288 return avc_has_perm(tsec->sid, tsec->sid,
1289 SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
1290}
1291
1292/* Check whether a task is allowed to use a system operation. */
1293static int task_has_system(struct task_struct *tsk,
1294 u32 perms)
1295{
1296 struct task_security_struct *tsec;
1297
1298 tsec = tsk->security;
1299
1300 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1301 SECCLASS_SYSTEM, perms, NULL);
1302}
1303
1304/* Check whether a task has a particular permission to an inode.
1305 The 'adp' parameter is optional and allows other audit
1306 data to be passed (e.g. the dentry). */
1307static int inode_has_perm(struct task_struct *tsk,
1308 struct inode *inode,
1309 u32 perms,
1310 struct avc_audit_data *adp)
1311{
1312 struct task_security_struct *tsec;
1313 struct inode_security_struct *isec;
1314 struct avc_audit_data ad;
1315
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001316 if (unlikely (IS_PRIVATE (inode)))
1317 return 0;
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 tsec = tsk->security;
1320 isec = inode->i_security;
1321
1322 if (!adp) {
1323 adp = &ad;
1324 AVC_AUDIT_DATA_INIT(&ad, FS);
1325 ad.u.fs.inode = inode;
1326 }
1327
1328 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1329}
1330
1331/* Same as inode_has_perm, but pass explicit audit data containing
1332 the dentry to help the auditing code to more easily generate the
1333 pathname if needed. */
1334static inline int dentry_has_perm(struct task_struct *tsk,
1335 struct vfsmount *mnt,
1336 struct dentry *dentry,
1337 u32 av)
1338{
1339 struct inode *inode = dentry->d_inode;
1340 struct avc_audit_data ad;
1341 AVC_AUDIT_DATA_INIT(&ad,FS);
1342 ad.u.fs.mnt = mnt;
1343 ad.u.fs.dentry = dentry;
1344 return inode_has_perm(tsk, inode, av, &ad);
1345}
1346
1347/* Check whether a task can use an open file descriptor to
1348 access an inode in a given way. Check access to the
1349 descriptor itself, and then use dentry_has_perm to
1350 check a particular permission to the file.
1351 Access to the descriptor is implicitly granted if it
1352 has the same SID as the process. If av is zero, then
1353 access to the file is not checked, e.g. for cases
1354 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001355static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 struct file *file,
1357 u32 av)
1358{
1359 struct task_security_struct *tsec = tsk->security;
1360 struct file_security_struct *fsec = file->f_security;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001361 struct vfsmount *mnt = file->f_path.mnt;
1362 struct dentry *dentry = file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 struct inode *inode = dentry->d_inode;
1364 struct avc_audit_data ad;
1365 int rc;
1366
1367 AVC_AUDIT_DATA_INIT(&ad, FS);
1368 ad.u.fs.mnt = mnt;
1369 ad.u.fs.dentry = dentry;
1370
1371 if (tsec->sid != fsec->sid) {
1372 rc = avc_has_perm(tsec->sid, fsec->sid,
1373 SECCLASS_FD,
1374 FD__USE,
1375 &ad);
1376 if (rc)
1377 return rc;
1378 }
1379
1380 /* av is zero if only checking access to the descriptor. */
1381 if (av)
1382 return inode_has_perm(tsk, inode, av, &ad);
1383
1384 return 0;
1385}
1386
1387/* Check whether a task can create a file. */
1388static int may_create(struct inode *dir,
1389 struct dentry *dentry,
1390 u16 tclass)
1391{
1392 struct task_security_struct *tsec;
1393 struct inode_security_struct *dsec;
1394 struct superblock_security_struct *sbsec;
1395 u32 newsid;
1396 struct avc_audit_data ad;
1397 int rc;
1398
1399 tsec = current->security;
1400 dsec = dir->i_security;
1401 sbsec = dir->i_sb->s_security;
1402
1403 AVC_AUDIT_DATA_INIT(&ad, FS);
1404 ad.u.fs.dentry = dentry;
1405
1406 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1407 DIR__ADD_NAME | DIR__SEARCH,
1408 &ad);
1409 if (rc)
1410 return rc;
1411
1412 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1413 newsid = tsec->create_sid;
1414 } else {
1415 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1416 &newsid);
1417 if (rc)
1418 return rc;
1419 }
1420
1421 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1422 if (rc)
1423 return rc;
1424
1425 return avc_has_perm(newsid, sbsec->sid,
1426 SECCLASS_FILESYSTEM,
1427 FILESYSTEM__ASSOCIATE, &ad);
1428}
1429
Michael LeMay4eb582c2006-06-26 00:24:57 -07001430/* Check whether a task can create a key. */
1431static int may_create_key(u32 ksid,
1432 struct task_struct *ctx)
1433{
1434 struct task_security_struct *tsec;
1435
1436 tsec = ctx->security;
1437
1438 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1439}
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441#define MAY_LINK 0
1442#define MAY_UNLINK 1
1443#define MAY_RMDIR 2
1444
1445/* Check whether a task can link, unlink, or rmdir a file/directory. */
1446static int may_link(struct inode *dir,
1447 struct dentry *dentry,
1448 int kind)
1449
1450{
1451 struct task_security_struct *tsec;
1452 struct inode_security_struct *dsec, *isec;
1453 struct avc_audit_data ad;
1454 u32 av;
1455 int rc;
1456
1457 tsec = current->security;
1458 dsec = dir->i_security;
1459 isec = dentry->d_inode->i_security;
1460
1461 AVC_AUDIT_DATA_INIT(&ad, FS);
1462 ad.u.fs.dentry = dentry;
1463
1464 av = DIR__SEARCH;
1465 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1466 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1467 if (rc)
1468 return rc;
1469
1470 switch (kind) {
1471 case MAY_LINK:
1472 av = FILE__LINK;
1473 break;
1474 case MAY_UNLINK:
1475 av = FILE__UNLINK;
1476 break;
1477 case MAY_RMDIR:
1478 av = DIR__RMDIR;
1479 break;
1480 default:
1481 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1482 return 0;
1483 }
1484
1485 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1486 return rc;
1487}
1488
1489static inline int may_rename(struct inode *old_dir,
1490 struct dentry *old_dentry,
1491 struct inode *new_dir,
1492 struct dentry *new_dentry)
1493{
1494 struct task_security_struct *tsec;
1495 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1496 struct avc_audit_data ad;
1497 u32 av;
1498 int old_is_dir, new_is_dir;
1499 int rc;
1500
1501 tsec = current->security;
1502 old_dsec = old_dir->i_security;
1503 old_isec = old_dentry->d_inode->i_security;
1504 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1505 new_dsec = new_dir->i_security;
1506
1507 AVC_AUDIT_DATA_INIT(&ad, FS);
1508
1509 ad.u.fs.dentry = old_dentry;
1510 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1511 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1512 if (rc)
1513 return rc;
1514 rc = avc_has_perm(tsec->sid, old_isec->sid,
1515 old_isec->sclass, FILE__RENAME, &ad);
1516 if (rc)
1517 return rc;
1518 if (old_is_dir && new_dir != old_dir) {
1519 rc = avc_has_perm(tsec->sid, old_isec->sid,
1520 old_isec->sclass, DIR__REPARENT, &ad);
1521 if (rc)
1522 return rc;
1523 }
1524
1525 ad.u.fs.dentry = new_dentry;
1526 av = DIR__ADD_NAME | DIR__SEARCH;
1527 if (new_dentry->d_inode)
1528 av |= DIR__REMOVE_NAME;
1529 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1530 if (rc)
1531 return rc;
1532 if (new_dentry->d_inode) {
1533 new_isec = new_dentry->d_inode->i_security;
1534 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1535 rc = avc_has_perm(tsec->sid, new_isec->sid,
1536 new_isec->sclass,
1537 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1538 if (rc)
1539 return rc;
1540 }
1541
1542 return 0;
1543}
1544
1545/* Check whether a task can perform a filesystem operation. */
1546static int superblock_has_perm(struct task_struct *tsk,
1547 struct super_block *sb,
1548 u32 perms,
1549 struct avc_audit_data *ad)
1550{
1551 struct task_security_struct *tsec;
1552 struct superblock_security_struct *sbsec;
1553
1554 tsec = tsk->security;
1555 sbsec = sb->s_security;
1556 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1557 perms, ad);
1558}
1559
1560/* Convert a Linux mode and permission mask to an access vector. */
1561static inline u32 file_mask_to_av(int mode, int mask)
1562{
1563 u32 av = 0;
1564
1565 if ((mode & S_IFMT) != S_IFDIR) {
1566 if (mask & MAY_EXEC)
1567 av |= FILE__EXECUTE;
1568 if (mask & MAY_READ)
1569 av |= FILE__READ;
1570
1571 if (mask & MAY_APPEND)
1572 av |= FILE__APPEND;
1573 else if (mask & MAY_WRITE)
1574 av |= FILE__WRITE;
1575
1576 } else {
1577 if (mask & MAY_EXEC)
1578 av |= DIR__SEARCH;
1579 if (mask & MAY_WRITE)
1580 av |= DIR__WRITE;
1581 if (mask & MAY_READ)
1582 av |= DIR__READ;
1583 }
1584
1585 return av;
1586}
1587
1588/* Convert a Linux file to an access vector. */
1589static inline u32 file_to_av(struct file *file)
1590{
1591 u32 av = 0;
1592
1593 if (file->f_mode & FMODE_READ)
1594 av |= FILE__READ;
1595 if (file->f_mode & FMODE_WRITE) {
1596 if (file->f_flags & O_APPEND)
1597 av |= FILE__APPEND;
1598 else
1599 av |= FILE__WRITE;
1600 }
1601
1602 return av;
1603}
1604
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605/* Hook functions begin here. */
1606
1607static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1608{
1609 struct task_security_struct *psec = parent->security;
1610 struct task_security_struct *csec = child->security;
1611 int rc;
1612
1613 rc = secondary_ops->ptrace(parent,child);
1614 if (rc)
1615 return rc;
1616
1617 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1618 /* Save the SID of the tracing process for later use in apply_creds. */
Stephen Smalley341c2d82006-03-11 03:27:16 -08001619 if (!(child->ptrace & PT_PTRACED) && !rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 csec->ptrace_sid = psec->sid;
1621 return rc;
1622}
1623
1624static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1625 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1626{
1627 int error;
1628
1629 error = task_has_perm(current, target, PROCESS__GETCAP);
1630 if (error)
1631 return error;
1632
1633 return secondary_ops->capget(target, effective, inheritable, permitted);
1634}
1635
1636static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1637 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1638{
1639 int error;
1640
1641 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1642 if (error)
1643 return error;
1644
1645 return task_has_perm(current, target, PROCESS__SETCAP);
1646}
1647
1648static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1649 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1650{
1651 secondary_ops->capset_set(target, effective, inheritable, permitted);
1652}
1653
1654static int selinux_capable(struct task_struct *tsk, int cap)
1655{
1656 int rc;
1657
1658 rc = secondary_ops->capable(tsk, cap);
1659 if (rc)
1660 return rc;
1661
1662 return task_has_capability(tsk,cap);
1663}
1664
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001665static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1666{
1667 int buflen, rc;
1668 char *buffer, *path, *end;
1669
1670 rc = -ENOMEM;
1671 buffer = (char*)__get_free_page(GFP_KERNEL);
1672 if (!buffer)
1673 goto out;
1674
1675 buflen = PAGE_SIZE;
1676 end = buffer+buflen;
1677 *--end = '\0';
1678 buflen--;
1679 path = end-1;
1680 *path = '/';
1681 while (table) {
1682 const char *name = table->procname;
1683 size_t namelen = strlen(name);
1684 buflen -= namelen + 1;
1685 if (buflen < 0)
1686 goto out_free;
1687 end -= namelen;
1688 memcpy(end, name, namelen);
1689 *--end = '/';
1690 path = end;
1691 table = table->parent;
1692 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001693 buflen -= 4;
1694 if (buflen < 0)
1695 goto out_free;
1696 end -= 4;
1697 memcpy(end, "/sys", 4);
1698 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001699 rc = security_genfs_sid("proc", path, tclass, sid);
1700out_free:
1701 free_page((unsigned long)buffer);
1702out:
1703 return rc;
1704}
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706static int selinux_sysctl(ctl_table *table, int op)
1707{
1708 int error = 0;
1709 u32 av;
1710 struct task_security_struct *tsec;
1711 u32 tsid;
1712 int rc;
1713
1714 rc = secondary_ops->sysctl(table, op);
1715 if (rc)
1716 return rc;
1717
1718 tsec = current->security;
1719
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001720 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1721 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 if (rc) {
1723 /* Default to the well-defined sysctl SID. */
1724 tsid = SECINITSID_SYSCTL;
1725 }
1726
1727 /* The op values are "defined" in sysctl.c, thereby creating
1728 * a bad coupling between this module and sysctl.c */
1729 if(op == 001) {
1730 error = avc_has_perm(tsec->sid, tsid,
1731 SECCLASS_DIR, DIR__SEARCH, NULL);
1732 } else {
1733 av = 0;
1734 if (op & 004)
1735 av |= FILE__READ;
1736 if (op & 002)
1737 av |= FILE__WRITE;
1738 if (av)
1739 error = avc_has_perm(tsec->sid, tsid,
1740 SECCLASS_FILE, av, NULL);
1741 }
1742
1743 return error;
1744}
1745
1746static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1747{
1748 int rc = 0;
1749
1750 if (!sb)
1751 return 0;
1752
1753 switch (cmds) {
1754 case Q_SYNC:
1755 case Q_QUOTAON:
1756 case Q_QUOTAOFF:
1757 case Q_SETINFO:
1758 case Q_SETQUOTA:
1759 rc = superblock_has_perm(current,
1760 sb,
1761 FILESYSTEM__QUOTAMOD, NULL);
1762 break;
1763 case Q_GETFMT:
1764 case Q_GETINFO:
1765 case Q_GETQUOTA:
1766 rc = superblock_has_perm(current,
1767 sb,
1768 FILESYSTEM__QUOTAGET, NULL);
1769 break;
1770 default:
1771 rc = 0; /* let the kernel handle invalid cmds */
1772 break;
1773 }
1774 return rc;
1775}
1776
1777static int selinux_quota_on(struct dentry *dentry)
1778{
1779 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1780}
1781
1782static int selinux_syslog(int type)
1783{
1784 int rc;
1785
1786 rc = secondary_ops->syslog(type);
1787 if (rc)
1788 return rc;
1789
1790 switch (type) {
1791 case 3: /* Read last kernel messages */
1792 case 10: /* Return size of the log buffer */
1793 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1794 break;
1795 case 6: /* Disable logging to console */
1796 case 7: /* Enable logging to console */
1797 case 8: /* Set level of messages printed to console */
1798 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1799 break;
1800 case 0: /* Close log */
1801 case 1: /* Open log */
1802 case 2: /* Read from log */
1803 case 4: /* Read/clear last kernel messages */
1804 case 5: /* Clear ring buffer */
1805 default:
1806 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1807 break;
1808 }
1809 return rc;
1810}
1811
1812/*
1813 * Check that a process has enough memory to allocate a new virtual
1814 * mapping. 0 means there is enough memory for the allocation to
1815 * succeed and -ENOMEM implies there is not.
1816 *
1817 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1818 * if the capability is granted, but __vm_enough_memory requires 1 if
1819 * the capability is granted.
1820 *
1821 * Do not audit the selinux permission check, as this is applied to all
1822 * processes that allocate mappings.
1823 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001824static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
1826 int rc, cap_sys_admin = 0;
1827 struct task_security_struct *tsec = current->security;
1828
1829 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1830 if (rc == 0)
1831 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001832 SECCLASS_CAPABILITY,
1833 CAP_TO_MASK(CAP_SYS_ADMIN),
1834 0,
1835 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 if (rc == 0)
1838 cap_sys_admin = 1;
1839
Alan Cox34b4e4a2007-08-22 14:01:28 -07001840 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841}
1842
1843/* binprm security operations */
1844
1845static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1846{
1847 struct bprm_security_struct *bsec;
1848
James Morris89d155e2005-10-30 14:59:21 -08001849 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 if (!bsec)
1851 return -ENOMEM;
1852
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 bsec->bprm = bprm;
1854 bsec->sid = SECINITSID_UNLABELED;
1855 bsec->set = 0;
1856
1857 bprm->security = bsec;
1858 return 0;
1859}
1860
1861static int selinux_bprm_set_security(struct linux_binprm *bprm)
1862{
1863 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001864 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 struct inode_security_struct *isec;
1866 struct bprm_security_struct *bsec;
1867 u32 newsid;
1868 struct avc_audit_data ad;
1869 int rc;
1870
1871 rc = secondary_ops->bprm_set_security(bprm);
1872 if (rc)
1873 return rc;
1874
1875 bsec = bprm->security;
1876
1877 if (bsec->set)
1878 return 0;
1879
1880 tsec = current->security;
1881 isec = inode->i_security;
1882
1883 /* Default to the current task SID. */
1884 bsec->sid = tsec->sid;
1885
Michael LeMay28eba5b2006-06-27 02:53:42 -07001886 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001888 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001889 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
1891 if (tsec->exec_sid) {
1892 newsid = tsec->exec_sid;
1893 /* Reset exec SID on execve. */
1894 tsec->exec_sid = 0;
1895 } else {
1896 /* Check for a default transition on this program. */
1897 rc = security_transition_sid(tsec->sid, isec->sid,
1898 SECCLASS_PROCESS, &newsid);
1899 if (rc)
1900 return rc;
1901 }
1902
1903 AVC_AUDIT_DATA_INIT(&ad, FS);
Josef Sipek3d5ff522006-12-08 02:37:38 -08001904 ad.u.fs.mnt = bprm->file->f_path.mnt;
1905 ad.u.fs.dentry = bprm->file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Josef Sipek3d5ff522006-12-08 02:37:38 -08001907 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 newsid = tsec->sid;
1909
1910 if (tsec->sid == newsid) {
1911 rc = avc_has_perm(tsec->sid, isec->sid,
1912 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1913 if (rc)
1914 return rc;
1915 } else {
1916 /* Check permissions for the transition. */
1917 rc = avc_has_perm(tsec->sid, newsid,
1918 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1919 if (rc)
1920 return rc;
1921
1922 rc = avc_has_perm(newsid, isec->sid,
1923 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1924 if (rc)
1925 return rc;
1926
1927 /* Clear any possibly unsafe personality bits on exec: */
1928 current->personality &= ~PER_CLEAR_ON_SETID;
1929
1930 /* Set the security field to the new SID. */
1931 bsec->sid = newsid;
1932 }
1933
1934 bsec->set = 1;
1935 return 0;
1936}
1937
1938static int selinux_bprm_check_security (struct linux_binprm *bprm)
1939{
1940 return secondary_ops->bprm_check_security(bprm);
1941}
1942
1943
1944static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1945{
1946 struct task_security_struct *tsec = current->security;
1947 int atsecure = 0;
1948
1949 if (tsec->osid != tsec->sid) {
1950 /* Enable secure mode for SIDs transitions unless
1951 the noatsecure permission is granted between
1952 the two SIDs, i.e. ahp returns 0. */
1953 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1954 SECCLASS_PROCESS,
1955 PROCESS__NOATSECURE, NULL);
1956 }
1957
1958 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1959}
1960
1961static void selinux_bprm_free_security(struct linux_binprm *bprm)
1962{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07001963 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965}
1966
1967extern struct vfsmount *selinuxfs_mount;
1968extern struct dentry *selinux_null;
1969
1970/* Derived from fs/exec.c:flush_old_files. */
1971static inline void flush_unauthorized_files(struct files_struct * files)
1972{
1973 struct avc_audit_data ad;
1974 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001975 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07001976 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001978 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001980 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001981 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 if (tty) {
1983 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08001984 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 if (file) {
1986 /* Revalidate access to controlling tty.
1987 Use inode_has_perm on the tty inode directly rather
1988 than using file_has_perm, as this particular open
1989 file may belong to another process and we are only
1990 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08001991 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 if (inode_has_perm(current, inode,
1993 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001994 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
1996 }
1997 file_list_unlock();
1998 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001999 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002000 /* Reset controlling tty. */
2001 if (drop_tty)
2002 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
2004 /* Revalidate access to inherited open files. */
2005
2006 AVC_AUDIT_DATA_INIT(&ad,FS);
2007
2008 spin_lock(&files->file_lock);
2009 for (;;) {
2010 unsigned long set, i;
2011 int fd;
2012
2013 j++;
2014 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002015 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002016 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002018 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 if (!set)
2020 continue;
2021 spin_unlock(&files->file_lock);
2022 for ( ; set ; i++,set >>= 1) {
2023 if (set & 1) {
2024 file = fget(i);
2025 if (!file)
2026 continue;
2027 if (file_has_perm(current,
2028 file,
2029 file_to_av(file))) {
2030 sys_close(i);
2031 fd = get_unused_fd();
2032 if (fd != i) {
2033 if (fd >= 0)
2034 put_unused_fd(fd);
2035 fput(file);
2036 continue;
2037 }
2038 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002039 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 } else {
2041 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002042 if (IS_ERR(devnull)) {
2043 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 put_unused_fd(fd);
2045 fput(file);
2046 continue;
2047 }
2048 }
2049 fd_install(fd, devnull);
2050 }
2051 fput(file);
2052 }
2053 }
2054 spin_lock(&files->file_lock);
2055
2056 }
2057 spin_unlock(&files->file_lock);
2058}
2059
2060static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2061{
2062 struct task_security_struct *tsec;
2063 struct bprm_security_struct *bsec;
2064 u32 sid;
2065 int rc;
2066
2067 secondary_ops->bprm_apply_creds(bprm, unsafe);
2068
2069 tsec = current->security;
2070
2071 bsec = bprm->security;
2072 sid = bsec->sid;
2073
2074 tsec->osid = tsec->sid;
2075 bsec->unsafe = 0;
2076 if (tsec->sid != sid) {
2077 /* Check for shared state. If not ok, leave SID
2078 unchanged and kill. */
2079 if (unsafe & LSM_UNSAFE_SHARE) {
2080 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2081 PROCESS__SHARE, NULL);
2082 if (rc) {
2083 bsec->unsafe = 1;
2084 return;
2085 }
2086 }
2087
2088 /* Check for ptracing, and update the task SID if ok.
2089 Otherwise, leave SID unchanged and kill. */
2090 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2091 rc = avc_has_perm(tsec->ptrace_sid, sid,
2092 SECCLASS_PROCESS, PROCESS__PTRACE,
2093 NULL);
2094 if (rc) {
2095 bsec->unsafe = 1;
2096 return;
2097 }
2098 }
2099 tsec->sid = sid;
2100 }
2101}
2102
2103/*
2104 * called after apply_creds without the task lock held
2105 */
2106static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2107{
2108 struct task_security_struct *tsec;
2109 struct rlimit *rlim, *initrlim;
2110 struct itimerval itimer;
2111 struct bprm_security_struct *bsec;
2112 int rc, i;
2113
2114 tsec = current->security;
2115 bsec = bprm->security;
2116
2117 if (bsec->unsafe) {
2118 force_sig_specific(SIGKILL, current);
2119 return;
2120 }
2121 if (tsec->osid == tsec->sid)
2122 return;
2123
2124 /* Close files for which the new task SID is not authorized. */
2125 flush_unauthorized_files(current->files);
2126
2127 /* Check whether the new SID can inherit signal state
2128 from the old SID. If not, clear itimers to avoid
2129 subsequent signal generation and flush and unblock
2130 signals. This must occur _after_ the task SID has
2131 been updated so that any kill done after the flush
2132 will be checked against the new SID. */
2133 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2134 PROCESS__SIGINH, NULL);
2135 if (rc) {
2136 memset(&itimer, 0, sizeof itimer);
2137 for (i = 0; i < 3; i++)
2138 do_setitimer(i, &itimer, NULL);
2139 flush_signals(current);
2140 spin_lock_irq(&current->sighand->siglock);
2141 flush_signal_handlers(current, 1);
2142 sigemptyset(&current->blocked);
2143 recalc_sigpending();
2144 spin_unlock_irq(&current->sighand->siglock);
2145 }
2146
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002147 /* Always clear parent death signal on SID transitions. */
2148 current->pdeath_signal = 0;
2149
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 /* Check whether the new SID can inherit resource limits
2151 from the old SID. If not, reset all soft limits to
2152 the lower of the current task's hard limit and the init
2153 task's soft limit. Note that the setting of hard limits
2154 (even to lower them) can be controlled by the setrlimit
2155 check. The inclusion of the init task's soft limit into
2156 the computation is to avoid resetting soft limits higher
2157 than the default soft limit for cases where the default
2158 is lower than the hard limit, e.g. RLIMIT_CORE or
2159 RLIMIT_STACK.*/
2160 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2161 PROCESS__RLIMITINH, NULL);
2162 if (rc) {
2163 for (i = 0; i < RLIM_NLIMITS; i++) {
2164 rlim = current->signal->rlim + i;
2165 initrlim = init_task.signal->rlim+i;
2166 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
2167 }
2168 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2169 /*
2170 * This will cause RLIMIT_CPU calculations
2171 * to be refigured.
2172 */
2173 current->it_prof_expires = jiffies_to_cputime(1);
2174 }
2175 }
2176
2177 /* Wake up the parent if it is waiting so that it can
2178 recheck wait permission to the new task SID. */
2179 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2180}
2181
2182/* superblock security operations */
2183
2184static int selinux_sb_alloc_security(struct super_block *sb)
2185{
2186 return superblock_alloc_security(sb);
2187}
2188
2189static void selinux_sb_free_security(struct super_block *sb)
2190{
2191 superblock_free_security(sb);
2192}
2193
2194static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2195{
2196 if (plen > olen)
2197 return 0;
2198
2199 return !memcmp(prefix, option, plen);
2200}
2201
2202static inline int selinux_option(char *option, int len)
2203{
2204 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
2205 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
Eric Paris08089252006-07-10 04:43:55 -07002206 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
2207 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208}
2209
2210static inline void take_option(char **to, char *from, int *first, int len)
2211{
2212 if (!*first) {
2213 **to = ',';
2214 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002215 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 *first = 0;
2217 memcpy(*to, from, len);
2218 *to += len;
2219}
2220
Cory Olmo3528a952006-09-29 01:58:44 -07002221static inline void take_selinux_option(char **to, char *from, int *first,
2222 int len)
2223{
2224 int current_size = 0;
2225
2226 if (!*first) {
2227 **to = '|';
2228 *to += 1;
2229 }
2230 else
2231 *first = 0;
2232
2233 while (current_size < len) {
2234 if (*from != '"') {
2235 **to = *from;
2236 *to += 1;
2237 }
2238 from += 1;
2239 current_size += 1;
2240 }
2241}
2242
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
2244{
2245 int fnosec, fsec, rc = 0;
2246 char *in_save, *in_curr, *in_end;
2247 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002248 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250 in_curr = orig;
2251 sec_curr = copy;
2252
2253 /* Binary mount data: just copy */
2254 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2255 copy_page(sec_curr, in_curr);
2256 goto out;
2257 }
2258
2259 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2260 if (!nosec) {
2261 rc = -ENOMEM;
2262 goto out;
2263 }
2264
2265 nosec_save = nosec;
2266 fnosec = fsec = 1;
2267 in_save = in_end = orig;
2268
2269 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002270 if (*in_end == '"')
2271 open_quote = !open_quote;
2272 if ((*in_end == ',' && open_quote == 0) ||
2273 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 int len = in_end - in_curr;
2275
2276 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002277 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 else
2279 take_option(&nosec, in_curr, &fnosec, len);
2280
2281 in_curr = in_end + 1;
2282 }
2283 } while (*in_end++);
2284
Eric Paris6931dfc2005-06-30 02:58:51 -07002285 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002286 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287out:
2288 return rc;
2289}
2290
2291static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2292{
2293 struct avc_audit_data ad;
2294 int rc;
2295
2296 rc = superblock_doinit(sb, data);
2297 if (rc)
2298 return rc;
2299
2300 AVC_AUDIT_DATA_INIT(&ad,FS);
2301 ad.u.fs.dentry = sb->s_root;
2302 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2303}
2304
David Howells726c3342006-06-23 02:02:58 -07002305static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306{
2307 struct avc_audit_data ad;
2308
2309 AVC_AUDIT_DATA_INIT(&ad,FS);
David Howells726c3342006-06-23 02:02:58 -07002310 ad.u.fs.dentry = dentry->d_sb->s_root;
2311 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312}
2313
2314static int selinux_mount(char * dev_name,
2315 struct nameidata *nd,
2316 char * type,
2317 unsigned long flags,
2318 void * data)
2319{
2320 int rc;
2321
2322 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2323 if (rc)
2324 return rc;
2325
2326 if (flags & MS_REMOUNT)
2327 return superblock_has_perm(current, nd->mnt->mnt_sb,
2328 FILESYSTEM__REMOUNT, NULL);
2329 else
2330 return dentry_has_perm(current, nd->mnt, nd->dentry,
2331 FILE__MOUNTON);
2332}
2333
2334static int selinux_umount(struct vfsmount *mnt, int flags)
2335{
2336 int rc;
2337
2338 rc = secondary_ops->sb_umount(mnt, flags);
2339 if (rc)
2340 return rc;
2341
2342 return superblock_has_perm(current,mnt->mnt_sb,
2343 FILESYSTEM__UNMOUNT,NULL);
2344}
2345
2346/* inode security operations */
2347
2348static int selinux_inode_alloc_security(struct inode *inode)
2349{
2350 return inode_alloc_security(inode);
2351}
2352
2353static void selinux_inode_free_security(struct inode *inode)
2354{
2355 inode_free_security(inode);
2356}
2357
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002358static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2359 char **name, void **value,
2360 size_t *len)
2361{
2362 struct task_security_struct *tsec;
2363 struct inode_security_struct *dsec;
2364 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002365 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002366 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002367 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002368
2369 tsec = current->security;
2370 dsec = dir->i_security;
2371 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002372
2373 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2374 newsid = tsec->create_sid;
2375 } else {
2376 rc = security_transition_sid(tsec->sid, dsec->sid,
2377 inode_mode_to_security_class(inode->i_mode),
2378 &newsid);
2379 if (rc) {
2380 printk(KERN_WARNING "%s: "
2381 "security_transition_sid failed, rc=%d (dev=%s "
2382 "ino=%ld)\n",
2383 __FUNCTION__,
2384 -rc, inode->i_sb->s_id, inode->i_ino);
2385 return rc;
2386 }
2387 }
2388
Eric Paris296fddf2006-09-25 23:32:00 -07002389 /* Possibly defer initialization to selinux_complete_init. */
2390 if (sbsec->initialized) {
2391 struct inode_security_struct *isec = inode->i_security;
2392 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2393 isec->sid = newsid;
2394 isec->initialized = 1;
2395 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002396
Stephen Smalley8aad3872006-03-22 00:09:13 -08002397 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002398 return -EOPNOTSUPP;
2399
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002400 if (name) {
2401 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
2402 if (!namep)
2403 return -ENOMEM;
2404 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002405 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002406
2407 if (value && len) {
2408 rc = security_sid_to_context(newsid, &context, &clen);
2409 if (rc) {
2410 kfree(namep);
2411 return rc;
2412 }
2413 *value = context;
2414 *len = clen;
2415 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002416
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002417 return 0;
2418}
2419
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2421{
2422 return may_create(dir, dentry, SECCLASS_FILE);
2423}
2424
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2426{
2427 int rc;
2428
2429 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2430 if (rc)
2431 return rc;
2432 return may_link(dir, old_dentry, MAY_LINK);
2433}
2434
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2436{
2437 int rc;
2438
2439 rc = secondary_ops->inode_unlink(dir, dentry);
2440 if (rc)
2441 return rc;
2442 return may_link(dir, dentry, MAY_UNLINK);
2443}
2444
2445static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2446{
2447 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2448}
2449
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2451{
2452 return may_create(dir, dentry, SECCLASS_DIR);
2453}
2454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2456{
2457 return may_link(dir, dentry, MAY_RMDIR);
2458}
2459
2460static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2461{
2462 int rc;
2463
2464 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2465 if (rc)
2466 return rc;
2467
2468 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2469}
2470
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2472 struct inode *new_inode, struct dentry *new_dentry)
2473{
2474 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2475}
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477static int selinux_inode_readlink(struct dentry *dentry)
2478{
2479 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2480}
2481
2482static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2483{
2484 int rc;
2485
2486 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2487 if (rc)
2488 return rc;
2489 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2490}
2491
2492static int selinux_inode_permission(struct inode *inode, int mask,
2493 struct nameidata *nd)
2494{
2495 int rc;
2496
2497 rc = secondary_ops->inode_permission(inode, mask, nd);
2498 if (rc)
2499 return rc;
2500
2501 if (!mask) {
2502 /* No permission to check. Existence test. */
2503 return 0;
2504 }
2505
2506 return inode_has_perm(current, inode,
2507 file_mask_to_av(inode->i_mode, mask), NULL);
2508}
2509
2510static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2511{
2512 int rc;
2513
2514 rc = secondary_ops->inode_setattr(dentry, iattr);
2515 if (rc)
2516 return rc;
2517
2518 if (iattr->ia_valid & ATTR_FORCE)
2519 return 0;
2520
2521 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2522 ATTR_ATIME_SET | ATTR_MTIME_SET))
2523 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2524
2525 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2526}
2527
2528static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2529{
2530 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2531}
2532
Serge E. Hallynb5376772007-10-16 23:31:36 -07002533static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2534{
2535 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2536 sizeof XATTR_SECURITY_PREFIX - 1)) {
2537 if (!strcmp(name, XATTR_NAME_CAPS)) {
2538 if (!capable(CAP_SETFCAP))
2539 return -EPERM;
2540 } else if (!capable(CAP_SYS_ADMIN)) {
2541 /* A different attribute in the security namespace.
2542 Restrict to administrator. */
2543 return -EPERM;
2544 }
2545 }
2546
2547 /* Not an attribute we recognize, so just check the
2548 ordinary setattr permission. */
2549 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2550}
2551
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2553{
2554 struct task_security_struct *tsec = current->security;
2555 struct inode *inode = dentry->d_inode;
2556 struct inode_security_struct *isec = inode->i_security;
2557 struct superblock_security_struct *sbsec;
2558 struct avc_audit_data ad;
2559 u32 newsid;
2560 int rc = 0;
2561
Serge E. Hallynb5376772007-10-16 23:31:36 -07002562 if (strcmp(name, XATTR_NAME_SELINUX))
2563 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
2565 sbsec = inode->i_sb->s_security;
2566 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2567 return -EOPNOTSUPP;
2568
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302569 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 return -EPERM;
2571
2572 AVC_AUDIT_DATA_INIT(&ad,FS);
2573 ad.u.fs.dentry = dentry;
2574
2575 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2576 FILE__RELABELFROM, &ad);
2577 if (rc)
2578 return rc;
2579
2580 rc = security_context_to_sid(value, size, &newsid);
2581 if (rc)
2582 return rc;
2583
2584 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2585 FILE__RELABELTO, &ad);
2586 if (rc)
2587 return rc;
2588
2589 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2590 isec->sclass);
2591 if (rc)
2592 return rc;
2593
2594 return avc_has_perm(newsid,
2595 sbsec->sid,
2596 SECCLASS_FILESYSTEM,
2597 FILESYSTEM__ASSOCIATE,
2598 &ad);
2599}
2600
2601static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2602 void *value, size_t size, int flags)
2603{
2604 struct inode *inode = dentry->d_inode;
2605 struct inode_security_struct *isec = inode->i_security;
2606 u32 newsid;
2607 int rc;
2608
2609 if (strcmp(name, XATTR_NAME_SELINUX)) {
2610 /* Not an attribute we recognize, so nothing to do. */
2611 return;
2612 }
2613
2614 rc = security_context_to_sid(value, size, &newsid);
2615 if (rc) {
2616 printk(KERN_WARNING "%s: unable to obtain SID for context "
2617 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2618 return;
2619 }
2620
2621 isec->sid = newsid;
2622 return;
2623}
2624
2625static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2626{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2628}
2629
2630static int selinux_inode_listxattr (struct dentry *dentry)
2631{
2632 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2633}
2634
2635static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2636{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002637 if (strcmp(name, XATTR_NAME_SELINUX))
2638 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
2640 /* No one is allowed to remove a SELinux security label.
2641 You can change the label, but all data must be labeled. */
2642 return -EACCES;
2643}
2644
James Morrisd381d8a2005-10-30 14:59:22 -08002645/*
2646 * Copy the in-core inode security context value to the user. If the
2647 * getxattr() prior to this succeeded, check to see if we need to
2648 * canonicalize the value to be finally returned to the user.
2649 *
2650 * Permission check is handled by selinux_inode_getxattr hook.
2651 */
David P. Quigley42492592008-02-04 22:29:39 -08002652static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653{
David P. Quigley42492592008-02-04 22:29:39 -08002654 u32 size;
2655 int error;
2656 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002659 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2660 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
David P. Quigley42492592008-02-04 22:29:39 -08002662 error = security_sid_to_context(isec->sid, &context, &size);
2663 if (error)
2664 return error;
2665 error = size;
2666 if (alloc) {
2667 *buffer = context;
2668 goto out_nofree;
2669 }
2670 kfree(context);
2671out_nofree:
2672 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673}
2674
2675static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2676 const void *value, size_t size, int flags)
2677{
2678 struct inode_security_struct *isec = inode->i_security;
2679 u32 newsid;
2680 int rc;
2681
2682 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2683 return -EOPNOTSUPP;
2684
2685 if (!value || !size)
2686 return -EACCES;
2687
2688 rc = security_context_to_sid((void*)value, size, &newsid);
2689 if (rc)
2690 return rc;
2691
2692 isec->sid = newsid;
2693 return 0;
2694}
2695
2696static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2697{
2698 const int len = sizeof(XATTR_NAME_SELINUX);
2699 if (buffer && len <= buffer_size)
2700 memcpy(buffer, XATTR_NAME_SELINUX, len);
2701 return len;
2702}
2703
Serge E. Hallynb5376772007-10-16 23:31:36 -07002704static int selinux_inode_need_killpriv(struct dentry *dentry)
2705{
2706 return secondary_ops->inode_need_killpriv(dentry);
2707}
2708
2709static int selinux_inode_killpriv(struct dentry *dentry)
2710{
2711 return secondary_ops->inode_killpriv(dentry);
2712}
2713
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714/* file security operations */
2715
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002716static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002718 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002719 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
2721 if (!mask) {
2722 /* No permission to check. Existence test. */
2723 return 0;
2724 }
2725
2726 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2727 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2728 mask |= MAY_APPEND;
2729
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002730 rc = file_has_perm(current, file,
2731 file_mask_to_av(inode->i_mode, mask));
2732 if (rc)
2733 return rc;
2734
2735 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736}
2737
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002738static int selinux_file_permission(struct file *file, int mask)
2739{
2740 struct inode *inode = file->f_path.dentry->d_inode;
2741 struct task_security_struct *tsec = current->security;
2742 struct file_security_struct *fsec = file->f_security;
2743 struct inode_security_struct *isec = inode->i_security;
2744
2745 if (!mask) {
2746 /* No permission to check. Existence test. */
2747 return 0;
2748 }
2749
2750 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2751 && fsec->pseqno == avc_policy_seqno())
2752 return selinux_netlbl_inode_permission(inode, mask);
2753
2754 return selinux_revalidate_file_permission(file, mask);
2755}
2756
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757static int selinux_file_alloc_security(struct file *file)
2758{
2759 return file_alloc_security(file);
2760}
2761
2762static void selinux_file_free_security(struct file *file)
2763{
2764 file_free_security(file);
2765}
2766
2767static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2768 unsigned long arg)
2769{
2770 int error = 0;
2771
2772 switch (cmd) {
2773 case FIONREAD:
2774 /* fall through */
2775 case FIBMAP:
2776 /* fall through */
2777 case FIGETBSZ:
2778 /* fall through */
2779 case EXT2_IOC_GETFLAGS:
2780 /* fall through */
2781 case EXT2_IOC_GETVERSION:
2782 error = file_has_perm(current, file, FILE__GETATTR);
2783 break;
2784
2785 case EXT2_IOC_SETFLAGS:
2786 /* fall through */
2787 case EXT2_IOC_SETVERSION:
2788 error = file_has_perm(current, file, FILE__SETATTR);
2789 break;
2790
2791 /* sys_ioctl() checks */
2792 case FIONBIO:
2793 /* fall through */
2794 case FIOASYNC:
2795 error = file_has_perm(current, file, 0);
2796 break;
2797
2798 case KDSKBENT:
2799 case KDSKBSENT:
2800 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2801 break;
2802
2803 /* default case assumes that the command will go
2804 * to the file's ioctl() function.
2805 */
2806 default:
2807 error = file_has_perm(current, file, FILE__IOCTL);
2808
2809 }
2810 return error;
2811}
2812
2813static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2814{
2815#ifndef CONFIG_PPC32
2816 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2817 /*
2818 * We are making executable an anonymous mapping or a
2819 * private file mapping that will also be writable.
2820 * This has an additional check.
2821 */
2822 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2823 if (rc)
2824 return rc;
2825 }
2826#endif
2827
2828 if (file) {
2829 /* read access is always possible with a mapping */
2830 u32 av = FILE__READ;
2831
2832 /* write access only matters if the mapping is shared */
2833 if (shared && (prot & PROT_WRITE))
2834 av |= FILE__WRITE;
2835
2836 if (prot & PROT_EXEC)
2837 av |= FILE__EXECUTE;
2838
2839 return file_has_perm(current, file, av);
2840 }
2841 return 0;
2842}
2843
2844static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002845 unsigned long prot, unsigned long flags,
2846 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847{
Eric Parised032182007-06-28 15:55:21 -04002848 int rc = 0;
2849 u32 sid = ((struct task_security_struct*)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
Eric Parised032182007-06-28 15:55:21 -04002851 if (addr < mmap_min_addr)
2852 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2853 MEMPROTECT__MMAP_ZERO, NULL);
2854 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 return rc;
2856
2857 if (selinux_checkreqprot)
2858 prot = reqprot;
2859
2860 return file_map_prot_check(file, prot,
2861 (flags & MAP_TYPE) == MAP_SHARED);
2862}
2863
2864static int selinux_file_mprotect(struct vm_area_struct *vma,
2865 unsigned long reqprot,
2866 unsigned long prot)
2867{
2868 int rc;
2869
2870 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2871 if (rc)
2872 return rc;
2873
2874 if (selinux_checkreqprot)
2875 prot = reqprot;
2876
2877#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002878 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2879 rc = 0;
2880 if (vma->vm_start >= vma->vm_mm->start_brk &&
2881 vma->vm_end <= vma->vm_mm->brk) {
2882 rc = task_has_perm(current, current,
2883 PROCESS__EXECHEAP);
2884 } else if (!vma->vm_file &&
2885 vma->vm_start <= vma->vm_mm->start_stack &&
2886 vma->vm_end >= vma->vm_mm->start_stack) {
2887 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2888 } else if (vma->vm_file && vma->anon_vma) {
2889 /*
2890 * We are making executable a file mapping that has
2891 * had some COW done. Since pages might have been
2892 * written, check ability to execute the possibly
2893 * modified content. This typically should only
2894 * occur for text relocations.
2895 */
2896 rc = file_has_perm(current, vma->vm_file,
2897 FILE__EXECMOD);
2898 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002899 if (rc)
2900 return rc;
2901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902#endif
2903
2904 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2905}
2906
2907static int selinux_file_lock(struct file *file, unsigned int cmd)
2908{
2909 return file_has_perm(current, file, FILE__LOCK);
2910}
2911
2912static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2913 unsigned long arg)
2914{
2915 int err = 0;
2916
2917 switch (cmd) {
2918 case F_SETFL:
Josef Sipek3d5ff522006-12-08 02:37:38 -08002919 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 err = -EINVAL;
2921 break;
2922 }
2923
2924 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2925 err = file_has_perm(current, file,FILE__WRITE);
2926 break;
2927 }
2928 /* fall through */
2929 case F_SETOWN:
2930 case F_SETSIG:
2931 case F_GETFL:
2932 case F_GETOWN:
2933 case F_GETSIG:
2934 /* Just check FD__USE permission */
2935 err = file_has_perm(current, file, 0);
2936 break;
2937 case F_GETLK:
2938 case F_SETLK:
2939 case F_SETLKW:
2940#if BITS_PER_LONG == 32
2941 case F_GETLK64:
2942 case F_SETLK64:
2943 case F_SETLKW64:
2944#endif
Josef Sipek3d5ff522006-12-08 02:37:38 -08002945 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 err = -EINVAL;
2947 break;
2948 }
2949 err = file_has_perm(current, file, FILE__LOCK);
2950 break;
2951 }
2952
2953 return err;
2954}
2955
2956static int selinux_file_set_fowner(struct file *file)
2957{
2958 struct task_security_struct *tsec;
2959 struct file_security_struct *fsec;
2960
2961 tsec = current->security;
2962 fsec = file->f_security;
2963 fsec->fown_sid = tsec->sid;
2964
2965 return 0;
2966}
2967
2968static int selinux_file_send_sigiotask(struct task_struct *tsk,
2969 struct fown_struct *fown, int signum)
2970{
2971 struct file *file;
2972 u32 perm;
2973 struct task_security_struct *tsec;
2974 struct file_security_struct *fsec;
2975
2976 /* struct fown_struct is never outside the context of a struct file */
Robert P. J. Dayb385a142007-02-10 01:46:25 -08002977 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
2979 tsec = tsk->security;
2980 fsec = file->f_security;
2981
2982 if (!signum)
2983 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
2984 else
2985 perm = signal_to_av(signum);
2986
2987 return avc_has_perm(fsec->fown_sid, tsec->sid,
2988 SECCLASS_PROCESS, perm, NULL);
2989}
2990
2991static int selinux_file_receive(struct file *file)
2992{
2993 return file_has_perm(current, file, file_to_av(file));
2994}
2995
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002996static int selinux_dentry_open(struct file *file)
2997{
2998 struct file_security_struct *fsec;
2999 struct inode *inode;
3000 struct inode_security_struct *isec;
3001 inode = file->f_path.dentry->d_inode;
3002 fsec = file->f_security;
3003 isec = inode->i_security;
3004 /*
3005 * Save inode label and policy sequence number
3006 * at open-time so that selinux_file_permission
3007 * can determine whether revalidation is necessary.
3008 * Task label is already saved in the file security
3009 * struct as its SID.
3010 */
3011 fsec->isid = isec->sid;
3012 fsec->pseqno = avc_policy_seqno();
3013 /*
3014 * Since the inode label or policy seqno may have changed
3015 * between the selinux_inode_permission check and the saving
3016 * of state above, recheck that access is still permitted.
3017 * Otherwise, access might never be revalidated against the
3018 * new inode label or new policy.
3019 * This check is not redundant - do not remove.
3020 */
3021 return inode_has_perm(current, inode, file_to_av(file), NULL);
3022}
3023
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024/* task security operations */
3025
3026static int selinux_task_create(unsigned long clone_flags)
3027{
3028 int rc;
3029
3030 rc = secondary_ops->task_create(clone_flags);
3031 if (rc)
3032 return rc;
3033
3034 return task_has_perm(current, current, PROCESS__FORK);
3035}
3036
3037static int selinux_task_alloc_security(struct task_struct *tsk)
3038{
3039 struct task_security_struct *tsec1, *tsec2;
3040 int rc;
3041
3042 tsec1 = current->security;
3043
3044 rc = task_alloc_security(tsk);
3045 if (rc)
3046 return rc;
3047 tsec2 = tsk->security;
3048
3049 tsec2->osid = tsec1->osid;
3050 tsec2->sid = tsec1->sid;
3051
Michael LeMay28eba5b2006-06-27 02:53:42 -07003052 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 tsec2->exec_sid = tsec1->exec_sid;
3054 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003055 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003056 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
3058 /* Retain ptracer SID across fork, if any.
3059 This will be reset by the ptrace hook upon any
3060 subsequent ptrace_attach operations. */
3061 tsec2->ptrace_sid = tsec1->ptrace_sid;
3062
3063 return 0;
3064}
3065
3066static void selinux_task_free_security(struct task_struct *tsk)
3067{
3068 task_free_security(tsk);
3069}
3070
3071static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3072{
3073 /* Since setuid only affects the current process, and
3074 since the SELinux controls are not based on the Linux
3075 identity attributes, SELinux does not need to control
3076 this operation. However, SELinux does control the use
3077 of the CAP_SETUID and CAP_SETGID capabilities using the
3078 capable hook. */
3079 return 0;
3080}
3081
3082static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3083{
3084 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
3085}
3086
3087static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3088{
3089 /* See the comment for setuid above. */
3090 return 0;
3091}
3092
3093static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3094{
3095 return task_has_perm(current, p, PROCESS__SETPGID);
3096}
3097
3098static int selinux_task_getpgid(struct task_struct *p)
3099{
3100 return task_has_perm(current, p, PROCESS__GETPGID);
3101}
3102
3103static int selinux_task_getsid(struct task_struct *p)
3104{
3105 return task_has_perm(current, p, PROCESS__GETSESSION);
3106}
3107
David Quigleyf9008e42006-06-30 01:55:46 -07003108static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3109{
3110 selinux_get_task_sid(p, secid);
3111}
3112
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113static int selinux_task_setgroups(struct group_info *group_info)
3114{
3115 /* See the comment for setuid above. */
3116 return 0;
3117}
3118
3119static int selinux_task_setnice(struct task_struct *p, int nice)
3120{
3121 int rc;
3122
3123 rc = secondary_ops->task_setnice(p, nice);
3124 if (rc)
3125 return rc;
3126
3127 return task_has_perm(current,p, PROCESS__SETSCHED);
3128}
3129
James Morris03e68062006-06-23 02:03:58 -07003130static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3131{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003132 int rc;
3133
3134 rc = secondary_ops->task_setioprio(p, ioprio);
3135 if (rc)
3136 return rc;
3137
James Morris03e68062006-06-23 02:03:58 -07003138 return task_has_perm(current, p, PROCESS__SETSCHED);
3139}
3140
David Quigleya1836a42006-06-30 01:55:49 -07003141static int selinux_task_getioprio(struct task_struct *p)
3142{
3143 return task_has_perm(current, p, PROCESS__GETSCHED);
3144}
3145
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3147{
3148 struct rlimit *old_rlim = current->signal->rlim + resource;
3149 int rc;
3150
3151 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3152 if (rc)
3153 return rc;
3154
3155 /* Control the ability to change the hard limit (whether
3156 lowering or raising it), so that the hard limit can
3157 later be used as a safe reset point for the soft limit
3158 upon context transitions. See selinux_bprm_apply_creds. */
3159 if (old_rlim->rlim_max != new_rlim->rlim_max)
3160 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3161
3162 return 0;
3163}
3164
3165static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3166{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003167 int rc;
3168
3169 rc = secondary_ops->task_setscheduler(p, policy, lp);
3170 if (rc)
3171 return rc;
3172
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 return task_has_perm(current, p, PROCESS__SETSCHED);
3174}
3175
3176static int selinux_task_getscheduler(struct task_struct *p)
3177{
3178 return task_has_perm(current, p, PROCESS__GETSCHED);
3179}
3180
David Quigley35601542006-06-23 02:04:01 -07003181static int selinux_task_movememory(struct task_struct *p)
3182{
3183 return task_has_perm(current, p, PROCESS__SETSCHED);
3184}
3185
David Quigleyf9008e42006-06-30 01:55:46 -07003186static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3187 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188{
3189 u32 perm;
3190 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003191 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
David Quigleyf9008e42006-06-30 01:55:46 -07003193 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 if (rc)
3195 return rc;
3196
Oleg Nesterov621d3122005-10-30 15:03:45 -08003197 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 return 0;
3199
3200 if (!sig)
3201 perm = PROCESS__SIGNULL; /* null signal; existence test */
3202 else
3203 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003204 tsec = p->security;
3205 if (secid)
3206 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3207 else
3208 rc = task_has_perm(current, p, perm);
3209 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210}
3211
3212static int selinux_task_prctl(int option,
3213 unsigned long arg2,
3214 unsigned long arg3,
3215 unsigned long arg4,
3216 unsigned long arg5)
3217{
3218 /* The current prctl operations do not appear to require
3219 any SELinux controls since they merely observe or modify
3220 the state of the current process. */
3221 return 0;
3222}
3223
3224static int selinux_task_wait(struct task_struct *p)
3225{
Eric Paris8a535142007-10-22 16:10:31 -04003226 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
3229static void selinux_task_reparent_to_init(struct task_struct *p)
3230{
3231 struct task_security_struct *tsec;
3232
3233 secondary_ops->task_reparent_to_init(p);
3234
3235 tsec = p->security;
3236 tsec->osid = tsec->sid;
3237 tsec->sid = SECINITSID_KERNEL;
3238 return;
3239}
3240
3241static void selinux_task_to_inode(struct task_struct *p,
3242 struct inode *inode)
3243{
3244 struct task_security_struct *tsec = p->security;
3245 struct inode_security_struct *isec = inode->i_security;
3246
3247 isec->sid = tsec->sid;
3248 isec->initialized = 1;
3249 return;
3250}
3251
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003253static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3254 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255{
3256 int offset, ihlen, ret = -EINVAL;
3257 struct iphdr _iph, *ih;
3258
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003259 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3261 if (ih == NULL)
3262 goto out;
3263
3264 ihlen = ih->ihl * 4;
3265 if (ihlen < sizeof(_iph))
3266 goto out;
3267
3268 ad->u.net.v4info.saddr = ih->saddr;
3269 ad->u.net.v4info.daddr = ih->daddr;
3270 ret = 0;
3271
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003272 if (proto)
3273 *proto = ih->protocol;
3274
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 switch (ih->protocol) {
3276 case IPPROTO_TCP: {
3277 struct tcphdr _tcph, *th;
3278
3279 if (ntohs(ih->frag_off) & IP_OFFSET)
3280 break;
3281
3282 offset += ihlen;
3283 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3284 if (th == NULL)
3285 break;
3286
3287 ad->u.net.sport = th->source;
3288 ad->u.net.dport = th->dest;
3289 break;
3290 }
3291
3292 case IPPROTO_UDP: {
3293 struct udphdr _udph, *uh;
3294
3295 if (ntohs(ih->frag_off) & IP_OFFSET)
3296 break;
3297
3298 offset += ihlen;
3299 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3300 if (uh == NULL)
3301 break;
3302
3303 ad->u.net.sport = uh->source;
3304 ad->u.net.dport = uh->dest;
3305 break;
3306 }
3307
James Morris2ee92d42006-11-13 16:09:01 -08003308 case IPPROTO_DCCP: {
3309 struct dccp_hdr _dccph, *dh;
3310
3311 if (ntohs(ih->frag_off) & IP_OFFSET)
3312 break;
3313
3314 offset += ihlen;
3315 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3316 if (dh == NULL)
3317 break;
3318
3319 ad->u.net.sport = dh->dccph_sport;
3320 ad->u.net.dport = dh->dccph_dport;
3321 break;
3322 }
3323
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324 default:
3325 break;
3326 }
3327out:
3328 return ret;
3329}
3330
3331#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3332
3333/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003334static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3335 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336{
3337 u8 nexthdr;
3338 int ret = -EINVAL, offset;
3339 struct ipv6hdr _ipv6h, *ip6;
3340
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003341 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3343 if (ip6 == NULL)
3344 goto out;
3345
3346 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3347 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3348 ret = 0;
3349
3350 nexthdr = ip6->nexthdr;
3351 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003352 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 if (offset < 0)
3354 goto out;
3355
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003356 if (proto)
3357 *proto = nexthdr;
3358
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 switch (nexthdr) {
3360 case IPPROTO_TCP: {
3361 struct tcphdr _tcph, *th;
3362
3363 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3364 if (th == NULL)
3365 break;
3366
3367 ad->u.net.sport = th->source;
3368 ad->u.net.dport = th->dest;
3369 break;
3370 }
3371
3372 case IPPROTO_UDP: {
3373 struct udphdr _udph, *uh;
3374
3375 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3376 if (uh == NULL)
3377 break;
3378
3379 ad->u.net.sport = uh->source;
3380 ad->u.net.dport = uh->dest;
3381 break;
3382 }
3383
James Morris2ee92d42006-11-13 16:09:01 -08003384 case IPPROTO_DCCP: {
3385 struct dccp_hdr _dccph, *dh;
3386
3387 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3388 if (dh == NULL)
3389 break;
3390
3391 ad->u.net.sport = dh->dccph_sport;
3392 ad->u.net.dport = dh->dccph_dport;
3393 break;
3394 }
3395
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 /* includes fragments */
3397 default:
3398 break;
3399 }
3400out:
3401 return ret;
3402}
3403
3404#endif /* IPV6 */
3405
3406static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003407 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408{
3409 int ret = 0;
3410
3411 switch (ad->u.net.family) {
3412 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003413 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 if (ret || !addrp)
3415 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3417 &ad->u.net.v4info.daddr);
3418 break;
3419
3420#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3421 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003422 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 if (ret || !addrp)
3424 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3426 &ad->u.net.v6info.daddr);
3427 break;
3428#endif /* IPV6 */
3429 default:
3430 break;
3431 }
3432
Paul Moore71f1cb02008-01-29 08:51:16 -05003433 if (unlikely(ret))
3434 printk(KERN_WARNING
3435 "SELinux: failure in selinux_parse_skb(),"
3436 " unable to parse packet\n");
3437
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 return ret;
3439}
3440
Paul Moore4f6a9932007-03-01 14:35:22 -05003441/**
Paul Moore220deb92008-01-29 08:38:23 -05003442 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003443 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003444 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003445 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003446 *
3447 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003448 * Check the various different forms of network peer labeling and determine
3449 * the peer label/SID for the packet; most of the magic actually occurs in
3450 * the security server function security_net_peersid_cmp(). The function
3451 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3452 * or -EACCES if @sid is invalid due to inconsistencies with the different
3453 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003454 *
3455 */
Paul Moore220deb92008-01-29 08:38:23 -05003456static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003457{
Paul Moore71f1cb02008-01-29 08:51:16 -05003458 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003459 u32 xfrm_sid;
3460 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003461 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003462
3463 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003464 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003465
Paul Moore71f1cb02008-01-29 08:51:16 -05003466 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3467 if (unlikely(err)) {
3468 printk(KERN_WARNING
3469 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3470 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003471 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003472 }
Paul Moore220deb92008-01-29 08:38:23 -05003473
3474 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003475}
3476
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477/* socket security operations */
3478static int socket_has_perm(struct task_struct *task, struct socket *sock,
3479 u32 perms)
3480{
3481 struct inode_security_struct *isec;
3482 struct task_security_struct *tsec;
3483 struct avc_audit_data ad;
3484 int err = 0;
3485
3486 tsec = task->security;
3487 isec = SOCK_INODE(sock)->i_security;
3488
3489 if (isec->sid == SECINITSID_KERNEL)
3490 goto out;
3491
3492 AVC_AUDIT_DATA_INIT(&ad,NET);
3493 ad.u.net.sk = sock->sk;
3494 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3495
3496out:
3497 return err;
3498}
3499
3500static int selinux_socket_create(int family, int type,
3501 int protocol, int kern)
3502{
3503 int err = 0;
3504 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003505 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506
3507 if (kern)
3508 goto out;
3509
3510 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003511 newsid = tsec->sockcreate_sid ? : tsec->sid;
3512 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 socket_type_to_security_class(family, type,
3514 protocol), SOCKET__CREATE, NULL);
3515
3516out:
3517 return err;
3518}
3519
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003520static int selinux_socket_post_create(struct socket *sock, int family,
3521 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003523 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 struct inode_security_struct *isec;
3525 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003526 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003527 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528
3529 isec = SOCK_INODE(sock)->i_security;
3530
3531 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003532 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003534 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 isec->initialized = 1;
3536
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003537 if (sock->sk) {
3538 sksec = sock->sk->sk_security;
3539 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003540 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003541 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003542 }
3543
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003544 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545}
3546
3547/* Range of port numbers used to automatically bind.
3548 Need to determine whether we should perform a name_bind
3549 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550
3551static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3552{
3553 u16 family;
3554 int err;
3555
3556 err = socket_has_perm(current, sock, SOCKET__BIND);
3557 if (err)
3558 goto out;
3559
3560 /*
3561 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003562 * Multiple address binding for SCTP is not supported yet: we just
3563 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 */
3565 family = sock->sk->sk_family;
3566 if (family == PF_INET || family == PF_INET6) {
3567 char *addrp;
3568 struct inode_security_struct *isec;
3569 struct task_security_struct *tsec;
3570 struct avc_audit_data ad;
3571 struct sockaddr_in *addr4 = NULL;
3572 struct sockaddr_in6 *addr6 = NULL;
3573 unsigned short snum;
3574 struct sock *sk = sock->sk;
3575 u32 sid, node_perm, addrlen;
3576
3577 tsec = current->security;
3578 isec = SOCK_INODE(sock)->i_security;
3579
3580 if (family == PF_INET) {
3581 addr4 = (struct sockaddr_in *)address;
3582 snum = ntohs(addr4->sin_port);
3583 addrlen = sizeof(addr4->sin_addr.s_addr);
3584 addrp = (char *)&addr4->sin_addr.s_addr;
3585 } else {
3586 addr6 = (struct sockaddr_in6 *)address;
3587 snum = ntohs(addr6->sin6_port);
3588 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3589 addrp = (char *)&addr6->sin6_addr.s6_addr;
3590 }
3591
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003592 if (snum) {
3593 int low, high;
3594
3595 inet_get_local_port_range(&low, &high);
3596
3597 if (snum < max(PROT_SOCK, low) || snum > high) {
3598 err = security_port_sid(sk->sk_family,
3599 sk->sk_type,
3600 sk->sk_protocol, snum,
3601 &sid);
3602 if (err)
3603 goto out;
3604 AVC_AUDIT_DATA_INIT(&ad,NET);
3605 ad.u.net.sport = htons(snum);
3606 ad.u.net.family = family;
3607 err = avc_has_perm(isec->sid, sid,
3608 isec->sclass,
3609 SOCKET__NAME_BIND, &ad);
3610 if (err)
3611 goto out;
3612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 }
3614
James Morris13402582005-09-30 14:24:34 -04003615 switch(isec->sclass) {
3616 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 node_perm = TCP_SOCKET__NODE_BIND;
3618 break;
3619
James Morris13402582005-09-30 14:24:34 -04003620 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 node_perm = UDP_SOCKET__NODE_BIND;
3622 break;
James Morris2ee92d42006-11-13 16:09:01 -08003623
3624 case SECCLASS_DCCP_SOCKET:
3625 node_perm = DCCP_SOCKET__NODE_BIND;
3626 break;
3627
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 default:
3629 node_perm = RAWIP_SOCKET__NODE_BIND;
3630 break;
3631 }
3632
Paul Moore224dfbd2008-01-29 08:38:13 -05003633 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 if (err)
3635 goto out;
3636
3637 AVC_AUDIT_DATA_INIT(&ad,NET);
3638 ad.u.net.sport = htons(snum);
3639 ad.u.net.family = family;
3640
3641 if (family == PF_INET)
3642 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3643 else
3644 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3645
3646 err = avc_has_perm(isec->sid, sid,
3647 isec->sclass, node_perm, &ad);
3648 if (err)
3649 goto out;
3650 }
3651out:
3652 return err;
3653}
3654
3655static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3656{
3657 struct inode_security_struct *isec;
3658 int err;
3659
3660 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3661 if (err)
3662 return err;
3663
3664 /*
James Morris2ee92d42006-11-13 16:09:01 -08003665 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 */
3667 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003668 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3669 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 struct sock *sk = sock->sk;
3671 struct avc_audit_data ad;
3672 struct sockaddr_in *addr4 = NULL;
3673 struct sockaddr_in6 *addr6 = NULL;
3674 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003675 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676
3677 if (sk->sk_family == PF_INET) {
3678 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003679 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 return -EINVAL;
3681 snum = ntohs(addr4->sin_port);
3682 } else {
3683 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003684 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 return -EINVAL;
3686 snum = ntohs(addr6->sin6_port);
3687 }
3688
3689 err = security_port_sid(sk->sk_family, sk->sk_type,
3690 sk->sk_protocol, snum, &sid);
3691 if (err)
3692 goto out;
3693
James Morris2ee92d42006-11-13 16:09:01 -08003694 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3695 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 AVC_AUDIT_DATA_INIT(&ad,NET);
3698 ad.u.net.dport = htons(snum);
3699 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003700 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 if (err)
3702 goto out;
3703 }
3704
3705out:
3706 return err;
3707}
3708
3709static int selinux_socket_listen(struct socket *sock, int backlog)
3710{
3711 return socket_has_perm(current, sock, SOCKET__LISTEN);
3712}
3713
3714static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3715{
3716 int err;
3717 struct inode_security_struct *isec;
3718 struct inode_security_struct *newisec;
3719
3720 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3721 if (err)
3722 return err;
3723
3724 newisec = SOCK_INODE(newsock)->i_security;
3725
3726 isec = SOCK_INODE(sock)->i_security;
3727 newisec->sclass = isec->sclass;
3728 newisec->sid = isec->sid;
3729 newisec->initialized = 1;
3730
3731 return 0;
3732}
3733
3734static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3735 int size)
3736{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003737 int rc;
3738
3739 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3740 if (rc)
3741 return rc;
3742
3743 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744}
3745
3746static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3747 int size, int flags)
3748{
3749 return socket_has_perm(current, sock, SOCKET__READ);
3750}
3751
3752static int selinux_socket_getsockname(struct socket *sock)
3753{
3754 return socket_has_perm(current, sock, SOCKET__GETATTR);
3755}
3756
3757static int selinux_socket_getpeername(struct socket *sock)
3758{
3759 return socket_has_perm(current, sock, SOCKET__GETATTR);
3760}
3761
3762static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3763{
Paul Mooref8687af2006-10-30 15:22:15 -08003764 int err;
3765
3766 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3767 if (err)
3768 return err;
3769
3770 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771}
3772
3773static int selinux_socket_getsockopt(struct socket *sock, int level,
3774 int optname)
3775{
3776 return socket_has_perm(current, sock, SOCKET__GETOPT);
3777}
3778
3779static int selinux_socket_shutdown(struct socket *sock, int how)
3780{
3781 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3782}
3783
3784static int selinux_socket_unix_stream_connect(struct socket *sock,
3785 struct socket *other,
3786 struct sock *newsk)
3787{
3788 struct sk_security_struct *ssec;
3789 struct inode_security_struct *isec;
3790 struct inode_security_struct *other_isec;
3791 struct avc_audit_data ad;
3792 int err;
3793
3794 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3795 if (err)
3796 return err;
3797
3798 isec = SOCK_INODE(sock)->i_security;
3799 other_isec = SOCK_INODE(other)->i_security;
3800
3801 AVC_AUDIT_DATA_INIT(&ad,NET);
3802 ad.u.net.sk = other->sk;
3803
3804 err = avc_has_perm(isec->sid, other_isec->sid,
3805 isec->sclass,
3806 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3807 if (err)
3808 return err;
3809
3810 /* connecting socket */
3811 ssec = sock->sk->sk_security;
3812 ssec->peer_sid = other_isec->sid;
3813
3814 /* server child socket */
3815 ssec = newsk->sk_security;
3816 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003817 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3818
3819 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820}
3821
3822static int selinux_socket_unix_may_send(struct socket *sock,
3823 struct socket *other)
3824{
3825 struct inode_security_struct *isec;
3826 struct inode_security_struct *other_isec;
3827 struct avc_audit_data ad;
3828 int err;
3829
3830 isec = SOCK_INODE(sock)->i_security;
3831 other_isec = SOCK_INODE(other)->i_security;
3832
3833 AVC_AUDIT_DATA_INIT(&ad,NET);
3834 ad.u.net.sk = other->sk;
3835
3836 err = avc_has_perm(isec->sid, other_isec->sid,
3837 isec->sclass, SOCKET__SENDTO, &ad);
3838 if (err)
3839 return err;
3840
3841 return 0;
3842}
3843
Paul Mooreeffad8d2008-01-29 08:49:27 -05003844static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3845 u32 peer_sid,
3846 struct avc_audit_data *ad)
3847{
3848 int err;
3849 u32 if_sid;
3850 u32 node_sid;
3851
3852 err = sel_netif_sid(ifindex, &if_sid);
3853 if (err)
3854 return err;
3855 err = avc_has_perm(peer_sid, if_sid,
3856 SECCLASS_NETIF, NETIF__INGRESS, ad);
3857 if (err)
3858 return err;
3859
3860 err = sel_netnode_sid(addrp, family, &node_sid);
3861 if (err)
3862 return err;
3863 return avc_has_perm(peer_sid, node_sid,
3864 SECCLASS_NODE, NODE__RECVFROM, ad);
3865}
3866
Paul Moore220deb92008-01-29 08:38:23 -05003867static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3868 struct sk_buff *skb,
3869 struct avc_audit_data *ad,
3870 u16 family,
3871 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872{
Paul Moore220deb92008-01-29 08:38:23 -05003873 int err;
3874 struct sk_security_struct *sksec = sk->sk_security;
3875 u16 sk_class;
3876 u32 netif_perm, node_perm, recv_perm;
3877 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003878
Paul Moore220deb92008-01-29 08:38:23 -05003879 sk_sid = sksec->sid;
3880 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
Paul Moore220deb92008-01-29 08:38:23 -05003882 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 case SECCLASS_UDP_SOCKET:
3884 netif_perm = NETIF__UDP_RECV;
3885 node_perm = NODE__UDP_RECV;
3886 recv_perm = UDP_SOCKET__RECV_MSG;
3887 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 case SECCLASS_TCP_SOCKET:
3889 netif_perm = NETIF__TCP_RECV;
3890 node_perm = NODE__TCP_RECV;
3891 recv_perm = TCP_SOCKET__RECV_MSG;
3892 break;
James Morris2ee92d42006-11-13 16:09:01 -08003893 case SECCLASS_DCCP_SOCKET:
3894 netif_perm = NETIF__DCCP_RECV;
3895 node_perm = NODE__DCCP_RECV;
3896 recv_perm = DCCP_SOCKET__RECV_MSG;
3897 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 default:
3899 netif_perm = NETIF__RAWIP_RECV;
3900 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003901 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 break;
3903 }
3904
Paul Moore220deb92008-01-29 08:38:23 -05003905 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003907 return err;
3908 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3909 if (err)
3910 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
Paul Moore224dfbd2008-01-29 08:38:13 -05003912 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003914 return err;
3915 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003917 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
Paul Moore220deb92008-01-29 08:38:23 -05003919 if (!recv_perm)
3920 return 0;
3921 err = security_port_sid(sk->sk_family, sk->sk_type,
3922 sk->sk_protocol, ntohs(ad->u.net.sport),
3923 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05003924 if (unlikely(err)) {
3925 printk(KERN_WARNING
3926 "SELinux: failure in"
3927 " selinux_sock_rcv_skb_iptables_compat(),"
3928 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05003929 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05003930 }
Paul Moore220deb92008-01-29 08:38:23 -05003931 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3932}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
Paul Moore220deb92008-01-29 08:38:23 -05003934static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3935 struct avc_audit_data *ad,
3936 u16 family, char *addrp)
3937{
3938 int err;
3939 struct sk_security_struct *sksec = sk->sk_security;
3940 u32 peer_sid;
3941 u32 sk_sid = sksec->sid;
3942
3943 if (selinux_compat_net)
3944 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3945 family, addrp);
3946 else
3947 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3948 PACKET__RECV, ad);
3949 if (err)
3950 return err;
3951
3952 if (selinux_policycap_netpeer) {
3953 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003955 return err;
3956 err = avc_has_perm(sk_sid, peer_sid,
3957 SECCLASS_PEER, PEER__RECV, ad);
3958 } else {
3959 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3960 if (err)
3961 return err;
3962 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003964
James Morris4e5ab4c2006-06-09 00:33:33 -07003965 return err;
3966}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003967
James Morris4e5ab4c2006-06-09 00:33:33 -07003968static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3969{
Paul Moore220deb92008-01-29 08:38:23 -05003970 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003971 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05003972 u16 family = sk->sk_family;
3973 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003974 struct avc_audit_data ad;
3975 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07003976
James Morris4e5ab4c2006-06-09 00:33:33 -07003977 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05003978 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07003979
3980 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00003981 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07003982 family = PF_INET;
3983
James Morris4e5ab4c2006-06-09 00:33:33 -07003984 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05003985 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07003986 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05003987 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07003988 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003989 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07003990
Paul Moore220deb92008-01-29 08:38:23 -05003991 /* If any sort of compatibility mode is enabled then handoff processing
3992 * to the selinux_sock_rcv_skb_compat() function to deal with the
3993 * special handling. We do this in an attempt to keep this function
3994 * as fast and as clean as possible. */
3995 if (selinux_compat_net || !selinux_policycap_netpeer)
3996 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3997 family, addrp);
3998
Paul Moored621d352008-01-29 08:43:36 -05003999 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4000 u32 peer_sid;
4001
4002 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4003 if (err)
4004 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004005 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4006 peer_sid, &ad);
4007 if (err)
4008 return err;
Paul Moored621d352008-01-29 08:43:36 -05004009 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4010 PEER__RECV, &ad);
4011 }
4012
Paul Mooreeffad8d2008-01-29 08:49:27 -05004013 if (selinux_secmark_enabled()) {
4014 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4015 PACKET__RECV, &ad);
4016 if (err)
4017 return err;
4018 }
4019
Paul Moored621d352008-01-29 08:43:36 -05004020 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021}
4022
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004023static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4024 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 int err = 0;
4027 char *scontext;
4028 u32 scontext_len;
4029 struct sk_security_struct *ssec;
4030 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004031 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
4033 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004034
Paul Moore3de4bab2006-11-17 17:38:54 -05004035 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4036 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004037 ssec = sock->sk->sk_security;
4038 peer_sid = ssec->peer_sid;
4039 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004040 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 err = -ENOPROTOOPT;
4042 goto out;
4043 }
4044
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004045 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4046
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 if (err)
4048 goto out;
4049
4050 if (scontext_len > len) {
4051 err = -ERANGE;
4052 goto out_len;
4053 }
4054
4055 if (copy_to_user(optval, scontext, scontext_len))
4056 err = -EFAULT;
4057
4058out_len:
4059 if (put_user(scontext_len, optlen))
4060 err = -EFAULT;
4061
4062 kfree(scontext);
4063out:
4064 return err;
4065}
4066
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004067static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004068{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004069 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004070 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004071
Paul Moore75e22912008-01-29 08:38:04 -05004072 if (sock)
4073 family = sock->sk->sk_family;
4074 else if (skb && skb->sk)
4075 family = skb->sk->sk_family;
4076 else
4077 goto out;
4078
4079 if (sock && family == PF_UNIX)
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004080 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004081 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004082 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004083
Paul Moore75e22912008-01-29 08:38:04 -05004084out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004085 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004086 if (peer_secid == SECSID_NULL)
4087 return -EINVAL;
4088 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004089}
4090
Al Viro7d877f32005-10-21 03:20:43 -04004091static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092{
4093 return sk_alloc_security(sk, family, priority);
4094}
4095
4096static void selinux_sk_free_security(struct sock *sk)
4097{
4098 sk_free_security(sk);
4099}
4100
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004101static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4102{
4103 struct sk_security_struct *ssec = sk->sk_security;
4104 struct sk_security_struct *newssec = newsk->sk_security;
4105
4106 newssec->sid = ssec->sid;
4107 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004108 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004109
Paul Moore9f2ad662006-11-17 17:38:53 -05004110 selinux_netlbl_sk_security_clone(ssec, newssec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004111}
4112
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004113static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004114{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004115 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004116 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004117 else {
4118 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004119
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004120 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004121 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004122}
4123
Adrian Bunk9a673e52006-08-15 00:03:53 -07004124static void selinux_sock_graft(struct sock* sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004125{
4126 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4127 struct sk_security_struct *sksec = sk->sk_security;
4128
David Woodhouse2148ccc2006-09-29 15:50:25 -07004129 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4130 sk->sk_family == PF_UNIX)
4131 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004132 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004133
4134 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004135}
4136
Adrian Bunk9a673e52006-08-15 00:03:53 -07004137static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4138 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004139{
4140 struct sk_security_struct *sksec = sk->sk_security;
4141 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004142 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004143 u32 peersid;
4144
Paul Moore220deb92008-01-29 08:38:23 -05004145 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4146 if (err)
4147 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004148 if (peersid == SECSID_NULL) {
4149 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004150 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004151 return 0;
4152 }
4153
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004154 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4155 if (err)
4156 return err;
4157
4158 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004159 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004160 return 0;
4161}
4162
Adrian Bunk9a673e52006-08-15 00:03:53 -07004163static void selinux_inet_csk_clone(struct sock *newsk,
4164 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004165{
4166 struct sk_security_struct *newsksec = newsk->sk_security;
4167
4168 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004169 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004170 /* NOTE: Ideally, we should also get the isec->sid for the
4171 new socket in sync, but we don't have the isec available yet.
4172 So we will wait until sock_graft to do it, by which
4173 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004174
Paul Moore9f2ad662006-11-17 17:38:53 -05004175 /* We don't need to take any sort of lock here as we are the only
4176 * thread with access to newsksec */
4177 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004178}
4179
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004180static void selinux_inet_conn_established(struct sock *sk,
4181 struct sk_buff *skb)
4182{
4183 struct sk_security_struct *sksec = sk->sk_security;
4184
Paul Moore220deb92008-01-29 08:38:23 -05004185 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004186}
4187
Adrian Bunk9a673e52006-08-15 00:03:53 -07004188static void selinux_req_classify_flow(const struct request_sock *req,
4189 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004190{
4191 fl->secid = req->secid;
4192}
4193
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4195{
4196 int err = 0;
4197 u32 perm;
4198 struct nlmsghdr *nlh;
4199 struct socket *sock = sk->sk_socket;
4200 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4201
4202 if (skb->len < NLMSG_SPACE(0)) {
4203 err = -EINVAL;
4204 goto out;
4205 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004206 nlh = nlmsg_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
4208 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4209 if (err) {
4210 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004211 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 "SELinux: unrecognized netlink message"
4213 " type=%hu for sclass=%hu\n",
4214 nlh->nlmsg_type, isec->sclass);
4215 if (!selinux_enforcing)
4216 err = 0;
4217 }
4218
4219 /* Ignore */
4220 if (err == -ENOENT)
4221 err = 0;
4222 goto out;
4223 }
4224
4225 err = socket_has_perm(current, sock, perm);
4226out:
4227 return err;
4228}
4229
4230#ifdef CONFIG_NETFILTER
4231
Paul Mooreeffad8d2008-01-29 08:49:27 -05004232static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4233 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004235 char *addrp;
4236 u32 peer_sid;
4237 struct avc_audit_data ad;
4238 u8 secmark_active;
4239 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004240
Paul Mooreeffad8d2008-01-29 08:49:27 -05004241 if (!selinux_policycap_netpeer)
4242 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004243
Paul Mooreeffad8d2008-01-29 08:49:27 -05004244 secmark_active = selinux_secmark_enabled();
4245 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4246 if (!secmark_active && !peerlbl_active)
4247 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004248
Paul Mooreeffad8d2008-01-29 08:49:27 -05004249 AVC_AUDIT_DATA_INIT(&ad, NET);
4250 ad.u.net.netif = ifindex;
4251 ad.u.net.family = family;
4252 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4253 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Paul Mooreeffad8d2008-01-29 08:49:27 -05004255 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4256 return NF_DROP;
4257
4258 if (peerlbl_active)
4259 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4260 peer_sid, &ad) != 0)
4261 return NF_DROP;
4262
4263 if (secmark_active)
4264 if (avc_has_perm(peer_sid, skb->secmark,
4265 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4266 return NF_DROP;
4267
4268 return NF_ACCEPT;
4269}
4270
4271static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4272 struct sk_buff *skb,
4273 const struct net_device *in,
4274 const struct net_device *out,
4275 int (*okfn)(struct sk_buff *))
4276{
4277 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4278}
4279
4280#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4281static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4282 struct sk_buff *skb,
4283 const struct net_device *in,
4284 const struct net_device *out,
4285 int (*okfn)(struct sk_buff *))
4286{
4287 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4288}
4289#endif /* IPV6 */
4290
4291static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4292 int ifindex,
4293 struct avc_audit_data *ad,
4294 u16 family, char *addrp)
4295{
4296 int err;
4297 struct sk_security_struct *sksec = sk->sk_security;
4298 u16 sk_class;
4299 u32 netif_perm, node_perm, send_perm;
4300 u32 port_sid, node_sid, if_sid, sk_sid;
4301
4302 sk_sid = sksec->sid;
4303 sk_class = sksec->sclass;
4304
4305 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 case SECCLASS_UDP_SOCKET:
4307 netif_perm = NETIF__UDP_SEND;
4308 node_perm = NODE__UDP_SEND;
4309 send_perm = UDP_SOCKET__SEND_MSG;
4310 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 case SECCLASS_TCP_SOCKET:
4312 netif_perm = NETIF__TCP_SEND;
4313 node_perm = NODE__TCP_SEND;
4314 send_perm = TCP_SOCKET__SEND_MSG;
4315 break;
James Morris2ee92d42006-11-13 16:09:01 -08004316 case SECCLASS_DCCP_SOCKET:
4317 netif_perm = NETIF__DCCP_SEND;
4318 node_perm = NODE__DCCP_SEND;
4319 send_perm = DCCP_SOCKET__SEND_MSG;
4320 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 default:
4322 netif_perm = NETIF__RAWIP_SEND;
4323 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004324 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 break;
4326 }
4327
Paul Mooreeffad8d2008-01-29 08:49:27 -05004328 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004329 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004330 return err;
4331 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4332 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
Paul Moore224dfbd2008-01-29 08:38:13 -05004334 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004335 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004336 return err;
4337 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004338 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004339 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
Paul Mooreeffad8d2008-01-29 08:49:27 -05004341 if (send_perm != 0)
4342 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Paul Mooreeffad8d2008-01-29 08:49:27 -05004344 err = security_port_sid(sk->sk_family, sk->sk_type,
4345 sk->sk_protocol, ntohs(ad->u.net.dport),
4346 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004347 if (unlikely(err)) {
4348 printk(KERN_WARNING
4349 "SELinux: failure in"
4350 " selinux_ip_postroute_iptables_compat(),"
4351 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004352 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004353 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004354 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004355}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356
Paul Mooreeffad8d2008-01-29 08:49:27 -05004357static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4358 int ifindex,
4359 struct avc_audit_data *ad,
4360 u16 family,
4361 char *addrp,
4362 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004363{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004364 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004365 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004366
Paul Mooreeffad8d2008-01-29 08:49:27 -05004367 if (sk == NULL)
4368 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004369 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004370
Paul Mooreeffad8d2008-01-29 08:49:27 -05004371 if (selinux_compat_net) {
4372 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4373 ad, family, addrp))
4374 return NF_DROP;
4375 } else {
4376 if (avc_has_perm(sksec->sid, skb->secmark,
4377 SECCLASS_PACKET, PACKET__SEND, ad))
4378 return NF_DROP;
4379 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004380
Paul Mooreeffad8d2008-01-29 08:49:27 -05004381 if (selinux_policycap_netpeer)
4382 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4383 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004384
Paul Mooreeffad8d2008-01-29 08:49:27 -05004385 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386}
4387
Paul Mooreeffad8d2008-01-29 08:49:27 -05004388static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4389 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004391 u32 secmark_perm;
4392 u32 peer_sid;
4393 struct sock *sk;
4394 struct avc_audit_data ad;
4395 char *addrp;
4396 u8 proto;
4397 u8 secmark_active;
4398 u8 peerlbl_active;
4399
4400 AVC_AUDIT_DATA_INIT(&ad, NET);
4401 ad.u.net.netif = ifindex;
4402 ad.u.net.family = family;
4403 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4404 return NF_DROP;
4405
4406 /* If any sort of compatibility mode is enabled then handoff processing
4407 * to the selinux_ip_postroute_compat() function to deal with the
4408 * special handling. We do this in an attempt to keep this function
4409 * as fast and as clean as possible. */
4410 if (selinux_compat_net || !selinux_policycap_netpeer)
4411 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4412 family, addrp, proto);
4413
4414 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4415 * packet transformation so allow the packet to pass without any checks
4416 * since we'll have another chance to perform access control checks
4417 * when the packet is on it's final way out.
4418 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4419 * is NULL, in this case go ahead and apply access control. */
4420 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4421 return NF_ACCEPT;
4422
4423 secmark_active = selinux_secmark_enabled();
4424 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4425 if (!secmark_active && !peerlbl_active)
4426 return NF_ACCEPT;
4427
4428 /* if the packet is locally generated (skb->sk != NULL) then use the
4429 * socket's label as the peer label, otherwise the packet is being
4430 * forwarded through this system and we need to fetch the peer label
4431 * directly from the packet */
4432 sk = skb->sk;
4433 if (sk) {
4434 struct sk_security_struct *sksec = sk->sk_security;
4435 peer_sid = sksec->sid;
4436 secmark_perm = PACKET__SEND;
4437 } else {
4438 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4439 return NF_DROP;
4440 secmark_perm = PACKET__FORWARD_OUT;
4441 }
4442
4443 if (secmark_active)
4444 if (avc_has_perm(peer_sid, skb->secmark,
4445 SECCLASS_PACKET, secmark_perm, &ad))
4446 return NF_DROP;
4447
4448 if (peerlbl_active) {
4449 u32 if_sid;
4450 u32 node_sid;
4451
4452 if (sel_netif_sid(ifindex, &if_sid))
4453 return NF_DROP;
4454 if (avc_has_perm(peer_sid, if_sid,
4455 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4456 return NF_DROP;
4457
4458 if (sel_netnode_sid(addrp, family, &node_sid))
4459 return NF_DROP;
4460 if (avc_has_perm(peer_sid, node_sid,
4461 SECCLASS_NODE, NODE__SENDTO, &ad))
4462 return NF_DROP;
4463 }
4464
4465 return NF_ACCEPT;
4466}
4467
4468static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4469 struct sk_buff *skb,
4470 const struct net_device *in,
4471 const struct net_device *out,
4472 int (*okfn)(struct sk_buff *))
4473{
4474 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475}
4476
4477#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004478static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4479 struct sk_buff *skb,
4480 const struct net_device *in,
4481 const struct net_device *out,
4482 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004484 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486#endif /* IPV6 */
4487
4488#endif /* CONFIG_NETFILTER */
4489
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4491{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 int err;
4493
4494 err = secondary_ops->netlink_send(sk, skb);
4495 if (err)
4496 return err;
4497
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4499 err = selinux_nlmsg_perm(sk, skb);
4500
4501 return err;
4502}
4503
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004504static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004506 int err;
4507 struct avc_audit_data ad;
4508
4509 err = secondary_ops->netlink_recv(skb, capability);
4510 if (err)
4511 return err;
4512
4513 AVC_AUDIT_DATA_INIT(&ad, CAP);
4514 ad.u.cap = capability;
4515
4516 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
4517 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518}
4519
4520static int ipc_alloc_security(struct task_struct *task,
4521 struct kern_ipc_perm *perm,
4522 u16 sclass)
4523{
4524 struct task_security_struct *tsec = task->security;
4525 struct ipc_security_struct *isec;
4526
James Morris89d155e2005-10-30 14:59:21 -08004527 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 if (!isec)
4529 return -ENOMEM;
4530
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 isec->sclass = sclass;
4532 isec->ipc_perm = perm;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004533 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 perm->security = isec;
4535
4536 return 0;
4537}
4538
4539static void ipc_free_security(struct kern_ipc_perm *perm)
4540{
4541 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 perm->security = NULL;
4543 kfree(isec);
4544}
4545
4546static int msg_msg_alloc_security(struct msg_msg *msg)
4547{
4548 struct msg_security_struct *msec;
4549
James Morris89d155e2005-10-30 14:59:21 -08004550 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 if (!msec)
4552 return -ENOMEM;
4553
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 msec->msg = msg;
4555 msec->sid = SECINITSID_UNLABELED;
4556 msg->security = msec;
4557
4558 return 0;
4559}
4560
4561static void msg_msg_free_security(struct msg_msg *msg)
4562{
4563 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
4565 msg->security = NULL;
4566 kfree(msec);
4567}
4568
4569static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004570 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571{
4572 struct task_security_struct *tsec;
4573 struct ipc_security_struct *isec;
4574 struct avc_audit_data ad;
4575
4576 tsec = current->security;
4577 isec = ipc_perms->security;
4578
4579 AVC_AUDIT_DATA_INIT(&ad, IPC);
4580 ad.u.ipc_id = ipc_perms->key;
4581
Stephen Smalley6af963f2005-05-01 08:58:39 -07004582 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583}
4584
4585static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4586{
4587 return msg_msg_alloc_security(msg);
4588}
4589
4590static void selinux_msg_msg_free_security(struct msg_msg *msg)
4591{
4592 msg_msg_free_security(msg);
4593}
4594
4595/* message queue security operations */
4596static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4597{
4598 struct task_security_struct *tsec;
4599 struct ipc_security_struct *isec;
4600 struct avc_audit_data ad;
4601 int rc;
4602
4603 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4604 if (rc)
4605 return rc;
4606
4607 tsec = current->security;
4608 isec = msq->q_perm.security;
4609
4610 AVC_AUDIT_DATA_INIT(&ad, IPC);
4611 ad.u.ipc_id = msq->q_perm.key;
4612
4613 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4614 MSGQ__CREATE, &ad);
4615 if (rc) {
4616 ipc_free_security(&msq->q_perm);
4617 return rc;
4618 }
4619 return 0;
4620}
4621
4622static void selinux_msg_queue_free_security(struct msg_queue *msq)
4623{
4624 ipc_free_security(&msq->q_perm);
4625}
4626
4627static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4628{
4629 struct task_security_struct *tsec;
4630 struct ipc_security_struct *isec;
4631 struct avc_audit_data ad;
4632
4633 tsec = current->security;
4634 isec = msq->q_perm.security;
4635
4636 AVC_AUDIT_DATA_INIT(&ad, IPC);
4637 ad.u.ipc_id = msq->q_perm.key;
4638
4639 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4640 MSGQ__ASSOCIATE, &ad);
4641}
4642
4643static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4644{
4645 int err;
4646 int perms;
4647
4648 switch(cmd) {
4649 case IPC_INFO:
4650 case MSG_INFO:
4651 /* No specific object, just general system-wide information. */
4652 return task_has_system(current, SYSTEM__IPC_INFO);
4653 case IPC_STAT:
4654 case MSG_STAT:
4655 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4656 break;
4657 case IPC_SET:
4658 perms = MSGQ__SETATTR;
4659 break;
4660 case IPC_RMID:
4661 perms = MSGQ__DESTROY;
4662 break;
4663 default:
4664 return 0;
4665 }
4666
Stephen Smalley6af963f2005-05-01 08:58:39 -07004667 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668 return err;
4669}
4670
4671static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4672{
4673 struct task_security_struct *tsec;
4674 struct ipc_security_struct *isec;
4675 struct msg_security_struct *msec;
4676 struct avc_audit_data ad;
4677 int rc;
4678
4679 tsec = current->security;
4680 isec = msq->q_perm.security;
4681 msec = msg->security;
4682
4683 /*
4684 * First time through, need to assign label to the message
4685 */
4686 if (msec->sid == SECINITSID_UNLABELED) {
4687 /*
4688 * Compute new sid based on current process and
4689 * message queue this message will be stored in
4690 */
4691 rc = security_transition_sid(tsec->sid,
4692 isec->sid,
4693 SECCLASS_MSG,
4694 &msec->sid);
4695 if (rc)
4696 return rc;
4697 }
4698
4699 AVC_AUDIT_DATA_INIT(&ad, IPC);
4700 ad.u.ipc_id = msq->q_perm.key;
4701
4702 /* Can this process write to the queue? */
4703 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4704 MSGQ__WRITE, &ad);
4705 if (!rc)
4706 /* Can this process send the message */
4707 rc = avc_has_perm(tsec->sid, msec->sid,
4708 SECCLASS_MSG, MSG__SEND, &ad);
4709 if (!rc)
4710 /* Can the message be put in the queue? */
4711 rc = avc_has_perm(msec->sid, isec->sid,
4712 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4713
4714 return rc;
4715}
4716
4717static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4718 struct task_struct *target,
4719 long type, int mode)
4720{
4721 struct task_security_struct *tsec;
4722 struct ipc_security_struct *isec;
4723 struct msg_security_struct *msec;
4724 struct avc_audit_data ad;
4725 int rc;
4726
4727 tsec = target->security;
4728 isec = msq->q_perm.security;
4729 msec = msg->security;
4730
4731 AVC_AUDIT_DATA_INIT(&ad, IPC);
4732 ad.u.ipc_id = msq->q_perm.key;
4733
4734 rc = avc_has_perm(tsec->sid, isec->sid,
4735 SECCLASS_MSGQ, MSGQ__READ, &ad);
4736 if (!rc)
4737 rc = avc_has_perm(tsec->sid, msec->sid,
4738 SECCLASS_MSG, MSG__RECEIVE, &ad);
4739 return rc;
4740}
4741
4742/* Shared Memory security operations */
4743static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4744{
4745 struct task_security_struct *tsec;
4746 struct ipc_security_struct *isec;
4747 struct avc_audit_data ad;
4748 int rc;
4749
4750 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4751 if (rc)
4752 return rc;
4753
4754 tsec = current->security;
4755 isec = shp->shm_perm.security;
4756
4757 AVC_AUDIT_DATA_INIT(&ad, IPC);
4758 ad.u.ipc_id = shp->shm_perm.key;
4759
4760 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4761 SHM__CREATE, &ad);
4762 if (rc) {
4763 ipc_free_security(&shp->shm_perm);
4764 return rc;
4765 }
4766 return 0;
4767}
4768
4769static void selinux_shm_free_security(struct shmid_kernel *shp)
4770{
4771 ipc_free_security(&shp->shm_perm);
4772}
4773
4774static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4775{
4776 struct task_security_struct *tsec;
4777 struct ipc_security_struct *isec;
4778 struct avc_audit_data ad;
4779
4780 tsec = current->security;
4781 isec = shp->shm_perm.security;
4782
4783 AVC_AUDIT_DATA_INIT(&ad, IPC);
4784 ad.u.ipc_id = shp->shm_perm.key;
4785
4786 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4787 SHM__ASSOCIATE, &ad);
4788}
4789
4790/* Note, at this point, shp is locked down */
4791static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4792{
4793 int perms;
4794 int err;
4795
4796 switch(cmd) {
4797 case IPC_INFO:
4798 case SHM_INFO:
4799 /* No specific object, just general system-wide information. */
4800 return task_has_system(current, SYSTEM__IPC_INFO);
4801 case IPC_STAT:
4802 case SHM_STAT:
4803 perms = SHM__GETATTR | SHM__ASSOCIATE;
4804 break;
4805 case IPC_SET:
4806 perms = SHM__SETATTR;
4807 break;
4808 case SHM_LOCK:
4809 case SHM_UNLOCK:
4810 perms = SHM__LOCK;
4811 break;
4812 case IPC_RMID:
4813 perms = SHM__DESTROY;
4814 break;
4815 default:
4816 return 0;
4817 }
4818
Stephen Smalley6af963f2005-05-01 08:58:39 -07004819 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820 return err;
4821}
4822
4823static int selinux_shm_shmat(struct shmid_kernel *shp,
4824 char __user *shmaddr, int shmflg)
4825{
4826 u32 perms;
4827 int rc;
4828
4829 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4830 if (rc)
4831 return rc;
4832
4833 if (shmflg & SHM_RDONLY)
4834 perms = SHM__READ;
4835 else
4836 perms = SHM__READ | SHM__WRITE;
4837
Stephen Smalley6af963f2005-05-01 08:58:39 -07004838 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839}
4840
4841/* Semaphore security operations */
4842static int selinux_sem_alloc_security(struct sem_array *sma)
4843{
4844 struct task_security_struct *tsec;
4845 struct ipc_security_struct *isec;
4846 struct avc_audit_data ad;
4847 int rc;
4848
4849 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4850 if (rc)
4851 return rc;
4852
4853 tsec = current->security;
4854 isec = sma->sem_perm.security;
4855
4856 AVC_AUDIT_DATA_INIT(&ad, IPC);
4857 ad.u.ipc_id = sma->sem_perm.key;
4858
4859 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4860 SEM__CREATE, &ad);
4861 if (rc) {
4862 ipc_free_security(&sma->sem_perm);
4863 return rc;
4864 }
4865 return 0;
4866}
4867
4868static void selinux_sem_free_security(struct sem_array *sma)
4869{
4870 ipc_free_security(&sma->sem_perm);
4871}
4872
4873static int selinux_sem_associate(struct sem_array *sma, int semflg)
4874{
4875 struct task_security_struct *tsec;
4876 struct ipc_security_struct *isec;
4877 struct avc_audit_data ad;
4878
4879 tsec = current->security;
4880 isec = sma->sem_perm.security;
4881
4882 AVC_AUDIT_DATA_INIT(&ad, IPC);
4883 ad.u.ipc_id = sma->sem_perm.key;
4884
4885 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4886 SEM__ASSOCIATE, &ad);
4887}
4888
4889/* Note, at this point, sma is locked down */
4890static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4891{
4892 int err;
4893 u32 perms;
4894
4895 switch(cmd) {
4896 case IPC_INFO:
4897 case SEM_INFO:
4898 /* No specific object, just general system-wide information. */
4899 return task_has_system(current, SYSTEM__IPC_INFO);
4900 case GETPID:
4901 case GETNCNT:
4902 case GETZCNT:
4903 perms = SEM__GETATTR;
4904 break;
4905 case GETVAL:
4906 case GETALL:
4907 perms = SEM__READ;
4908 break;
4909 case SETVAL:
4910 case SETALL:
4911 perms = SEM__WRITE;
4912 break;
4913 case IPC_RMID:
4914 perms = SEM__DESTROY;
4915 break;
4916 case IPC_SET:
4917 perms = SEM__SETATTR;
4918 break;
4919 case IPC_STAT:
4920 case SEM_STAT:
4921 perms = SEM__GETATTR | SEM__ASSOCIATE;
4922 break;
4923 default:
4924 return 0;
4925 }
4926
Stephen Smalley6af963f2005-05-01 08:58:39 -07004927 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928 return err;
4929}
4930
4931static int selinux_sem_semop(struct sem_array *sma,
4932 struct sembuf *sops, unsigned nsops, int alter)
4933{
4934 u32 perms;
4935
4936 if (alter)
4937 perms = SEM__READ | SEM__WRITE;
4938 else
4939 perms = SEM__READ;
4940
Stephen Smalley6af963f2005-05-01 08:58:39 -07004941 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942}
4943
4944static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4945{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004946 u32 av = 0;
4947
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948 av = 0;
4949 if (flag & S_IRUGO)
4950 av |= IPC__UNIX_READ;
4951 if (flag & S_IWUGO)
4952 av |= IPC__UNIX_WRITE;
4953
4954 if (av == 0)
4955 return 0;
4956
Stephen Smalley6af963f2005-05-01 08:58:39 -07004957 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958}
4959
4960/* module stacking operations */
4961static int selinux_register_security (const char *name, struct security_operations *ops)
4962{
4963 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05004964 printk(KERN_ERR "%s: There is already a secondary security "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965 "module registered.\n", __FUNCTION__);
4966 return -EINVAL;
4967 }
4968
4969 secondary_ops = ops;
4970
4971 printk(KERN_INFO "%s: Registering secondary module %s\n",
4972 __FUNCTION__,
4973 name);
4974
4975 return 0;
4976}
4977
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
4979{
4980 if (inode)
4981 inode_doinit_with_dentry(inode, dentry);
4982}
4983
4984static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00004985 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986{
4987 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00004988 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 int error;
Al Viro04ff9702007-03-12 16:17:58 +00004990 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991
4992 if (current != p) {
4993 error = task_has_perm(current, p, PROCESS__GETATTR);
4994 if (error)
4995 return error;
4996 }
4997
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 tsec = p->security;
4999
5000 if (!strcmp(name, "current"))
5001 sid = tsec->sid;
5002 else if (!strcmp(name, "prev"))
5003 sid = tsec->osid;
5004 else if (!strcmp(name, "exec"))
5005 sid = tsec->exec_sid;
5006 else if (!strcmp(name, "fscreate"))
5007 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005008 else if (!strcmp(name, "keycreate"))
5009 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005010 else if (!strcmp(name, "sockcreate"))
5011 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 else
5013 return -EINVAL;
5014
5015 if (!sid)
5016 return 0;
5017
Al Viro04ff9702007-03-12 16:17:58 +00005018 error = security_sid_to_context(sid, value, &len);
5019 if (error)
5020 return error;
5021 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022}
5023
5024static int selinux_setprocattr(struct task_struct *p,
5025 char *name, void *value, size_t size)
5026{
5027 struct task_security_struct *tsec;
5028 u32 sid = 0;
5029 int error;
5030 char *str = value;
5031
5032 if (current != p) {
5033 /* SELinux only allows a process to change its own
5034 security attributes. */
5035 return -EACCES;
5036 }
5037
5038 /*
5039 * Basic control over ability to set these attributes at all.
5040 * current == p, but we'll pass them separately in case the
5041 * above restriction is ever removed.
5042 */
5043 if (!strcmp(name, "exec"))
5044 error = task_has_perm(current, p, PROCESS__SETEXEC);
5045 else if (!strcmp(name, "fscreate"))
5046 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005047 else if (!strcmp(name, "keycreate"))
5048 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005049 else if (!strcmp(name, "sockcreate"))
5050 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051 else if (!strcmp(name, "current"))
5052 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5053 else
5054 error = -EINVAL;
5055 if (error)
5056 return error;
5057
5058 /* Obtain a SID for the context, if one was specified. */
5059 if (size && str[1] && str[1] != '\n') {
5060 if (str[size-1] == '\n') {
5061 str[size-1] = 0;
5062 size--;
5063 }
5064 error = security_context_to_sid(value, size, &sid);
5065 if (error)
5066 return error;
5067 }
5068
5069 /* Permission checking based on the specified context is
5070 performed during the actual operation (execve,
5071 open/mkdir/...), when we know the full context of the
5072 operation. See selinux_bprm_set_security for the execve
5073 checks and may_create for the file creation checks. The
5074 operation will then fail if the context is not permitted. */
5075 tsec = p->security;
5076 if (!strcmp(name, "exec"))
5077 tsec->exec_sid = sid;
5078 else if (!strcmp(name, "fscreate"))
5079 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005080 else if (!strcmp(name, "keycreate")) {
5081 error = may_create_key(sid, p);
5082 if (error)
5083 return error;
5084 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005085 } else if (!strcmp(name, "sockcreate"))
5086 tsec->sockcreate_sid = sid;
5087 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088 struct av_decision avd;
5089
5090 if (sid == 0)
5091 return -EINVAL;
5092
5093 /* Only allow single threaded processes to change context */
5094 if (atomic_read(&p->mm->mm_users) != 1) {
5095 struct task_struct *g, *t;
5096 struct mm_struct *mm = p->mm;
5097 read_lock(&tasklist_lock);
5098 do_each_thread(g, t)
5099 if (t->mm == mm && t != p) {
5100 read_unlock(&tasklist_lock);
5101 return -EPERM;
5102 }
5103 while_each_thread(g, t);
5104 read_unlock(&tasklist_lock);
5105 }
5106
5107 /* Check permissions for the transition. */
5108 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
5109 PROCESS__DYNTRANSITION, NULL);
5110 if (error)
5111 return error;
5112
5113 /* Check for ptracing, and update the task SID if ok.
5114 Otherwise, leave SID unchanged and fail. */
5115 task_lock(p);
5116 if (p->ptrace & PT_PTRACED) {
5117 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
5118 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005119 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 if (!error)
5121 tsec->sid = sid;
5122 task_unlock(p);
5123 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
5124 PROCESS__PTRACE, &avd, error, NULL);
5125 if (error)
5126 return error;
5127 } else {
5128 tsec->sid = sid;
5129 task_unlock(p);
5130 }
5131 }
5132 else
5133 return -EINVAL;
5134
5135 return size;
5136}
5137
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005138static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5139{
5140 return security_sid_to_context(secid, secdata, seclen);
5141}
5142
David Howells63cb3442008-01-15 23:47:35 +00005143static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
5144{
5145 return security_context_to_sid(secdata, seclen, secid);
5146}
5147
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005148static void selinux_release_secctx(char *secdata, u32 seclen)
5149{
Paul Moore088999e2007-08-01 11:12:58 -04005150 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005151}
5152
Michael LeMayd7200242006-06-22 14:47:17 -07005153#ifdef CONFIG_KEYS
5154
David Howells7e047ef2006-06-26 00:24:50 -07005155static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5156 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005157{
5158 struct task_security_struct *tsec = tsk->security;
5159 struct key_security_struct *ksec;
5160
5161 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5162 if (!ksec)
5163 return -ENOMEM;
5164
5165 ksec->obj = k;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005166 if (tsec->keycreate_sid)
5167 ksec->sid = tsec->keycreate_sid;
5168 else
5169 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005170 k->security = ksec;
5171
5172 return 0;
5173}
5174
5175static void selinux_key_free(struct key *k)
5176{
5177 struct key_security_struct *ksec = k->security;
5178
5179 k->security = NULL;
5180 kfree(ksec);
5181}
5182
5183static int selinux_key_permission(key_ref_t key_ref,
5184 struct task_struct *ctx,
5185 key_perm_t perm)
5186{
5187 struct key *key;
5188 struct task_security_struct *tsec;
5189 struct key_security_struct *ksec;
5190
5191 key = key_ref_to_ptr(key_ref);
5192
5193 tsec = ctx->security;
5194 ksec = key->security;
5195
5196 /* if no specific permissions are requested, we skip the
5197 permission check. No serious, additional covert channels
5198 appear to be created. */
5199 if (perm == 0)
5200 return 0;
5201
5202 return avc_has_perm(tsec->sid, ksec->sid,
5203 SECCLASS_KEY, perm, NULL);
5204}
5205
5206#endif
5207
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208static struct security_operations selinux_ops = {
5209 .ptrace = selinux_ptrace,
5210 .capget = selinux_capget,
5211 .capset_check = selinux_capset_check,
5212 .capset_set = selinux_capset_set,
5213 .sysctl = selinux_sysctl,
5214 .capable = selinux_capable,
5215 .quotactl = selinux_quotactl,
5216 .quota_on = selinux_quota_on,
5217 .syslog = selinux_syslog,
5218 .vm_enough_memory = selinux_vm_enough_memory,
5219
5220 .netlink_send = selinux_netlink_send,
5221 .netlink_recv = selinux_netlink_recv,
5222
5223 .bprm_alloc_security = selinux_bprm_alloc_security,
5224 .bprm_free_security = selinux_bprm_free_security,
5225 .bprm_apply_creds = selinux_bprm_apply_creds,
5226 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5227 .bprm_set_security = selinux_bprm_set_security,
5228 .bprm_check_security = selinux_bprm_check_security,
5229 .bprm_secureexec = selinux_bprm_secureexec,
5230
5231 .sb_alloc_security = selinux_sb_alloc_security,
5232 .sb_free_security = selinux_sb_free_security,
5233 .sb_copy_data = selinux_sb_copy_data,
5234 .sb_kern_mount = selinux_sb_kern_mount,
5235 .sb_statfs = selinux_sb_statfs,
5236 .sb_mount = selinux_mount,
5237 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005238 .sb_get_mnt_opts = selinux_get_mnt_opts,
5239 .sb_set_mnt_opts = selinux_set_mnt_opts,
5240 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
5242 .inode_alloc_security = selinux_inode_alloc_security,
5243 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005244 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247 .inode_unlink = selinux_inode_unlink,
5248 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250 .inode_rmdir = selinux_inode_rmdir,
5251 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253 .inode_readlink = selinux_inode_readlink,
5254 .inode_follow_link = selinux_inode_follow_link,
5255 .inode_permission = selinux_inode_permission,
5256 .inode_setattr = selinux_inode_setattr,
5257 .inode_getattr = selinux_inode_getattr,
5258 .inode_setxattr = selinux_inode_setxattr,
5259 .inode_post_setxattr = selinux_inode_post_setxattr,
5260 .inode_getxattr = selinux_inode_getxattr,
5261 .inode_listxattr = selinux_inode_listxattr,
5262 .inode_removexattr = selinux_inode_removexattr,
5263 .inode_getsecurity = selinux_inode_getsecurity,
5264 .inode_setsecurity = selinux_inode_setsecurity,
5265 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005266 .inode_need_killpriv = selinux_inode_need_killpriv,
5267 .inode_killpriv = selinux_inode_killpriv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268
5269 .file_permission = selinux_file_permission,
5270 .file_alloc_security = selinux_file_alloc_security,
5271 .file_free_security = selinux_file_free_security,
5272 .file_ioctl = selinux_file_ioctl,
5273 .file_mmap = selinux_file_mmap,
5274 .file_mprotect = selinux_file_mprotect,
5275 .file_lock = selinux_file_lock,
5276 .file_fcntl = selinux_file_fcntl,
5277 .file_set_fowner = selinux_file_set_fowner,
5278 .file_send_sigiotask = selinux_file_send_sigiotask,
5279 .file_receive = selinux_file_receive,
5280
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005281 .dentry_open = selinux_dentry_open,
5282
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283 .task_create = selinux_task_create,
5284 .task_alloc_security = selinux_task_alloc_security,
5285 .task_free_security = selinux_task_free_security,
5286 .task_setuid = selinux_task_setuid,
5287 .task_post_setuid = selinux_task_post_setuid,
5288 .task_setgid = selinux_task_setgid,
5289 .task_setpgid = selinux_task_setpgid,
5290 .task_getpgid = selinux_task_getpgid,
5291 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005292 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293 .task_setgroups = selinux_task_setgroups,
5294 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005295 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005296 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297 .task_setrlimit = selinux_task_setrlimit,
5298 .task_setscheduler = selinux_task_setscheduler,
5299 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005300 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301 .task_kill = selinux_task_kill,
5302 .task_wait = selinux_task_wait,
5303 .task_prctl = selinux_task_prctl,
5304 .task_reparent_to_init = selinux_task_reparent_to_init,
5305 .task_to_inode = selinux_task_to_inode,
5306
5307 .ipc_permission = selinux_ipc_permission,
5308
5309 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5310 .msg_msg_free_security = selinux_msg_msg_free_security,
5311
5312 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5313 .msg_queue_free_security = selinux_msg_queue_free_security,
5314 .msg_queue_associate = selinux_msg_queue_associate,
5315 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5316 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5317 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5318
5319 .shm_alloc_security = selinux_shm_alloc_security,
5320 .shm_free_security = selinux_shm_free_security,
5321 .shm_associate = selinux_shm_associate,
5322 .shm_shmctl = selinux_shm_shmctl,
5323 .shm_shmat = selinux_shm_shmat,
5324
5325 .sem_alloc_security = selinux_sem_alloc_security,
5326 .sem_free_security = selinux_sem_free_security,
5327 .sem_associate = selinux_sem_associate,
5328 .sem_semctl = selinux_sem_semctl,
5329 .sem_semop = selinux_sem_semop,
5330
5331 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332
5333 .d_instantiate = selinux_d_instantiate,
5334
5335 .getprocattr = selinux_getprocattr,
5336 .setprocattr = selinux_setprocattr,
5337
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005338 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005339 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005340 .release_secctx = selinux_release_secctx,
5341
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 .unix_stream_connect = selinux_socket_unix_stream_connect,
5343 .unix_may_send = selinux_socket_unix_may_send,
5344
5345 .socket_create = selinux_socket_create,
5346 .socket_post_create = selinux_socket_post_create,
5347 .socket_bind = selinux_socket_bind,
5348 .socket_connect = selinux_socket_connect,
5349 .socket_listen = selinux_socket_listen,
5350 .socket_accept = selinux_socket_accept,
5351 .socket_sendmsg = selinux_socket_sendmsg,
5352 .socket_recvmsg = selinux_socket_recvmsg,
5353 .socket_getsockname = selinux_socket_getsockname,
5354 .socket_getpeername = selinux_socket_getpeername,
5355 .socket_getsockopt = selinux_socket_getsockopt,
5356 .socket_setsockopt = selinux_socket_setsockopt,
5357 .socket_shutdown = selinux_socket_shutdown,
5358 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005359 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5360 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361 .sk_alloc_security = selinux_sk_alloc_security,
5362 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005363 .sk_clone_security = selinux_sk_clone_security,
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005364 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005365 .sock_graft = selinux_sock_graft,
5366 .inet_conn_request = selinux_inet_conn_request,
5367 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005368 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005369 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005370
5371#ifdef CONFIG_SECURITY_NETWORK_XFRM
5372 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5373 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5374 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005375 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005376 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5377 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005378 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005379 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005380 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005381 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005383
5384#ifdef CONFIG_KEYS
5385 .key_alloc = selinux_key_alloc,
5386 .key_free = selinux_key_free,
5387 .key_permission = selinux_key_permission,
5388#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389};
5390
5391static __init int selinux_init(void)
5392{
5393 struct task_security_struct *tsec;
5394
5395 if (!selinux_enabled) {
5396 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5397 return 0;
5398 }
5399
5400 printk(KERN_INFO "SELinux: Initializing.\n");
5401
5402 /* Set the security state for the initial task. */
5403 if (task_alloc_security(current))
5404 panic("SELinux: Failed to initialize initial task.\n");
5405 tsec = current->security;
5406 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5407
James Morris7cae7e22006-03-22 00:09:22 -08005408 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5409 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005410 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 avc_init();
5412
5413 original_ops = secondary_ops = security_ops;
5414 if (!secondary_ops)
5415 panic ("SELinux: No initial security operations\n");
5416 if (register_security (&selinux_ops))
5417 panic("SELinux: Unable to register with kernel.\n");
5418
5419 if (selinux_enforcing) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005420 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 } else {
Eric Parisfadcdb42007-02-22 18:11:31 -05005422 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423 }
Michael LeMayd7200242006-06-22 14:47:17 -07005424
5425#ifdef CONFIG_KEYS
5426 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005427 selinux_key_alloc(&root_user_keyring, current,
5428 KEY_ALLOC_NOT_IN_QUOTA);
5429 selinux_key_alloc(&root_session_keyring, current,
5430 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005431#endif
5432
Linus Torvalds1da177e2005-04-16 15:20:36 -07005433 return 0;
5434}
5435
5436void selinux_complete_init(void)
5437{
Eric Parisfadcdb42007-02-22 18:11:31 -05005438 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439
5440 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005441 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005442 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443 spin_lock(&sb_security_lock);
5444next_sb:
5445 if (!list_empty(&superblock_security_head)) {
5446 struct superblock_security_struct *sbsec =
5447 list_entry(superblock_security_head.next,
5448 struct superblock_security_struct,
5449 list);
5450 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005453 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005454 down_read(&sb->s_umount);
5455 if (sb->s_root)
5456 superblock_doinit(sb, NULL);
5457 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005458 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459 spin_lock(&sb_security_lock);
5460 list_del_init(&sbsec->list);
5461 goto next_sb;
5462 }
5463 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005464 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465}
5466
5467/* SELinux requires early initialization in order to label
5468 all processes and objects when they are created. */
5469security_initcall(selinux_init);
5470
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005471#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472
Paul Mooreeffad8d2008-01-29 08:49:27 -05005473static struct nf_hook_ops selinux_ipv4_ops[] = {
5474 {
5475 .hook = selinux_ipv4_postroute,
5476 .owner = THIS_MODULE,
5477 .pf = PF_INET,
5478 .hooknum = NF_INET_POST_ROUTING,
5479 .priority = NF_IP_PRI_SELINUX_LAST,
5480 },
5481 {
5482 .hook = selinux_ipv4_forward,
5483 .owner = THIS_MODULE,
5484 .pf = PF_INET,
5485 .hooknum = NF_INET_FORWARD,
5486 .priority = NF_IP_PRI_SELINUX_FIRST,
5487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488};
5489
5490#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5491
Paul Mooreeffad8d2008-01-29 08:49:27 -05005492static struct nf_hook_ops selinux_ipv6_ops[] = {
5493 {
5494 .hook = selinux_ipv6_postroute,
5495 .owner = THIS_MODULE,
5496 .pf = PF_INET6,
5497 .hooknum = NF_INET_POST_ROUTING,
5498 .priority = NF_IP6_PRI_SELINUX_LAST,
5499 },
5500 {
5501 .hook = selinux_ipv6_forward,
5502 .owner = THIS_MODULE,
5503 .pf = PF_INET6,
5504 .hooknum = NF_INET_FORWARD,
5505 .priority = NF_IP6_PRI_SELINUX_FIRST,
5506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507};
5508
5509#endif /* IPV6 */
5510
5511static int __init selinux_nf_ip_init(void)
5512{
5513 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005514 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515
5516 if (!selinux_enabled)
5517 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005518
5519 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5520
Paul Mooreeffad8d2008-01-29 08:49:27 -05005521 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5522 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5523 if (err)
5524 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5525 err);
5526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527
5528#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005529 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5530 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5531 if (err)
5532 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5533 err);
5534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005536
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537out:
5538 return err;
5539}
5540
5541__initcall(selinux_nf_ip_init);
5542
5543#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5544static void selinux_nf_ip_exit(void)
5545{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005546 u32 iter;
5547
Eric Parisfadcdb42007-02-22 18:11:31 -05005548 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549
Paul Mooreeffad8d2008-01-29 08:49:27 -05005550 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5551 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005553 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5554 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555#endif /* IPV6 */
5556}
5557#endif
5558
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005559#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560
5561#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5562#define selinux_nf_ip_exit()
5563#endif
5564
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005565#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566
5567#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5568int selinux_disable(void)
5569{
5570 extern void exit_sel_fs(void);
5571 static int selinux_disabled = 0;
5572
5573 if (ss_initialized) {
5574 /* Not permitted after initial policy load. */
5575 return -EINVAL;
5576 }
5577
5578 if (selinux_disabled) {
5579 /* Only do this once. */
5580 return -EINVAL;
5581 }
5582
5583 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5584
5585 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005586 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587
5588 /* Reset security_ops to the secondary module, dummy or capability. */
5589 security_ops = secondary_ops;
5590
5591 /* Unregister netfilter hooks. */
5592 selinux_nf_ip_exit();
5593
5594 /* Unregister selinuxfs. */
5595 exit_sel_fs();
5596
5597 return 0;
5598}
5599#endif
5600
5601