blob: 89bb6d36c0a7f69aec9d8e0e373fe68a3c820514 [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
Josef Bacika02fe132008-04-04 09:35:05 +1100183 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
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,
Eric Parise0007522008-03-05 10:31:54 -0500446 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500447{
448 int rc = 0, i;
449 struct superblock_security_struct *sbsec = sb->s_security;
450 char *context = NULL;
451 u32 len;
452 char tmp;
453
Eric Parise0007522008-03-05 10:31:54 -0500454 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500455
456 if (!sbsec->initialized)
457 return -EINVAL;
458
459 if (!ss_initialized)
460 return -EINVAL;
461
462 /*
463 * if we ever use sbsec flags for anything other than tracking mount
464 * settings this is going to need a mask
465 */
466 tmp = sbsec->flags;
467 /* count the number of mount options for this sb */
468 for (i = 0; i < 8; i++) {
469 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500470 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500471 tmp >>= 1;
472 }
473
Eric Parise0007522008-03-05 10:31:54 -0500474 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
475 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500476 rc = -ENOMEM;
477 goto out_free;
478 }
479
Eric Parise0007522008-03-05 10:31:54 -0500480 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
481 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500482 rc = -ENOMEM;
483 goto out_free;
484 }
485
486 i = 0;
487 if (sbsec->flags & FSCONTEXT_MNT) {
488 rc = security_sid_to_context(sbsec->sid, &context, &len);
489 if (rc)
490 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500491 opts->mnt_opts[i] = context;
492 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500493 }
494 if (sbsec->flags & CONTEXT_MNT) {
495 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
496 if (rc)
497 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500498 opts->mnt_opts[i] = context;
499 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500500 }
501 if (sbsec->flags & DEFCONTEXT_MNT) {
502 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
503 if (rc)
504 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500505 opts->mnt_opts[i] = context;
506 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500507 }
508 if (sbsec->flags & ROOTCONTEXT_MNT) {
509 struct inode *root = sbsec->sb->s_root->d_inode;
510 struct inode_security_struct *isec = root->i_security;
511
512 rc = security_sid_to_context(isec->sid, &context, &len);
513 if (rc)
514 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500515 opts->mnt_opts[i] = context;
516 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500517 }
518
Eric Parise0007522008-03-05 10:31:54 -0500519 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500520
521 return 0;
522
523out_free:
Eric Parise0007522008-03-05 10:31:54 -0500524 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500525 return rc;
526}
527
528static int bad_option(struct superblock_security_struct *sbsec, char flag,
529 u32 old_sid, u32 new_sid)
530{
531 /* check if the old mount command had the same options */
532 if (sbsec->initialized)
533 if (!(sbsec->flags & flag) ||
534 (old_sid != new_sid))
535 return 1;
536
537 /* check if we were passed the same options twice,
538 * aka someone passed context=a,context=b
539 */
540 if (!sbsec->initialized)
541 if (sbsec->flags & flag)
542 return 1;
543 return 0;
544}
Eric Parise0007522008-03-05 10:31:54 -0500545
Eric Parisc9180a52007-11-30 13:00:35 -0500546/*
547 * Allow filesystems with binary mount data to explicitly set mount point
548 * labeling information.
549 */
Eric Parise0007522008-03-05 10:31:54 -0500550static int selinux_set_mnt_opts(struct super_block *sb,
551 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500552{
553 int rc = 0, i;
554 struct task_security_struct *tsec = current->security;
555 struct superblock_security_struct *sbsec = sb->s_security;
556 const char *name = sb->s_type->name;
557 struct inode *inode = sbsec->sb->s_root->d_inode;
558 struct inode_security_struct *root_isec = inode->i_security;
559 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
560 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500561 char **mount_options = opts->mnt_opts;
562 int *flags = opts->mnt_opts_flags;
563 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500564
565 mutex_lock(&sbsec->lock);
566
567 if (!ss_initialized) {
568 if (!num_opts) {
569 /* Defer initialization until selinux_complete_init,
570 after the initial policy is loaded and the security
571 server is ready to handle calls. */
572 spin_lock(&sb_security_lock);
573 if (list_empty(&sbsec->list))
574 list_add(&sbsec->list, &superblock_security_head);
575 spin_unlock(&sb_security_lock);
576 goto out;
577 }
578 rc = -EINVAL;
579 printk(KERN_WARNING "Unable to set superblock options before "
580 "the security server is initialized\n");
581 goto out;
582 }
583
584 /*
Eric Parise0007522008-03-05 10:31:54 -0500585 * Binary mount data FS will come through this function twice. Once
586 * from an explicit call and once from the generic calls from the vfs.
587 * Since the generic VFS calls will not contain any security mount data
588 * we need to skip the double mount verification.
589 *
590 * This does open a hole in which we will not notice if the first
591 * mount using this sb set explict options and a second mount using
592 * this sb does not set any security options. (The first options
593 * will be used for both mounts)
594 */
595 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
596 && (num_opts == 0))
597 goto out;
598
599 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500600 * parse the mount options, check if they are valid sids.
601 * also check if someone is trying to mount the same sb more
602 * than once with different security options.
603 */
604 for (i = 0; i < num_opts; i++) {
605 u32 sid;
606 rc = security_context_to_sid(mount_options[i],
607 strlen(mount_options[i]), &sid);
608 if (rc) {
609 printk(KERN_WARNING "SELinux: security_context_to_sid"
610 "(%s) failed for (dev %s, type %s) errno=%d\n",
611 mount_options[i], sb->s_id, name, rc);
612 goto out;
613 }
614 switch (flags[i]) {
615 case FSCONTEXT_MNT:
616 fscontext_sid = sid;
617
618 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
619 fscontext_sid))
620 goto out_double_mount;
621
622 sbsec->flags |= FSCONTEXT_MNT;
623 break;
624 case CONTEXT_MNT:
625 context_sid = sid;
626
627 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
628 context_sid))
629 goto out_double_mount;
630
631 sbsec->flags |= CONTEXT_MNT;
632 break;
633 case ROOTCONTEXT_MNT:
634 rootcontext_sid = sid;
635
636 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
637 rootcontext_sid))
638 goto out_double_mount;
639
640 sbsec->flags |= ROOTCONTEXT_MNT;
641
642 break;
643 case DEFCONTEXT_MNT:
644 defcontext_sid = sid;
645
646 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
647 defcontext_sid))
648 goto out_double_mount;
649
650 sbsec->flags |= DEFCONTEXT_MNT;
651
652 break;
653 default:
654 rc = -EINVAL;
655 goto out;
656 }
657 }
658
659 if (sbsec->initialized) {
660 /* previously mounted with options, but not on this attempt? */
661 if (sbsec->flags && !num_opts)
662 goto out_double_mount;
663 rc = 0;
664 goto out;
665 }
666
667 if (strcmp(sb->s_type->name, "proc") == 0)
668 sbsec->proc = 1;
669
670 /* Determine the labeling behavior to use for this filesystem type. */
671 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
672 if (rc) {
673 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
674 __FUNCTION__, sb->s_type->name, rc);
675 goto out;
676 }
677
678 /* sets the context of the superblock for the fs being mounted. */
679 if (fscontext_sid) {
680
681 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
682 if (rc)
683 goto out;
684
685 sbsec->sid = fscontext_sid;
686 }
687
688 /*
689 * Switch to using mount point labeling behavior.
690 * sets the label used on all file below the mountpoint, and will set
691 * the superblock context if not already set.
692 */
693 if (context_sid) {
694 if (!fscontext_sid) {
695 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
696 if (rc)
697 goto out;
698 sbsec->sid = context_sid;
699 } else {
700 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
701 if (rc)
702 goto out;
703 }
704 if (!rootcontext_sid)
705 rootcontext_sid = context_sid;
706
707 sbsec->mntpoint_sid = context_sid;
708 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
709 }
710
711 if (rootcontext_sid) {
712 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
713 if (rc)
714 goto out;
715
716 root_isec->sid = rootcontext_sid;
717 root_isec->initialized = 1;
718 }
719
720 if (defcontext_sid) {
721 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
722 rc = -EINVAL;
723 printk(KERN_WARNING "SELinux: defcontext option is "
724 "invalid for this filesystem type\n");
725 goto out;
726 }
727
728 if (defcontext_sid != sbsec->def_sid) {
729 rc = may_context_mount_inode_relabel(defcontext_sid,
730 sbsec, tsec);
731 if (rc)
732 goto out;
733 }
734
735 sbsec->def_sid = defcontext_sid;
736 }
737
738 rc = sb_finish_set_opts(sb);
739out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700740 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500742out_double_mount:
743 rc = -EINVAL;
744 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
745 "security settings for (dev %s, type %s)\n", sb->s_id, name);
746 goto out;
747}
748
749static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
750 struct super_block *newsb)
751{
752 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
753 struct superblock_security_struct *newsbsec = newsb->s_security;
754
755 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
756 int set_context = (oldsbsec->flags & CONTEXT_MNT);
757 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
758
759 /* we can't error, we can't save the info, this shouldn't get called
760 * this early in the boot process. */
761 BUG_ON(!ss_initialized);
762
763 /* this might go away sometime down the line if there is a new user
764 * of clone, but for now, nfs better not get here... */
765 BUG_ON(newsbsec->initialized);
766
767 /* how can we clone if the old one wasn't set up?? */
768 BUG_ON(!oldsbsec->initialized);
769
770 mutex_lock(&newsbsec->lock);
771
772 newsbsec->flags = oldsbsec->flags;
773
774 newsbsec->sid = oldsbsec->sid;
775 newsbsec->def_sid = oldsbsec->def_sid;
776 newsbsec->behavior = oldsbsec->behavior;
777
778 if (set_context) {
779 u32 sid = oldsbsec->mntpoint_sid;
780
781 if (!set_fscontext)
782 newsbsec->sid = sid;
783 if (!set_rootcontext) {
784 struct inode *newinode = newsb->s_root->d_inode;
785 struct inode_security_struct *newisec = newinode->i_security;
786 newisec->sid = sid;
787 }
788 newsbsec->mntpoint_sid = sid;
789 }
790 if (set_rootcontext) {
791 const struct inode *oldinode = oldsb->s_root->d_inode;
792 const struct inode_security_struct *oldisec = oldinode->i_security;
793 struct inode *newinode = newsb->s_root->d_inode;
794 struct inode_security_struct *newisec = newinode->i_security;
795
796 newisec->sid = oldisec->sid;
797 }
798
799 sb_finish_set_opts(newsb);
800 mutex_unlock(&newsbsec->lock);
801}
802
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200803static int selinux_parse_opts_str(char *options,
804 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500805{
Eric Parise0007522008-03-05 10:31:54 -0500806 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500807 char *context = NULL, *defcontext = NULL;
808 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500809 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500810
Eric Parise0007522008-03-05 10:31:54 -0500811 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500812
813 /* Standard string-based options. */
814 while ((p = strsep(&options, "|")) != NULL) {
815 int token;
816 substring_t args[MAX_OPT_ARGS];
817
818 if (!*p)
819 continue;
820
821 token = match_token(p, tokens, args);
822
823 switch (token) {
824 case Opt_context:
825 if (context || defcontext) {
826 rc = -EINVAL;
827 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
828 goto out_err;
829 }
830 context = match_strdup(&args[0]);
831 if (!context) {
832 rc = -ENOMEM;
833 goto out_err;
834 }
835 break;
836
837 case Opt_fscontext:
838 if (fscontext) {
839 rc = -EINVAL;
840 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
841 goto out_err;
842 }
843 fscontext = match_strdup(&args[0]);
844 if (!fscontext) {
845 rc = -ENOMEM;
846 goto out_err;
847 }
848 break;
849
850 case Opt_rootcontext:
851 if (rootcontext) {
852 rc = -EINVAL;
853 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
854 goto out_err;
855 }
856 rootcontext = match_strdup(&args[0]);
857 if (!rootcontext) {
858 rc = -ENOMEM;
859 goto out_err;
860 }
861 break;
862
863 case Opt_defcontext:
864 if (context || defcontext) {
865 rc = -EINVAL;
866 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
867 goto out_err;
868 }
869 defcontext = match_strdup(&args[0]);
870 if (!defcontext) {
871 rc = -ENOMEM;
872 goto out_err;
873 }
874 break;
875
876 default:
877 rc = -EINVAL;
878 printk(KERN_WARNING "SELinux: unknown mount option\n");
879 goto out_err;
880
881 }
882 }
883
Eric Parise0007522008-03-05 10:31:54 -0500884 rc = -ENOMEM;
885 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
886 if (!opts->mnt_opts)
887 goto out_err;
888
889 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
890 if (!opts->mnt_opts_flags) {
891 kfree(opts->mnt_opts);
892 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500893 }
894
Eric Parise0007522008-03-05 10:31:54 -0500895 if (fscontext) {
896 opts->mnt_opts[num_mnt_opts] = fscontext;
897 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
898 }
899 if (context) {
900 opts->mnt_opts[num_mnt_opts] = context;
901 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
902 }
903 if (rootcontext) {
904 opts->mnt_opts[num_mnt_opts] = rootcontext;
905 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
906 }
907 if (defcontext) {
908 opts->mnt_opts[num_mnt_opts] = defcontext;
909 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
910 }
911
912 opts->num_mnt_opts = num_mnt_opts;
913 return 0;
914
Eric Parisc9180a52007-11-30 13:00:35 -0500915out_err:
916 kfree(context);
917 kfree(defcontext);
918 kfree(fscontext);
919 kfree(rootcontext);
920 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921}
Eric Parise0007522008-03-05 10:31:54 -0500922/*
923 * string mount options parsing and call set the sbsec
924 */
925static int superblock_doinit(struct super_block *sb, void *data)
926{
927 int rc = 0;
928 char *options = data;
929 struct security_mnt_opts opts;
930
931 security_init_mnt_opts(&opts);
932
933 if (!data)
934 goto out;
935
936 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
937
938 rc = selinux_parse_opts_str(options, &opts);
939 if (rc)
940 goto out_err;
941
942out:
943 rc = selinux_set_mnt_opts(sb, &opts);
944
945out_err:
946 security_free_mnt_opts(&opts);
947 return rc;
948}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
950static inline u16 inode_mode_to_security_class(umode_t mode)
951{
952 switch (mode & S_IFMT) {
953 case S_IFSOCK:
954 return SECCLASS_SOCK_FILE;
955 case S_IFLNK:
956 return SECCLASS_LNK_FILE;
957 case S_IFREG:
958 return SECCLASS_FILE;
959 case S_IFBLK:
960 return SECCLASS_BLK_FILE;
961 case S_IFDIR:
962 return SECCLASS_DIR;
963 case S_IFCHR:
964 return SECCLASS_CHR_FILE;
965 case S_IFIFO:
966 return SECCLASS_FIFO_FILE;
967
968 }
969
970 return SECCLASS_FILE;
971}
972
James Morris13402582005-09-30 14:24:34 -0400973static inline int default_protocol_stream(int protocol)
974{
975 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
976}
977
978static inline int default_protocol_dgram(int protocol)
979{
980 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
981}
982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983static inline u16 socket_type_to_security_class(int family, int type, int protocol)
984{
985 switch (family) {
986 case PF_UNIX:
987 switch (type) {
988 case SOCK_STREAM:
989 case SOCK_SEQPACKET:
990 return SECCLASS_UNIX_STREAM_SOCKET;
991 case SOCK_DGRAM:
992 return SECCLASS_UNIX_DGRAM_SOCKET;
993 }
994 break;
995 case PF_INET:
996 case PF_INET6:
997 switch (type) {
998 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -0400999 if (default_protocol_stream(protocol))
1000 return SECCLASS_TCP_SOCKET;
1001 else
1002 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001004 if (default_protocol_dgram(protocol))
1005 return SECCLASS_UDP_SOCKET;
1006 else
1007 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001008 case SOCK_DCCP:
1009 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001010 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return SECCLASS_RAWIP_SOCKET;
1012 }
1013 break;
1014 case PF_NETLINK:
1015 switch (protocol) {
1016 case NETLINK_ROUTE:
1017 return SECCLASS_NETLINK_ROUTE_SOCKET;
1018 case NETLINK_FIREWALL:
1019 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001020 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1022 case NETLINK_NFLOG:
1023 return SECCLASS_NETLINK_NFLOG_SOCKET;
1024 case NETLINK_XFRM:
1025 return SECCLASS_NETLINK_XFRM_SOCKET;
1026 case NETLINK_SELINUX:
1027 return SECCLASS_NETLINK_SELINUX_SOCKET;
1028 case NETLINK_AUDIT:
1029 return SECCLASS_NETLINK_AUDIT_SOCKET;
1030 case NETLINK_IP6_FW:
1031 return SECCLASS_NETLINK_IP6FW_SOCKET;
1032 case NETLINK_DNRTMSG:
1033 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001034 case NETLINK_KOBJECT_UEVENT:
1035 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 default:
1037 return SECCLASS_NETLINK_SOCKET;
1038 }
1039 case PF_PACKET:
1040 return SECCLASS_PACKET_SOCKET;
1041 case PF_KEY:
1042 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001043 case PF_APPLETALK:
1044 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 }
1046
1047 return SECCLASS_SOCKET;
1048}
1049
1050#ifdef CONFIG_PROC_FS
1051static int selinux_proc_get_sid(struct proc_dir_entry *de,
1052 u16 tclass,
1053 u32 *sid)
1054{
1055 int buflen, rc;
1056 char *buffer, *path, *end;
1057
1058 buffer = (char*)__get_free_page(GFP_KERNEL);
1059 if (!buffer)
1060 return -ENOMEM;
1061
1062 buflen = PAGE_SIZE;
1063 end = buffer+buflen;
1064 *--end = '\0';
1065 buflen--;
1066 path = end-1;
1067 *path = '/';
1068 while (de && de != de->parent) {
1069 buflen -= de->namelen + 1;
1070 if (buflen < 0)
1071 break;
1072 end -= de->namelen;
1073 memcpy(end, de->name, de->namelen);
1074 *--end = '/';
1075 path = end;
1076 de = de->parent;
1077 }
1078 rc = security_genfs_sid("proc", path, tclass, sid);
1079 free_page((unsigned long)buffer);
1080 return rc;
1081}
1082#else
1083static int selinux_proc_get_sid(struct proc_dir_entry *de,
1084 u16 tclass,
1085 u32 *sid)
1086{
1087 return -EINVAL;
1088}
1089#endif
1090
1091/* The inode's security attributes must be initialized before first use. */
1092static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1093{
1094 struct superblock_security_struct *sbsec = NULL;
1095 struct inode_security_struct *isec = inode->i_security;
1096 u32 sid;
1097 struct dentry *dentry;
1098#define INITCONTEXTLEN 255
1099 char *context = NULL;
1100 unsigned len = 0;
1101 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 if (isec->initialized)
1104 goto out;
1105
Eric Paris23970742006-09-25 23:32:01 -07001106 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001108 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 sbsec = inode->i_sb->s_security;
1111 if (!sbsec->initialized) {
1112 /* Defer initialization until selinux_complete_init,
1113 after the initial policy is loaded and the security
1114 server is ready to handle calls. */
1115 spin_lock(&sbsec->isec_lock);
1116 if (list_empty(&isec->list))
1117 list_add(&isec->list, &sbsec->isec_head);
1118 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001119 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
1121
1122 switch (sbsec->behavior) {
1123 case SECURITY_FS_USE_XATTR:
1124 if (!inode->i_op->getxattr) {
1125 isec->sid = sbsec->def_sid;
1126 break;
1127 }
1128
1129 /* Need a dentry, since the xattr API requires one.
1130 Life would be simpler if we could just pass the inode. */
1131 if (opt_dentry) {
1132 /* Called from d_instantiate or d_splice_alias. */
1133 dentry = dget(opt_dentry);
1134 } else {
1135 /* Called from selinux_complete_init, try to find a dentry. */
1136 dentry = d_find_alias(inode);
1137 }
1138 if (!dentry) {
1139 printk(KERN_WARNING "%s: no dentry for dev=%s "
1140 "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
1141 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001142 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 }
1144
1145 len = INITCONTEXTLEN;
Stephen Smalley869ab512008-04-04 08:46:05 -04001146 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 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, XATTR_NAME_SELINUX,
1153 context, len);
1154 if (rc == -ERANGE) {
1155 /* Need a larger buffer. Query for the right size. */
1156 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1157 NULL, 0);
1158 if (rc < 0) {
1159 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001160 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
1162 kfree(context);
1163 len = rc;
Stephen Smalley869ab512008-04-04 08:46:05 -04001164 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 if (!context) {
1166 rc = -ENOMEM;
1167 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001168 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 }
1170 rc = inode->i_op->getxattr(dentry,
1171 XATTR_NAME_SELINUX,
1172 context, len);
1173 }
1174 dput(dentry);
1175 if (rc < 0) {
1176 if (rc != -ENODATA) {
1177 printk(KERN_WARNING "%s: getxattr returned "
1178 "%d for dev=%s ino=%ld\n", __FUNCTION__,
1179 -rc, inode->i_sb->s_id, inode->i_ino);
1180 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001181 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 /* Map ENODATA to the default file SID */
1184 sid = sbsec->def_sid;
1185 rc = 0;
1186 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001187 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001188 sbsec->def_sid,
1189 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 if (rc) {
1191 printk(KERN_WARNING "%s: context_to_sid(%s) "
1192 "returned %d for dev=%s ino=%ld\n",
1193 __FUNCTION__, context, -rc,
1194 inode->i_sb->s_id, inode->i_ino);
1195 kfree(context);
1196 /* Leave with the unlabeled SID */
1197 rc = 0;
1198 break;
1199 }
1200 }
1201 kfree(context);
1202 isec->sid = sid;
1203 break;
1204 case SECURITY_FS_USE_TASK:
1205 isec->sid = isec->task_sid;
1206 break;
1207 case SECURITY_FS_USE_TRANS:
1208 /* Default to the fs SID. */
1209 isec->sid = sbsec->sid;
1210
1211 /* Try to obtain a transition SID. */
1212 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1213 rc = security_transition_sid(isec->task_sid,
1214 sbsec->sid,
1215 isec->sclass,
1216 &sid);
1217 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001218 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 isec->sid = sid;
1220 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001221 case SECURITY_FS_USE_MNTPOINT:
1222 isec->sid = sbsec->mntpoint_sid;
1223 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001225 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 isec->sid = sbsec->sid;
1227
1228 if (sbsec->proc) {
1229 struct proc_inode *proci = PROC_I(inode);
1230 if (proci->pde) {
1231 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1232 rc = selinux_proc_get_sid(proci->pde,
1233 isec->sclass,
1234 &sid);
1235 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001236 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 isec->sid = sid;
1238 }
1239 }
1240 break;
1241 }
1242
1243 isec->initialized = 1;
1244
Eric Paris23970742006-09-25 23:32:01 -07001245out_unlock:
1246 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247out:
1248 if (isec->sclass == SECCLASS_FILE)
1249 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 return rc;
1251}
1252
1253/* Convert a Linux signal to an access vector. */
1254static inline u32 signal_to_av(int sig)
1255{
1256 u32 perm = 0;
1257
1258 switch (sig) {
1259 case SIGCHLD:
1260 /* Commonly granted from child to parent. */
1261 perm = PROCESS__SIGCHLD;
1262 break;
1263 case SIGKILL:
1264 /* Cannot be caught or ignored */
1265 perm = PROCESS__SIGKILL;
1266 break;
1267 case SIGSTOP:
1268 /* Cannot be caught or ignored */
1269 perm = PROCESS__SIGSTOP;
1270 break;
1271 default:
1272 /* All other signals. */
1273 perm = PROCESS__SIGNAL;
1274 break;
1275 }
1276
1277 return perm;
1278}
1279
1280/* Check permission betweeen a pair of tasks, e.g. signal checks,
1281 fork check, ptrace check, etc. */
1282static int task_has_perm(struct task_struct *tsk1,
1283 struct task_struct *tsk2,
1284 u32 perms)
1285{
1286 struct task_security_struct *tsec1, *tsec2;
1287
1288 tsec1 = tsk1->security;
1289 tsec2 = tsk2->security;
1290 return avc_has_perm(tsec1->sid, tsec2->sid,
1291 SECCLASS_PROCESS, perms, NULL);
1292}
1293
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001294#if CAP_LAST_CAP > 63
1295#error Fix SELinux to handle capabilities > 63.
1296#endif
1297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298/* Check whether a task is allowed to use a capability. */
1299static int task_has_capability(struct task_struct *tsk,
1300 int cap)
1301{
1302 struct task_security_struct *tsec;
1303 struct avc_audit_data ad;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001304 u16 sclass;
1305 u32 av = CAP_TO_MASK(cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 tsec = tsk->security;
1308
1309 AVC_AUDIT_DATA_INIT(&ad,CAP);
1310 ad.tsk = tsk;
1311 ad.u.cap = cap;
1312
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001313 switch (CAP_TO_INDEX(cap)) {
1314 case 0:
1315 sclass = SECCLASS_CAPABILITY;
1316 break;
1317 case 1:
1318 sclass = SECCLASS_CAPABILITY2;
1319 break;
1320 default:
1321 printk(KERN_ERR
1322 "SELinux: out of range capability %d\n", cap);
1323 BUG();
1324 }
1325 return avc_has_perm(tsec->sid, tsec->sid, sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326}
1327
1328/* Check whether a task is allowed to use a system operation. */
1329static int task_has_system(struct task_struct *tsk,
1330 u32 perms)
1331{
1332 struct task_security_struct *tsec;
1333
1334 tsec = tsk->security;
1335
1336 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1337 SECCLASS_SYSTEM, perms, NULL);
1338}
1339
1340/* Check whether a task has a particular permission to an inode.
1341 The 'adp' parameter is optional and allows other audit
1342 data to be passed (e.g. the dentry). */
1343static int inode_has_perm(struct task_struct *tsk,
1344 struct inode *inode,
1345 u32 perms,
1346 struct avc_audit_data *adp)
1347{
1348 struct task_security_struct *tsec;
1349 struct inode_security_struct *isec;
1350 struct avc_audit_data ad;
1351
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001352 if (unlikely (IS_PRIVATE (inode)))
1353 return 0;
1354
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 tsec = tsk->security;
1356 isec = inode->i_security;
1357
1358 if (!adp) {
1359 adp = &ad;
1360 AVC_AUDIT_DATA_INIT(&ad, FS);
1361 ad.u.fs.inode = inode;
1362 }
1363
1364 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1365}
1366
1367/* Same as inode_has_perm, but pass explicit audit data containing
1368 the dentry to help the auditing code to more easily generate the
1369 pathname if needed. */
1370static inline int dentry_has_perm(struct task_struct *tsk,
1371 struct vfsmount *mnt,
1372 struct dentry *dentry,
1373 u32 av)
1374{
1375 struct inode *inode = dentry->d_inode;
1376 struct avc_audit_data ad;
1377 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001378 ad.u.fs.path.mnt = mnt;
1379 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 return inode_has_perm(tsk, inode, av, &ad);
1381}
1382
1383/* Check whether a task can use an open file descriptor to
1384 access an inode in a given way. Check access to the
1385 descriptor itself, and then use dentry_has_perm to
1386 check a particular permission to the file.
1387 Access to the descriptor is implicitly granted if it
1388 has the same SID as the process. If av is zero, then
1389 access to the file is not checked, e.g. for cases
1390 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001391static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 struct file *file,
1393 u32 av)
1394{
1395 struct task_security_struct *tsec = tsk->security;
1396 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001397 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 struct avc_audit_data ad;
1399 int rc;
1400
1401 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001402 ad.u.fs.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
1404 if (tsec->sid != fsec->sid) {
1405 rc = avc_has_perm(tsec->sid, fsec->sid,
1406 SECCLASS_FD,
1407 FD__USE,
1408 &ad);
1409 if (rc)
1410 return rc;
1411 }
1412
1413 /* av is zero if only checking access to the descriptor. */
1414 if (av)
1415 return inode_has_perm(tsk, inode, av, &ad);
1416
1417 return 0;
1418}
1419
1420/* Check whether a task can create a file. */
1421static int may_create(struct inode *dir,
1422 struct dentry *dentry,
1423 u16 tclass)
1424{
1425 struct task_security_struct *tsec;
1426 struct inode_security_struct *dsec;
1427 struct superblock_security_struct *sbsec;
1428 u32 newsid;
1429 struct avc_audit_data ad;
1430 int rc;
1431
1432 tsec = current->security;
1433 dsec = dir->i_security;
1434 sbsec = dir->i_sb->s_security;
1435
1436 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001437 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
1439 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1440 DIR__ADD_NAME | DIR__SEARCH,
1441 &ad);
1442 if (rc)
1443 return rc;
1444
1445 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1446 newsid = tsec->create_sid;
1447 } else {
1448 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1449 &newsid);
1450 if (rc)
1451 return rc;
1452 }
1453
1454 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1455 if (rc)
1456 return rc;
1457
1458 return avc_has_perm(newsid, sbsec->sid,
1459 SECCLASS_FILESYSTEM,
1460 FILESYSTEM__ASSOCIATE, &ad);
1461}
1462
Michael LeMay4eb582c2006-06-26 00:24:57 -07001463/* Check whether a task can create a key. */
1464static int may_create_key(u32 ksid,
1465 struct task_struct *ctx)
1466{
1467 struct task_security_struct *tsec;
1468
1469 tsec = ctx->security;
1470
1471 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1472}
1473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474#define MAY_LINK 0
1475#define MAY_UNLINK 1
1476#define MAY_RMDIR 2
1477
1478/* Check whether a task can link, unlink, or rmdir a file/directory. */
1479static int may_link(struct inode *dir,
1480 struct dentry *dentry,
1481 int kind)
1482
1483{
1484 struct task_security_struct *tsec;
1485 struct inode_security_struct *dsec, *isec;
1486 struct avc_audit_data ad;
1487 u32 av;
1488 int rc;
1489
1490 tsec = current->security;
1491 dsec = dir->i_security;
1492 isec = dentry->d_inode->i_security;
1493
1494 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001495 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
1497 av = DIR__SEARCH;
1498 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1499 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1500 if (rc)
1501 return rc;
1502
1503 switch (kind) {
1504 case MAY_LINK:
1505 av = FILE__LINK;
1506 break;
1507 case MAY_UNLINK:
1508 av = FILE__UNLINK;
1509 break;
1510 case MAY_RMDIR:
1511 av = DIR__RMDIR;
1512 break;
1513 default:
1514 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1515 return 0;
1516 }
1517
1518 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1519 return rc;
1520}
1521
1522static inline int may_rename(struct inode *old_dir,
1523 struct dentry *old_dentry,
1524 struct inode *new_dir,
1525 struct dentry *new_dentry)
1526{
1527 struct task_security_struct *tsec;
1528 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1529 struct avc_audit_data ad;
1530 u32 av;
1531 int old_is_dir, new_is_dir;
1532 int rc;
1533
1534 tsec = current->security;
1535 old_dsec = old_dir->i_security;
1536 old_isec = old_dentry->d_inode->i_security;
1537 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1538 new_dsec = new_dir->i_security;
1539
1540 AVC_AUDIT_DATA_INIT(&ad, FS);
1541
Jan Blunck44707fd2008-02-14 19:38:33 -08001542 ad.u.fs.path.dentry = old_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1544 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1545 if (rc)
1546 return rc;
1547 rc = avc_has_perm(tsec->sid, old_isec->sid,
1548 old_isec->sclass, FILE__RENAME, &ad);
1549 if (rc)
1550 return rc;
1551 if (old_is_dir && new_dir != old_dir) {
1552 rc = avc_has_perm(tsec->sid, old_isec->sid,
1553 old_isec->sclass, DIR__REPARENT, &ad);
1554 if (rc)
1555 return rc;
1556 }
1557
Jan Blunck44707fd2008-02-14 19:38:33 -08001558 ad.u.fs.path.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 av = DIR__ADD_NAME | DIR__SEARCH;
1560 if (new_dentry->d_inode)
1561 av |= DIR__REMOVE_NAME;
1562 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1563 if (rc)
1564 return rc;
1565 if (new_dentry->d_inode) {
1566 new_isec = new_dentry->d_inode->i_security;
1567 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1568 rc = avc_has_perm(tsec->sid, new_isec->sid,
1569 new_isec->sclass,
1570 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1571 if (rc)
1572 return rc;
1573 }
1574
1575 return 0;
1576}
1577
1578/* Check whether a task can perform a filesystem operation. */
1579static int superblock_has_perm(struct task_struct *tsk,
1580 struct super_block *sb,
1581 u32 perms,
1582 struct avc_audit_data *ad)
1583{
1584 struct task_security_struct *tsec;
1585 struct superblock_security_struct *sbsec;
1586
1587 tsec = tsk->security;
1588 sbsec = sb->s_security;
1589 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1590 perms, ad);
1591}
1592
1593/* Convert a Linux mode and permission mask to an access vector. */
1594static inline u32 file_mask_to_av(int mode, int mask)
1595{
1596 u32 av = 0;
1597
1598 if ((mode & S_IFMT) != S_IFDIR) {
1599 if (mask & MAY_EXEC)
1600 av |= FILE__EXECUTE;
1601 if (mask & MAY_READ)
1602 av |= FILE__READ;
1603
1604 if (mask & MAY_APPEND)
1605 av |= FILE__APPEND;
1606 else if (mask & MAY_WRITE)
1607 av |= FILE__WRITE;
1608
1609 } else {
1610 if (mask & MAY_EXEC)
1611 av |= DIR__SEARCH;
1612 if (mask & MAY_WRITE)
1613 av |= DIR__WRITE;
1614 if (mask & MAY_READ)
1615 av |= DIR__READ;
1616 }
1617
1618 return av;
1619}
1620
1621/* Convert a Linux file to an access vector. */
1622static inline u32 file_to_av(struct file *file)
1623{
1624 u32 av = 0;
1625
1626 if (file->f_mode & FMODE_READ)
1627 av |= FILE__READ;
1628 if (file->f_mode & FMODE_WRITE) {
1629 if (file->f_flags & O_APPEND)
1630 av |= FILE__APPEND;
1631 else
1632 av |= FILE__WRITE;
1633 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001634 if (!av) {
1635 /*
1636 * Special file opened with flags 3 for ioctl-only use.
1637 */
1638 av = FILE__IOCTL;
1639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 return av;
1642}
1643
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644/* Hook functions begin here. */
1645
1646static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1647{
1648 struct task_security_struct *psec = parent->security;
1649 struct task_security_struct *csec = child->security;
1650 int rc;
1651
1652 rc = secondary_ops->ptrace(parent,child);
1653 if (rc)
1654 return rc;
1655
1656 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1657 /* Save the SID of the tracing process for later use in apply_creds. */
Stephen Smalley341c2d82006-03-11 03:27:16 -08001658 if (!(child->ptrace & PT_PTRACED) && !rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 csec->ptrace_sid = psec->sid;
1660 return rc;
1661}
1662
1663static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1664 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1665{
1666 int error;
1667
1668 error = task_has_perm(current, target, PROCESS__GETCAP);
1669 if (error)
1670 return error;
1671
1672 return secondary_ops->capget(target, effective, inheritable, permitted);
1673}
1674
1675static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1676 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1677{
1678 int error;
1679
1680 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1681 if (error)
1682 return error;
1683
1684 return task_has_perm(current, target, PROCESS__SETCAP);
1685}
1686
1687static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1688 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1689{
1690 secondary_ops->capset_set(target, effective, inheritable, permitted);
1691}
1692
1693static int selinux_capable(struct task_struct *tsk, int cap)
1694{
1695 int rc;
1696
1697 rc = secondary_ops->capable(tsk, cap);
1698 if (rc)
1699 return rc;
1700
1701 return task_has_capability(tsk,cap);
1702}
1703
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001704static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1705{
1706 int buflen, rc;
1707 char *buffer, *path, *end;
1708
1709 rc = -ENOMEM;
1710 buffer = (char*)__get_free_page(GFP_KERNEL);
1711 if (!buffer)
1712 goto out;
1713
1714 buflen = PAGE_SIZE;
1715 end = buffer+buflen;
1716 *--end = '\0';
1717 buflen--;
1718 path = end-1;
1719 *path = '/';
1720 while (table) {
1721 const char *name = table->procname;
1722 size_t namelen = strlen(name);
1723 buflen -= namelen + 1;
1724 if (buflen < 0)
1725 goto out_free;
1726 end -= namelen;
1727 memcpy(end, name, namelen);
1728 *--end = '/';
1729 path = end;
1730 table = table->parent;
1731 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001732 buflen -= 4;
1733 if (buflen < 0)
1734 goto out_free;
1735 end -= 4;
1736 memcpy(end, "/sys", 4);
1737 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001738 rc = security_genfs_sid("proc", path, tclass, sid);
1739out_free:
1740 free_page((unsigned long)buffer);
1741out:
1742 return rc;
1743}
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745static int selinux_sysctl(ctl_table *table, int op)
1746{
1747 int error = 0;
1748 u32 av;
1749 struct task_security_struct *tsec;
1750 u32 tsid;
1751 int rc;
1752
1753 rc = secondary_ops->sysctl(table, op);
1754 if (rc)
1755 return rc;
1756
1757 tsec = current->security;
1758
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001759 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1760 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 if (rc) {
1762 /* Default to the well-defined sysctl SID. */
1763 tsid = SECINITSID_SYSCTL;
1764 }
1765
1766 /* The op values are "defined" in sysctl.c, thereby creating
1767 * a bad coupling between this module and sysctl.c */
1768 if(op == 001) {
1769 error = avc_has_perm(tsec->sid, tsid,
1770 SECCLASS_DIR, DIR__SEARCH, NULL);
1771 } else {
1772 av = 0;
1773 if (op & 004)
1774 av |= FILE__READ;
1775 if (op & 002)
1776 av |= FILE__WRITE;
1777 if (av)
1778 error = avc_has_perm(tsec->sid, tsid,
1779 SECCLASS_FILE, av, NULL);
1780 }
1781
1782 return error;
1783}
1784
1785static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1786{
1787 int rc = 0;
1788
1789 if (!sb)
1790 return 0;
1791
1792 switch (cmds) {
1793 case Q_SYNC:
1794 case Q_QUOTAON:
1795 case Q_QUOTAOFF:
1796 case Q_SETINFO:
1797 case Q_SETQUOTA:
1798 rc = superblock_has_perm(current,
1799 sb,
1800 FILESYSTEM__QUOTAMOD, NULL);
1801 break;
1802 case Q_GETFMT:
1803 case Q_GETINFO:
1804 case Q_GETQUOTA:
1805 rc = superblock_has_perm(current,
1806 sb,
1807 FILESYSTEM__QUOTAGET, NULL);
1808 break;
1809 default:
1810 rc = 0; /* let the kernel handle invalid cmds */
1811 break;
1812 }
1813 return rc;
1814}
1815
1816static int selinux_quota_on(struct dentry *dentry)
1817{
1818 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1819}
1820
1821static int selinux_syslog(int type)
1822{
1823 int rc;
1824
1825 rc = secondary_ops->syslog(type);
1826 if (rc)
1827 return rc;
1828
1829 switch (type) {
1830 case 3: /* Read last kernel messages */
1831 case 10: /* Return size of the log buffer */
1832 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1833 break;
1834 case 6: /* Disable logging to console */
1835 case 7: /* Enable logging to console */
1836 case 8: /* Set level of messages printed to console */
1837 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1838 break;
1839 case 0: /* Close log */
1840 case 1: /* Open log */
1841 case 2: /* Read from log */
1842 case 4: /* Read/clear last kernel messages */
1843 case 5: /* Clear ring buffer */
1844 default:
1845 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1846 break;
1847 }
1848 return rc;
1849}
1850
1851/*
1852 * Check that a process has enough memory to allocate a new virtual
1853 * mapping. 0 means there is enough memory for the allocation to
1854 * succeed and -ENOMEM implies there is not.
1855 *
1856 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1857 * if the capability is granted, but __vm_enough_memory requires 1 if
1858 * the capability is granted.
1859 *
1860 * Do not audit the selinux permission check, as this is applied to all
1861 * processes that allocate mappings.
1862 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001863static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864{
1865 int rc, cap_sys_admin = 0;
1866 struct task_security_struct *tsec = current->security;
1867
1868 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1869 if (rc == 0)
1870 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001871 SECCLASS_CAPABILITY,
1872 CAP_TO_MASK(CAP_SYS_ADMIN),
1873 0,
1874 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
1876 if (rc == 0)
1877 cap_sys_admin = 1;
1878
Alan Cox34b4e4a2007-08-22 14:01:28 -07001879 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880}
1881
1882/* binprm security operations */
1883
1884static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1885{
1886 struct bprm_security_struct *bsec;
1887
James Morris89d155e2005-10-30 14:59:21 -08001888 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 if (!bsec)
1890 return -ENOMEM;
1891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 bsec->bprm = bprm;
1893 bsec->sid = SECINITSID_UNLABELED;
1894 bsec->set = 0;
1895
1896 bprm->security = bsec;
1897 return 0;
1898}
1899
1900static int selinux_bprm_set_security(struct linux_binprm *bprm)
1901{
1902 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001903 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 struct inode_security_struct *isec;
1905 struct bprm_security_struct *bsec;
1906 u32 newsid;
1907 struct avc_audit_data ad;
1908 int rc;
1909
1910 rc = secondary_ops->bprm_set_security(bprm);
1911 if (rc)
1912 return rc;
1913
1914 bsec = bprm->security;
1915
1916 if (bsec->set)
1917 return 0;
1918
1919 tsec = current->security;
1920 isec = inode->i_security;
1921
1922 /* Default to the current task SID. */
1923 bsec->sid = tsec->sid;
1924
Michael LeMay28eba5b2006-06-27 02:53:42 -07001925 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001927 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001928 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
1930 if (tsec->exec_sid) {
1931 newsid = tsec->exec_sid;
1932 /* Reset exec SID on execve. */
1933 tsec->exec_sid = 0;
1934 } else {
1935 /* Check for a default transition on this program. */
1936 rc = security_transition_sid(tsec->sid, isec->sid,
1937 SECCLASS_PROCESS, &newsid);
1938 if (rc)
1939 return rc;
1940 }
1941
1942 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001943 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Josef Sipek3d5ff522006-12-08 02:37:38 -08001945 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 newsid = tsec->sid;
1947
1948 if (tsec->sid == newsid) {
1949 rc = avc_has_perm(tsec->sid, isec->sid,
1950 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1951 if (rc)
1952 return rc;
1953 } else {
1954 /* Check permissions for the transition. */
1955 rc = avc_has_perm(tsec->sid, newsid,
1956 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1957 if (rc)
1958 return rc;
1959
1960 rc = avc_has_perm(newsid, isec->sid,
1961 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1962 if (rc)
1963 return rc;
1964
1965 /* Clear any possibly unsafe personality bits on exec: */
1966 current->personality &= ~PER_CLEAR_ON_SETID;
1967
1968 /* Set the security field to the new SID. */
1969 bsec->sid = newsid;
1970 }
1971
1972 bsec->set = 1;
1973 return 0;
1974}
1975
1976static int selinux_bprm_check_security (struct linux_binprm *bprm)
1977{
1978 return secondary_ops->bprm_check_security(bprm);
1979}
1980
1981
1982static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1983{
1984 struct task_security_struct *tsec = current->security;
1985 int atsecure = 0;
1986
1987 if (tsec->osid != tsec->sid) {
1988 /* Enable secure mode for SIDs transitions unless
1989 the noatsecure permission is granted between
1990 the two SIDs, i.e. ahp returns 0. */
1991 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1992 SECCLASS_PROCESS,
1993 PROCESS__NOATSECURE, NULL);
1994 }
1995
1996 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1997}
1998
1999static void selinux_bprm_free_security(struct linux_binprm *bprm)
2000{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07002001 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003}
2004
2005extern struct vfsmount *selinuxfs_mount;
2006extern struct dentry *selinux_null;
2007
2008/* Derived from fs/exec.c:flush_old_files. */
2009static inline void flush_unauthorized_files(struct files_struct * files)
2010{
2011 struct avc_audit_data ad;
2012 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002013 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002014 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002016 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002018 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002019 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 if (tty) {
2021 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08002022 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (file) {
2024 /* Revalidate access to controlling tty.
2025 Use inode_has_perm on the tty inode directly rather
2026 than using file_has_perm, as this particular open
2027 file may belong to another process and we are only
2028 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002029 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 if (inode_has_perm(current, inode,
2031 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002032 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034 }
2035 file_list_unlock();
2036 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002037 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002038 /* Reset controlling tty. */
2039 if (drop_tty)
2040 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
2042 /* Revalidate access to inherited open files. */
2043
2044 AVC_AUDIT_DATA_INIT(&ad,FS);
2045
2046 spin_lock(&files->file_lock);
2047 for (;;) {
2048 unsigned long set, i;
2049 int fd;
2050
2051 j++;
2052 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002053 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002054 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002056 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 if (!set)
2058 continue;
2059 spin_unlock(&files->file_lock);
2060 for ( ; set ; i++,set >>= 1) {
2061 if (set & 1) {
2062 file = fget(i);
2063 if (!file)
2064 continue;
2065 if (file_has_perm(current,
2066 file,
2067 file_to_av(file))) {
2068 sys_close(i);
2069 fd = get_unused_fd();
2070 if (fd != i) {
2071 if (fd >= 0)
2072 put_unused_fd(fd);
2073 fput(file);
2074 continue;
2075 }
2076 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002077 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 } else {
2079 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002080 if (IS_ERR(devnull)) {
2081 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 put_unused_fd(fd);
2083 fput(file);
2084 continue;
2085 }
2086 }
2087 fd_install(fd, devnull);
2088 }
2089 fput(file);
2090 }
2091 }
2092 spin_lock(&files->file_lock);
2093
2094 }
2095 spin_unlock(&files->file_lock);
2096}
2097
2098static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2099{
2100 struct task_security_struct *tsec;
2101 struct bprm_security_struct *bsec;
2102 u32 sid;
2103 int rc;
2104
2105 secondary_ops->bprm_apply_creds(bprm, unsafe);
2106
2107 tsec = current->security;
2108
2109 bsec = bprm->security;
2110 sid = bsec->sid;
2111
2112 tsec->osid = tsec->sid;
2113 bsec->unsafe = 0;
2114 if (tsec->sid != sid) {
2115 /* Check for shared state. If not ok, leave SID
2116 unchanged and kill. */
2117 if (unsafe & LSM_UNSAFE_SHARE) {
2118 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2119 PROCESS__SHARE, NULL);
2120 if (rc) {
2121 bsec->unsafe = 1;
2122 return;
2123 }
2124 }
2125
2126 /* Check for ptracing, and update the task SID if ok.
2127 Otherwise, leave SID unchanged and kill. */
2128 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2129 rc = avc_has_perm(tsec->ptrace_sid, sid,
2130 SECCLASS_PROCESS, PROCESS__PTRACE,
2131 NULL);
2132 if (rc) {
2133 bsec->unsafe = 1;
2134 return;
2135 }
2136 }
2137 tsec->sid = sid;
2138 }
2139}
2140
2141/*
2142 * called after apply_creds without the task lock held
2143 */
2144static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2145{
2146 struct task_security_struct *tsec;
2147 struct rlimit *rlim, *initrlim;
2148 struct itimerval itimer;
2149 struct bprm_security_struct *bsec;
2150 int rc, i;
2151
2152 tsec = current->security;
2153 bsec = bprm->security;
2154
2155 if (bsec->unsafe) {
2156 force_sig_specific(SIGKILL, current);
2157 return;
2158 }
2159 if (tsec->osid == tsec->sid)
2160 return;
2161
2162 /* Close files for which the new task SID is not authorized. */
2163 flush_unauthorized_files(current->files);
2164
2165 /* Check whether the new SID can inherit signal state
2166 from the old SID. If not, clear itimers to avoid
2167 subsequent signal generation and flush and unblock
2168 signals. This must occur _after_ the task SID has
2169 been updated so that any kill done after the flush
2170 will be checked against the new SID. */
2171 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2172 PROCESS__SIGINH, NULL);
2173 if (rc) {
2174 memset(&itimer, 0, sizeof itimer);
2175 for (i = 0; i < 3; i++)
2176 do_setitimer(i, &itimer, NULL);
2177 flush_signals(current);
2178 spin_lock_irq(&current->sighand->siglock);
2179 flush_signal_handlers(current, 1);
2180 sigemptyset(&current->blocked);
2181 recalc_sigpending();
2182 spin_unlock_irq(&current->sighand->siglock);
2183 }
2184
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002185 /* Always clear parent death signal on SID transitions. */
2186 current->pdeath_signal = 0;
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 /* Check whether the new SID can inherit resource limits
2189 from the old SID. If not, reset all soft limits to
2190 the lower of the current task's hard limit and the init
2191 task's soft limit. Note that the setting of hard limits
2192 (even to lower them) can be controlled by the setrlimit
2193 check. The inclusion of the init task's soft limit into
2194 the computation is to avoid resetting soft limits higher
2195 than the default soft limit for cases where the default
2196 is lower than the hard limit, e.g. RLIMIT_CORE or
2197 RLIMIT_STACK.*/
2198 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2199 PROCESS__RLIMITINH, NULL);
2200 if (rc) {
2201 for (i = 0; i < RLIM_NLIMITS; i++) {
2202 rlim = current->signal->rlim + i;
2203 initrlim = init_task.signal->rlim+i;
2204 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
2205 }
2206 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2207 /*
2208 * This will cause RLIMIT_CPU calculations
2209 * to be refigured.
2210 */
2211 current->it_prof_expires = jiffies_to_cputime(1);
2212 }
2213 }
2214
2215 /* Wake up the parent if it is waiting so that it can
2216 recheck wait permission to the new task SID. */
2217 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2218}
2219
2220/* superblock security operations */
2221
2222static int selinux_sb_alloc_security(struct super_block *sb)
2223{
2224 return superblock_alloc_security(sb);
2225}
2226
2227static void selinux_sb_free_security(struct super_block *sb)
2228{
2229 superblock_free_security(sb);
2230}
2231
2232static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2233{
2234 if (plen > olen)
2235 return 0;
2236
2237 return !memcmp(prefix, option, plen);
2238}
2239
2240static inline int selinux_option(char *option, int len)
2241{
2242 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
2243 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
Eric Paris08089252006-07-10 04:43:55 -07002244 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
2245 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246}
2247
2248static inline void take_option(char **to, char *from, int *first, int len)
2249{
2250 if (!*first) {
2251 **to = ',';
2252 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002253 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 *first = 0;
2255 memcpy(*to, from, len);
2256 *to += len;
2257}
2258
Cory Olmo3528a952006-09-29 01:58:44 -07002259static inline void take_selinux_option(char **to, char *from, int *first,
2260 int len)
2261{
2262 int current_size = 0;
2263
2264 if (!*first) {
2265 **to = '|';
2266 *to += 1;
2267 }
2268 else
2269 *first = 0;
2270
2271 while (current_size < len) {
2272 if (*from != '"') {
2273 **to = *from;
2274 *to += 1;
2275 }
2276 from += 1;
2277 current_size += 1;
2278 }
2279}
2280
Eric Parise0007522008-03-05 10:31:54 -05002281static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282{
2283 int fnosec, fsec, rc = 0;
2284 char *in_save, *in_curr, *in_end;
2285 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002286 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
2288 in_curr = orig;
2289 sec_curr = copy;
2290
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2292 if (!nosec) {
2293 rc = -ENOMEM;
2294 goto out;
2295 }
2296
2297 nosec_save = nosec;
2298 fnosec = fsec = 1;
2299 in_save = in_end = orig;
2300
2301 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002302 if (*in_end == '"')
2303 open_quote = !open_quote;
2304 if ((*in_end == ',' && open_quote == 0) ||
2305 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 int len = in_end - in_curr;
2307
2308 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002309 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 else
2311 take_option(&nosec, in_curr, &fnosec, len);
2312
2313 in_curr = in_end + 1;
2314 }
2315 } while (*in_end++);
2316
Eric Paris6931dfc2005-06-30 02:58:51 -07002317 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002318 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319out:
2320 return rc;
2321}
2322
2323static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2324{
2325 struct avc_audit_data ad;
2326 int rc;
2327
2328 rc = superblock_doinit(sb, data);
2329 if (rc)
2330 return rc;
2331
2332 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002333 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2335}
2336
David Howells726c3342006-06-23 02:02:58 -07002337static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338{
2339 struct avc_audit_data ad;
2340
2341 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002342 ad.u.fs.path.dentry = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002343 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344}
2345
2346static int selinux_mount(char * dev_name,
2347 struct nameidata *nd,
2348 char * type,
2349 unsigned long flags,
2350 void * data)
2351{
2352 int rc;
2353
2354 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2355 if (rc)
2356 return rc;
2357
2358 if (flags & MS_REMOUNT)
Jan Blunck4ac91372008-02-14 19:34:32 -08002359 return superblock_has_perm(current, nd->path.mnt->mnt_sb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 FILESYSTEM__REMOUNT, NULL);
2361 else
Jan Blunck4ac91372008-02-14 19:34:32 -08002362 return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 FILE__MOUNTON);
2364}
2365
2366static int selinux_umount(struct vfsmount *mnt, int flags)
2367{
2368 int rc;
2369
2370 rc = secondary_ops->sb_umount(mnt, flags);
2371 if (rc)
2372 return rc;
2373
2374 return superblock_has_perm(current,mnt->mnt_sb,
2375 FILESYSTEM__UNMOUNT,NULL);
2376}
2377
2378/* inode security operations */
2379
2380static int selinux_inode_alloc_security(struct inode *inode)
2381{
2382 return inode_alloc_security(inode);
2383}
2384
2385static void selinux_inode_free_security(struct inode *inode)
2386{
2387 inode_free_security(inode);
2388}
2389
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002390static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2391 char **name, void **value,
2392 size_t *len)
2393{
2394 struct task_security_struct *tsec;
2395 struct inode_security_struct *dsec;
2396 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002397 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002398 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002399 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002400
2401 tsec = current->security;
2402 dsec = dir->i_security;
2403 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002404
2405 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2406 newsid = tsec->create_sid;
2407 } else {
2408 rc = security_transition_sid(tsec->sid, dsec->sid,
2409 inode_mode_to_security_class(inode->i_mode),
2410 &newsid);
2411 if (rc) {
2412 printk(KERN_WARNING "%s: "
2413 "security_transition_sid failed, rc=%d (dev=%s "
2414 "ino=%ld)\n",
2415 __FUNCTION__,
2416 -rc, inode->i_sb->s_id, inode->i_ino);
2417 return rc;
2418 }
2419 }
2420
Eric Paris296fddf2006-09-25 23:32:00 -07002421 /* Possibly defer initialization to selinux_complete_init. */
2422 if (sbsec->initialized) {
2423 struct inode_security_struct *isec = inode->i_security;
2424 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2425 isec->sid = newsid;
2426 isec->initialized = 1;
2427 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002428
Stephen Smalley8aad3872006-03-22 00:09:13 -08002429 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002430 return -EOPNOTSUPP;
2431
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002432 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002433 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002434 if (!namep)
2435 return -ENOMEM;
2436 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002437 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002438
2439 if (value && len) {
2440 rc = security_sid_to_context(newsid, &context, &clen);
2441 if (rc) {
2442 kfree(namep);
2443 return rc;
2444 }
2445 *value = context;
2446 *len = clen;
2447 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002448
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002449 return 0;
2450}
2451
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2453{
2454 return may_create(dir, dentry, SECCLASS_FILE);
2455}
2456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2458{
2459 int rc;
2460
2461 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2462 if (rc)
2463 return rc;
2464 return may_link(dir, old_dentry, MAY_LINK);
2465}
2466
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2468{
2469 int rc;
2470
2471 rc = secondary_ops->inode_unlink(dir, dentry);
2472 if (rc)
2473 return rc;
2474 return may_link(dir, dentry, MAY_UNLINK);
2475}
2476
2477static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2478{
2479 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2480}
2481
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2483{
2484 return may_create(dir, dentry, SECCLASS_DIR);
2485}
2486
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2488{
2489 return may_link(dir, dentry, MAY_RMDIR);
2490}
2491
2492static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2493{
2494 int rc;
2495
2496 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2497 if (rc)
2498 return rc;
2499
2500 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2501}
2502
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2504 struct inode *new_inode, struct dentry *new_dentry)
2505{
2506 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2507}
2508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509static int selinux_inode_readlink(struct dentry *dentry)
2510{
2511 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2512}
2513
2514static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2515{
2516 int rc;
2517
2518 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2519 if (rc)
2520 return rc;
2521 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2522}
2523
2524static int selinux_inode_permission(struct inode *inode, int mask,
2525 struct nameidata *nd)
2526{
2527 int rc;
2528
2529 rc = secondary_ops->inode_permission(inode, mask, nd);
2530 if (rc)
2531 return rc;
2532
2533 if (!mask) {
2534 /* No permission to check. Existence test. */
2535 return 0;
2536 }
2537
2538 return inode_has_perm(current, inode,
2539 file_mask_to_av(inode->i_mode, mask), NULL);
2540}
2541
2542static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2543{
2544 int rc;
2545
2546 rc = secondary_ops->inode_setattr(dentry, iattr);
2547 if (rc)
2548 return rc;
2549
2550 if (iattr->ia_valid & ATTR_FORCE)
2551 return 0;
2552
2553 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2554 ATTR_ATIME_SET | ATTR_MTIME_SET))
2555 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2556
2557 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2558}
2559
2560static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2561{
2562 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2563}
2564
Serge E. Hallynb5376772007-10-16 23:31:36 -07002565static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2566{
2567 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2568 sizeof XATTR_SECURITY_PREFIX - 1)) {
2569 if (!strcmp(name, XATTR_NAME_CAPS)) {
2570 if (!capable(CAP_SETFCAP))
2571 return -EPERM;
2572 } else if (!capable(CAP_SYS_ADMIN)) {
2573 /* A different attribute in the security namespace.
2574 Restrict to administrator. */
2575 return -EPERM;
2576 }
2577 }
2578
2579 /* Not an attribute we recognize, so just check the
2580 ordinary setattr permission. */
2581 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2582}
2583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2585{
2586 struct task_security_struct *tsec = current->security;
2587 struct inode *inode = dentry->d_inode;
2588 struct inode_security_struct *isec = inode->i_security;
2589 struct superblock_security_struct *sbsec;
2590 struct avc_audit_data ad;
2591 u32 newsid;
2592 int rc = 0;
2593
Serge E. Hallynb5376772007-10-16 23:31:36 -07002594 if (strcmp(name, XATTR_NAME_SELINUX))
2595 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
2597 sbsec = inode->i_sb->s_security;
2598 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2599 return -EOPNOTSUPP;
2600
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302601 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 return -EPERM;
2603
2604 AVC_AUDIT_DATA_INIT(&ad,FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002605 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2608 FILE__RELABELFROM, &ad);
2609 if (rc)
2610 return rc;
2611
2612 rc = security_context_to_sid(value, size, &newsid);
2613 if (rc)
2614 return rc;
2615
2616 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2617 FILE__RELABELTO, &ad);
2618 if (rc)
2619 return rc;
2620
2621 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2622 isec->sclass);
2623 if (rc)
2624 return rc;
2625
2626 return avc_has_perm(newsid,
2627 sbsec->sid,
2628 SECCLASS_FILESYSTEM,
2629 FILESYSTEM__ASSOCIATE,
2630 &ad);
2631}
2632
2633static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2634 void *value, size_t size, int flags)
2635{
2636 struct inode *inode = dentry->d_inode;
2637 struct inode_security_struct *isec = inode->i_security;
2638 u32 newsid;
2639 int rc;
2640
2641 if (strcmp(name, XATTR_NAME_SELINUX)) {
2642 /* Not an attribute we recognize, so nothing to do. */
2643 return;
2644 }
2645
2646 rc = security_context_to_sid(value, size, &newsid);
2647 if (rc) {
2648 printk(KERN_WARNING "%s: unable to obtain SID for context "
2649 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2650 return;
2651 }
2652
2653 isec->sid = newsid;
2654 return;
2655}
2656
2657static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2658{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2660}
2661
2662static int selinux_inode_listxattr (struct dentry *dentry)
2663{
2664 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2665}
2666
2667static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2668{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002669 if (strcmp(name, XATTR_NAME_SELINUX))
2670 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
2672 /* No one is allowed to remove a SELinux security label.
2673 You can change the label, but all data must be labeled. */
2674 return -EACCES;
2675}
2676
James Morrisd381d8a2005-10-30 14:59:22 -08002677/*
2678 * Copy the in-core inode security context value to the user. If the
2679 * getxattr() prior to this succeeded, check to see if we need to
2680 * canonicalize the value to be finally returned to the user.
2681 *
2682 * Permission check is handled by selinux_inode_getxattr hook.
2683 */
David P. Quigley42492592008-02-04 22:29:39 -08002684static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685{
David P. Quigley42492592008-02-04 22:29:39 -08002686 u32 size;
2687 int error;
2688 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002691 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2692 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
David P. Quigley42492592008-02-04 22:29:39 -08002694 error = security_sid_to_context(isec->sid, &context, &size);
2695 if (error)
2696 return error;
2697 error = size;
2698 if (alloc) {
2699 *buffer = context;
2700 goto out_nofree;
2701 }
2702 kfree(context);
2703out_nofree:
2704 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705}
2706
2707static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2708 const void *value, size_t size, int flags)
2709{
2710 struct inode_security_struct *isec = inode->i_security;
2711 u32 newsid;
2712 int rc;
2713
2714 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2715 return -EOPNOTSUPP;
2716
2717 if (!value || !size)
2718 return -EACCES;
2719
2720 rc = security_context_to_sid((void*)value, size, &newsid);
2721 if (rc)
2722 return rc;
2723
2724 isec->sid = newsid;
2725 return 0;
2726}
2727
2728static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2729{
2730 const int len = sizeof(XATTR_NAME_SELINUX);
2731 if (buffer && len <= buffer_size)
2732 memcpy(buffer, XATTR_NAME_SELINUX, len);
2733 return len;
2734}
2735
Serge E. Hallynb5376772007-10-16 23:31:36 -07002736static int selinux_inode_need_killpriv(struct dentry *dentry)
2737{
2738 return secondary_ops->inode_need_killpriv(dentry);
2739}
2740
2741static int selinux_inode_killpriv(struct dentry *dentry)
2742{
2743 return secondary_ops->inode_killpriv(dentry);
2744}
2745
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746/* file security operations */
2747
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002748static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002750 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002751 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
2753 if (!mask) {
2754 /* No permission to check. Existence test. */
2755 return 0;
2756 }
2757
2758 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2759 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2760 mask |= MAY_APPEND;
2761
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002762 rc = file_has_perm(current, file,
2763 file_mask_to_av(inode->i_mode, mask));
2764 if (rc)
2765 return rc;
2766
2767 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768}
2769
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002770static int selinux_file_permission(struct file *file, int mask)
2771{
2772 struct inode *inode = file->f_path.dentry->d_inode;
2773 struct task_security_struct *tsec = current->security;
2774 struct file_security_struct *fsec = file->f_security;
2775 struct inode_security_struct *isec = inode->i_security;
2776
2777 if (!mask) {
2778 /* No permission to check. Existence test. */
2779 return 0;
2780 }
2781
2782 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2783 && fsec->pseqno == avc_policy_seqno())
2784 return selinux_netlbl_inode_permission(inode, mask);
2785
2786 return selinux_revalidate_file_permission(file, mask);
2787}
2788
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789static int selinux_file_alloc_security(struct file *file)
2790{
2791 return file_alloc_security(file);
2792}
2793
2794static void selinux_file_free_security(struct file *file)
2795{
2796 file_free_security(file);
2797}
2798
2799static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2800 unsigned long arg)
2801{
2802 int error = 0;
2803
2804 switch (cmd) {
2805 case FIONREAD:
2806 /* fall through */
2807 case FIBMAP:
2808 /* fall through */
2809 case FIGETBSZ:
2810 /* fall through */
2811 case EXT2_IOC_GETFLAGS:
2812 /* fall through */
2813 case EXT2_IOC_GETVERSION:
2814 error = file_has_perm(current, file, FILE__GETATTR);
2815 break;
2816
2817 case EXT2_IOC_SETFLAGS:
2818 /* fall through */
2819 case EXT2_IOC_SETVERSION:
2820 error = file_has_perm(current, file, FILE__SETATTR);
2821 break;
2822
2823 /* sys_ioctl() checks */
2824 case FIONBIO:
2825 /* fall through */
2826 case FIOASYNC:
2827 error = file_has_perm(current, file, 0);
2828 break;
2829
2830 case KDSKBENT:
2831 case KDSKBSENT:
2832 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2833 break;
2834
2835 /* default case assumes that the command will go
2836 * to the file's ioctl() function.
2837 */
2838 default:
2839 error = file_has_perm(current, file, FILE__IOCTL);
2840
2841 }
2842 return error;
2843}
2844
2845static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2846{
2847#ifndef CONFIG_PPC32
2848 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2849 /*
2850 * We are making executable an anonymous mapping or a
2851 * private file mapping that will also be writable.
2852 * This has an additional check.
2853 */
2854 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2855 if (rc)
2856 return rc;
2857 }
2858#endif
2859
2860 if (file) {
2861 /* read access is always possible with a mapping */
2862 u32 av = FILE__READ;
2863
2864 /* write access only matters if the mapping is shared */
2865 if (shared && (prot & PROT_WRITE))
2866 av |= FILE__WRITE;
2867
2868 if (prot & PROT_EXEC)
2869 av |= FILE__EXECUTE;
2870
2871 return file_has_perm(current, file, av);
2872 }
2873 return 0;
2874}
2875
2876static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002877 unsigned long prot, unsigned long flags,
2878 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879{
Eric Parised032182007-06-28 15:55:21 -04002880 int rc = 0;
2881 u32 sid = ((struct task_security_struct*)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
Eric Parised032182007-06-28 15:55:21 -04002883 if (addr < mmap_min_addr)
2884 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2885 MEMPROTECT__MMAP_ZERO, NULL);
2886 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 return rc;
2888
2889 if (selinux_checkreqprot)
2890 prot = reqprot;
2891
2892 return file_map_prot_check(file, prot,
2893 (flags & MAP_TYPE) == MAP_SHARED);
2894}
2895
2896static int selinux_file_mprotect(struct vm_area_struct *vma,
2897 unsigned long reqprot,
2898 unsigned long prot)
2899{
2900 int rc;
2901
2902 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2903 if (rc)
2904 return rc;
2905
2906 if (selinux_checkreqprot)
2907 prot = reqprot;
2908
2909#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002910 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2911 rc = 0;
2912 if (vma->vm_start >= vma->vm_mm->start_brk &&
2913 vma->vm_end <= vma->vm_mm->brk) {
2914 rc = task_has_perm(current, current,
2915 PROCESS__EXECHEAP);
2916 } else if (!vma->vm_file &&
2917 vma->vm_start <= vma->vm_mm->start_stack &&
2918 vma->vm_end >= vma->vm_mm->start_stack) {
2919 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2920 } else if (vma->vm_file && vma->anon_vma) {
2921 /*
2922 * We are making executable a file mapping that has
2923 * had some COW done. Since pages might have been
2924 * written, check ability to execute the possibly
2925 * modified content. This typically should only
2926 * occur for text relocations.
2927 */
2928 rc = file_has_perm(current, vma->vm_file,
2929 FILE__EXECMOD);
2930 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002931 if (rc)
2932 return rc;
2933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934#endif
2935
2936 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2937}
2938
2939static int selinux_file_lock(struct file *file, unsigned int cmd)
2940{
2941 return file_has_perm(current, file, FILE__LOCK);
2942}
2943
2944static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2945 unsigned long arg)
2946{
2947 int err = 0;
2948
2949 switch (cmd) {
2950 case F_SETFL:
Josef Sipek3d5ff522006-12-08 02:37:38 -08002951 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 err = -EINVAL;
2953 break;
2954 }
2955
2956 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2957 err = file_has_perm(current, file,FILE__WRITE);
2958 break;
2959 }
2960 /* fall through */
2961 case F_SETOWN:
2962 case F_SETSIG:
2963 case F_GETFL:
2964 case F_GETOWN:
2965 case F_GETSIG:
2966 /* Just check FD__USE permission */
2967 err = file_has_perm(current, file, 0);
2968 break;
2969 case F_GETLK:
2970 case F_SETLK:
2971 case F_SETLKW:
2972#if BITS_PER_LONG == 32
2973 case F_GETLK64:
2974 case F_SETLK64:
2975 case F_SETLKW64:
2976#endif
Josef Sipek3d5ff522006-12-08 02:37:38 -08002977 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 err = -EINVAL;
2979 break;
2980 }
2981 err = file_has_perm(current, file, FILE__LOCK);
2982 break;
2983 }
2984
2985 return err;
2986}
2987
2988static int selinux_file_set_fowner(struct file *file)
2989{
2990 struct task_security_struct *tsec;
2991 struct file_security_struct *fsec;
2992
2993 tsec = current->security;
2994 fsec = file->f_security;
2995 fsec->fown_sid = tsec->sid;
2996
2997 return 0;
2998}
2999
3000static int selinux_file_send_sigiotask(struct task_struct *tsk,
3001 struct fown_struct *fown, int signum)
3002{
3003 struct file *file;
3004 u32 perm;
3005 struct task_security_struct *tsec;
3006 struct file_security_struct *fsec;
3007
3008 /* struct fown_struct is never outside the context of a struct file */
Robert P. J. Dayb385a142007-02-10 01:46:25 -08003009 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
3011 tsec = tsk->security;
3012 fsec = file->f_security;
3013
3014 if (!signum)
3015 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3016 else
3017 perm = signal_to_av(signum);
3018
3019 return avc_has_perm(fsec->fown_sid, tsec->sid,
3020 SECCLASS_PROCESS, perm, NULL);
3021}
3022
3023static int selinux_file_receive(struct file *file)
3024{
3025 return file_has_perm(current, file, file_to_av(file));
3026}
3027
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003028static int selinux_dentry_open(struct file *file)
3029{
3030 struct file_security_struct *fsec;
3031 struct inode *inode;
3032 struct inode_security_struct *isec;
3033 inode = file->f_path.dentry->d_inode;
3034 fsec = file->f_security;
3035 isec = inode->i_security;
3036 /*
3037 * Save inode label and policy sequence number
3038 * at open-time so that selinux_file_permission
3039 * can determine whether revalidation is necessary.
3040 * Task label is already saved in the file security
3041 * struct as its SID.
3042 */
3043 fsec->isid = isec->sid;
3044 fsec->pseqno = avc_policy_seqno();
3045 /*
3046 * Since the inode label or policy seqno may have changed
3047 * between the selinux_inode_permission check and the saving
3048 * of state above, recheck that access is still permitted.
3049 * Otherwise, access might never be revalidated against the
3050 * new inode label or new policy.
3051 * This check is not redundant - do not remove.
3052 */
3053 return inode_has_perm(current, inode, file_to_av(file), NULL);
3054}
3055
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056/* task security operations */
3057
3058static int selinux_task_create(unsigned long clone_flags)
3059{
3060 int rc;
3061
3062 rc = secondary_ops->task_create(clone_flags);
3063 if (rc)
3064 return rc;
3065
3066 return task_has_perm(current, current, PROCESS__FORK);
3067}
3068
3069static int selinux_task_alloc_security(struct task_struct *tsk)
3070{
3071 struct task_security_struct *tsec1, *tsec2;
3072 int rc;
3073
3074 tsec1 = current->security;
3075
3076 rc = task_alloc_security(tsk);
3077 if (rc)
3078 return rc;
3079 tsec2 = tsk->security;
3080
3081 tsec2->osid = tsec1->osid;
3082 tsec2->sid = tsec1->sid;
3083
Michael LeMay28eba5b2006-06-27 02:53:42 -07003084 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 tsec2->exec_sid = tsec1->exec_sid;
3086 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003087 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003088 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
3090 /* Retain ptracer SID across fork, if any.
3091 This will be reset by the ptrace hook upon any
3092 subsequent ptrace_attach operations. */
3093 tsec2->ptrace_sid = tsec1->ptrace_sid;
3094
3095 return 0;
3096}
3097
3098static void selinux_task_free_security(struct task_struct *tsk)
3099{
3100 task_free_security(tsk);
3101}
3102
3103static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3104{
3105 /* Since setuid only affects the current process, and
3106 since the SELinux controls are not based on the Linux
3107 identity attributes, SELinux does not need to control
3108 this operation. However, SELinux does control the use
3109 of the CAP_SETUID and CAP_SETGID capabilities using the
3110 capable hook. */
3111 return 0;
3112}
3113
3114static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3115{
3116 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
3117}
3118
3119static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3120{
3121 /* See the comment for setuid above. */
3122 return 0;
3123}
3124
3125static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3126{
3127 return task_has_perm(current, p, PROCESS__SETPGID);
3128}
3129
3130static int selinux_task_getpgid(struct task_struct *p)
3131{
3132 return task_has_perm(current, p, PROCESS__GETPGID);
3133}
3134
3135static int selinux_task_getsid(struct task_struct *p)
3136{
3137 return task_has_perm(current, p, PROCESS__GETSESSION);
3138}
3139
David Quigleyf9008e42006-06-30 01:55:46 -07003140static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3141{
3142 selinux_get_task_sid(p, secid);
3143}
3144
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145static int selinux_task_setgroups(struct group_info *group_info)
3146{
3147 /* See the comment for setuid above. */
3148 return 0;
3149}
3150
3151static int selinux_task_setnice(struct task_struct *p, int nice)
3152{
3153 int rc;
3154
3155 rc = secondary_ops->task_setnice(p, nice);
3156 if (rc)
3157 return rc;
3158
3159 return task_has_perm(current,p, PROCESS__SETSCHED);
3160}
3161
James Morris03e68062006-06-23 02:03:58 -07003162static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3163{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003164 int rc;
3165
3166 rc = secondary_ops->task_setioprio(p, ioprio);
3167 if (rc)
3168 return rc;
3169
James Morris03e68062006-06-23 02:03:58 -07003170 return task_has_perm(current, p, PROCESS__SETSCHED);
3171}
3172
David Quigleya1836a42006-06-30 01:55:49 -07003173static int selinux_task_getioprio(struct task_struct *p)
3174{
3175 return task_has_perm(current, p, PROCESS__GETSCHED);
3176}
3177
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3179{
3180 struct rlimit *old_rlim = current->signal->rlim + resource;
3181 int rc;
3182
3183 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3184 if (rc)
3185 return rc;
3186
3187 /* Control the ability to change the hard limit (whether
3188 lowering or raising it), so that the hard limit can
3189 later be used as a safe reset point for the soft limit
3190 upon context transitions. See selinux_bprm_apply_creds. */
3191 if (old_rlim->rlim_max != new_rlim->rlim_max)
3192 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3193
3194 return 0;
3195}
3196
3197static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3198{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003199 int rc;
3200
3201 rc = secondary_ops->task_setscheduler(p, policy, lp);
3202 if (rc)
3203 return rc;
3204
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 return task_has_perm(current, p, PROCESS__SETSCHED);
3206}
3207
3208static int selinux_task_getscheduler(struct task_struct *p)
3209{
3210 return task_has_perm(current, p, PROCESS__GETSCHED);
3211}
3212
David Quigley35601542006-06-23 02:04:01 -07003213static int selinux_task_movememory(struct task_struct *p)
3214{
3215 return task_has_perm(current, p, PROCESS__SETSCHED);
3216}
3217
David Quigleyf9008e42006-06-30 01:55:46 -07003218static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3219 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220{
3221 u32 perm;
3222 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003223 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
David Quigleyf9008e42006-06-30 01:55:46 -07003225 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 if (rc)
3227 return rc;
3228
Oleg Nesterov621d3122005-10-30 15:03:45 -08003229 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 return 0;
3231
3232 if (!sig)
3233 perm = PROCESS__SIGNULL; /* null signal; existence test */
3234 else
3235 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003236 tsec = p->security;
3237 if (secid)
3238 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3239 else
3240 rc = task_has_perm(current, p, perm);
3241 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242}
3243
3244static int selinux_task_prctl(int option,
3245 unsigned long arg2,
3246 unsigned long arg3,
3247 unsigned long arg4,
3248 unsigned long arg5)
3249{
3250 /* The current prctl operations do not appear to require
3251 any SELinux controls since they merely observe or modify
3252 the state of the current process. */
3253 return 0;
3254}
3255
3256static int selinux_task_wait(struct task_struct *p)
3257{
Eric Paris8a535142007-10-22 16:10:31 -04003258 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259}
3260
3261static void selinux_task_reparent_to_init(struct task_struct *p)
3262{
3263 struct task_security_struct *tsec;
3264
3265 secondary_ops->task_reparent_to_init(p);
3266
3267 tsec = p->security;
3268 tsec->osid = tsec->sid;
3269 tsec->sid = SECINITSID_KERNEL;
3270 return;
3271}
3272
3273static void selinux_task_to_inode(struct task_struct *p,
3274 struct inode *inode)
3275{
3276 struct task_security_struct *tsec = p->security;
3277 struct inode_security_struct *isec = inode->i_security;
3278
3279 isec->sid = tsec->sid;
3280 isec->initialized = 1;
3281 return;
3282}
3283
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003285static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3286 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287{
3288 int offset, ihlen, ret = -EINVAL;
3289 struct iphdr _iph, *ih;
3290
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003291 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3293 if (ih == NULL)
3294 goto out;
3295
3296 ihlen = ih->ihl * 4;
3297 if (ihlen < sizeof(_iph))
3298 goto out;
3299
3300 ad->u.net.v4info.saddr = ih->saddr;
3301 ad->u.net.v4info.daddr = ih->daddr;
3302 ret = 0;
3303
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003304 if (proto)
3305 *proto = ih->protocol;
3306
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 switch (ih->protocol) {
3308 case IPPROTO_TCP: {
3309 struct tcphdr _tcph, *th;
3310
3311 if (ntohs(ih->frag_off) & IP_OFFSET)
3312 break;
3313
3314 offset += ihlen;
3315 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3316 if (th == NULL)
3317 break;
3318
3319 ad->u.net.sport = th->source;
3320 ad->u.net.dport = th->dest;
3321 break;
3322 }
3323
3324 case IPPROTO_UDP: {
3325 struct udphdr _udph, *uh;
3326
3327 if (ntohs(ih->frag_off) & IP_OFFSET)
3328 break;
3329
3330 offset += ihlen;
3331 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3332 if (uh == NULL)
3333 break;
3334
3335 ad->u.net.sport = uh->source;
3336 ad->u.net.dport = uh->dest;
3337 break;
3338 }
3339
James Morris2ee92d42006-11-13 16:09:01 -08003340 case IPPROTO_DCCP: {
3341 struct dccp_hdr _dccph, *dh;
3342
3343 if (ntohs(ih->frag_off) & IP_OFFSET)
3344 break;
3345
3346 offset += ihlen;
3347 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3348 if (dh == NULL)
3349 break;
3350
3351 ad->u.net.sport = dh->dccph_sport;
3352 ad->u.net.dport = dh->dccph_dport;
3353 break;
3354 }
3355
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 default:
3357 break;
3358 }
3359out:
3360 return ret;
3361}
3362
3363#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3364
3365/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003366static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3367 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
3369 u8 nexthdr;
3370 int ret = -EINVAL, offset;
3371 struct ipv6hdr _ipv6h, *ip6;
3372
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003373 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3375 if (ip6 == NULL)
3376 goto out;
3377
3378 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3379 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3380 ret = 0;
3381
3382 nexthdr = ip6->nexthdr;
3383 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003384 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 if (offset < 0)
3386 goto out;
3387
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003388 if (proto)
3389 *proto = nexthdr;
3390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 switch (nexthdr) {
3392 case IPPROTO_TCP: {
3393 struct tcphdr _tcph, *th;
3394
3395 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3396 if (th == NULL)
3397 break;
3398
3399 ad->u.net.sport = th->source;
3400 ad->u.net.dport = th->dest;
3401 break;
3402 }
3403
3404 case IPPROTO_UDP: {
3405 struct udphdr _udph, *uh;
3406
3407 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3408 if (uh == NULL)
3409 break;
3410
3411 ad->u.net.sport = uh->source;
3412 ad->u.net.dport = uh->dest;
3413 break;
3414 }
3415
James Morris2ee92d42006-11-13 16:09:01 -08003416 case IPPROTO_DCCP: {
3417 struct dccp_hdr _dccph, *dh;
3418
3419 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3420 if (dh == NULL)
3421 break;
3422
3423 ad->u.net.sport = dh->dccph_sport;
3424 ad->u.net.dport = dh->dccph_dport;
3425 break;
3426 }
3427
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 /* includes fragments */
3429 default:
3430 break;
3431 }
3432out:
3433 return ret;
3434}
3435
3436#endif /* IPV6 */
3437
3438static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003439 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440{
3441 int ret = 0;
3442
3443 switch (ad->u.net.family) {
3444 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003445 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 if (ret || !addrp)
3447 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3449 &ad->u.net.v4info.daddr);
3450 break;
3451
3452#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3453 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003454 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 if (ret || !addrp)
3456 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3458 &ad->u.net.v6info.daddr);
3459 break;
3460#endif /* IPV6 */
3461 default:
3462 break;
3463 }
3464
Paul Moore71f1cb02008-01-29 08:51:16 -05003465 if (unlikely(ret))
3466 printk(KERN_WARNING
3467 "SELinux: failure in selinux_parse_skb(),"
3468 " unable to parse packet\n");
3469
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 return ret;
3471}
3472
Paul Moore4f6a9932007-03-01 14:35:22 -05003473/**
Paul Moore220deb92008-01-29 08:38:23 -05003474 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003475 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003476 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003477 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003478 *
3479 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003480 * Check the various different forms of network peer labeling and determine
3481 * the peer label/SID for the packet; most of the magic actually occurs in
3482 * the security server function security_net_peersid_cmp(). The function
3483 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3484 * or -EACCES if @sid is invalid due to inconsistencies with the different
3485 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003486 *
3487 */
Paul Moore220deb92008-01-29 08:38:23 -05003488static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003489{
Paul Moore71f1cb02008-01-29 08:51:16 -05003490 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003491 u32 xfrm_sid;
3492 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003493 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003494
3495 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003496 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003497
Paul Moore71f1cb02008-01-29 08:51:16 -05003498 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3499 if (unlikely(err)) {
3500 printk(KERN_WARNING
3501 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3502 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003503 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003504 }
Paul Moore220deb92008-01-29 08:38:23 -05003505
3506 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003507}
3508
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509/* socket security operations */
3510static int socket_has_perm(struct task_struct *task, struct socket *sock,
3511 u32 perms)
3512{
3513 struct inode_security_struct *isec;
3514 struct task_security_struct *tsec;
3515 struct avc_audit_data ad;
3516 int err = 0;
3517
3518 tsec = task->security;
3519 isec = SOCK_INODE(sock)->i_security;
3520
3521 if (isec->sid == SECINITSID_KERNEL)
3522 goto out;
3523
3524 AVC_AUDIT_DATA_INIT(&ad,NET);
3525 ad.u.net.sk = sock->sk;
3526 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3527
3528out:
3529 return err;
3530}
3531
3532static int selinux_socket_create(int family, int type,
3533 int protocol, int kern)
3534{
3535 int err = 0;
3536 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003537 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
3539 if (kern)
3540 goto out;
3541
3542 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003543 newsid = tsec->sockcreate_sid ? : tsec->sid;
3544 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 socket_type_to_security_class(family, type,
3546 protocol), SOCKET__CREATE, NULL);
3547
3548out:
3549 return err;
3550}
3551
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003552static int selinux_socket_post_create(struct socket *sock, int family,
3553 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003555 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 struct inode_security_struct *isec;
3557 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003558 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003559 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
3561 isec = SOCK_INODE(sock)->i_security;
3562
3563 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003564 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003566 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 isec->initialized = 1;
3568
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003569 if (sock->sk) {
3570 sksec = sock->sk->sk_security;
3571 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003572 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003573 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003574 }
3575
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003576 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577}
3578
3579/* Range of port numbers used to automatically bind.
3580 Need to determine whether we should perform a name_bind
3581 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
3583static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3584{
3585 u16 family;
3586 int err;
3587
3588 err = socket_has_perm(current, sock, SOCKET__BIND);
3589 if (err)
3590 goto out;
3591
3592 /*
3593 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003594 * Multiple address binding for SCTP is not supported yet: we just
3595 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 */
3597 family = sock->sk->sk_family;
3598 if (family == PF_INET || family == PF_INET6) {
3599 char *addrp;
3600 struct inode_security_struct *isec;
3601 struct task_security_struct *tsec;
3602 struct avc_audit_data ad;
3603 struct sockaddr_in *addr4 = NULL;
3604 struct sockaddr_in6 *addr6 = NULL;
3605 unsigned short snum;
3606 struct sock *sk = sock->sk;
3607 u32 sid, node_perm, addrlen;
3608
3609 tsec = current->security;
3610 isec = SOCK_INODE(sock)->i_security;
3611
3612 if (family == PF_INET) {
3613 addr4 = (struct sockaddr_in *)address;
3614 snum = ntohs(addr4->sin_port);
3615 addrlen = sizeof(addr4->sin_addr.s_addr);
3616 addrp = (char *)&addr4->sin_addr.s_addr;
3617 } else {
3618 addr6 = (struct sockaddr_in6 *)address;
3619 snum = ntohs(addr6->sin6_port);
3620 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3621 addrp = (char *)&addr6->sin6_addr.s6_addr;
3622 }
3623
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003624 if (snum) {
3625 int low, high;
3626
3627 inet_get_local_port_range(&low, &high);
3628
3629 if (snum < max(PROT_SOCK, low) || snum > high) {
3630 err = security_port_sid(sk->sk_family,
3631 sk->sk_type,
3632 sk->sk_protocol, snum,
3633 &sid);
3634 if (err)
3635 goto out;
3636 AVC_AUDIT_DATA_INIT(&ad,NET);
3637 ad.u.net.sport = htons(snum);
3638 ad.u.net.family = family;
3639 err = avc_has_perm(isec->sid, sid,
3640 isec->sclass,
3641 SOCKET__NAME_BIND, &ad);
3642 if (err)
3643 goto out;
3644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 }
3646
James Morris13402582005-09-30 14:24:34 -04003647 switch(isec->sclass) {
3648 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 node_perm = TCP_SOCKET__NODE_BIND;
3650 break;
3651
James Morris13402582005-09-30 14:24:34 -04003652 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 node_perm = UDP_SOCKET__NODE_BIND;
3654 break;
James Morris2ee92d42006-11-13 16:09:01 -08003655
3656 case SECCLASS_DCCP_SOCKET:
3657 node_perm = DCCP_SOCKET__NODE_BIND;
3658 break;
3659
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 default:
3661 node_perm = RAWIP_SOCKET__NODE_BIND;
3662 break;
3663 }
3664
Paul Moore224dfbd2008-01-29 08:38:13 -05003665 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 if (err)
3667 goto out;
3668
3669 AVC_AUDIT_DATA_INIT(&ad,NET);
3670 ad.u.net.sport = htons(snum);
3671 ad.u.net.family = family;
3672
3673 if (family == PF_INET)
3674 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3675 else
3676 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3677
3678 err = avc_has_perm(isec->sid, sid,
3679 isec->sclass, node_perm, &ad);
3680 if (err)
3681 goto out;
3682 }
3683out:
3684 return err;
3685}
3686
3687static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3688{
3689 struct inode_security_struct *isec;
3690 int err;
3691
3692 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3693 if (err)
3694 return err;
3695
3696 /*
James Morris2ee92d42006-11-13 16:09:01 -08003697 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 */
3699 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003700 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3701 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 struct sock *sk = sock->sk;
3703 struct avc_audit_data ad;
3704 struct sockaddr_in *addr4 = NULL;
3705 struct sockaddr_in6 *addr6 = NULL;
3706 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003707 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
3709 if (sk->sk_family == PF_INET) {
3710 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003711 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 return -EINVAL;
3713 snum = ntohs(addr4->sin_port);
3714 } else {
3715 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003716 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 return -EINVAL;
3718 snum = ntohs(addr6->sin6_port);
3719 }
3720
3721 err = security_port_sid(sk->sk_family, sk->sk_type,
3722 sk->sk_protocol, snum, &sid);
3723 if (err)
3724 goto out;
3725
James Morris2ee92d42006-11-13 16:09:01 -08003726 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3727 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3728
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 AVC_AUDIT_DATA_INIT(&ad,NET);
3730 ad.u.net.dport = htons(snum);
3731 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003732 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 if (err)
3734 goto out;
3735 }
3736
3737out:
3738 return err;
3739}
3740
3741static int selinux_socket_listen(struct socket *sock, int backlog)
3742{
3743 return socket_has_perm(current, sock, SOCKET__LISTEN);
3744}
3745
3746static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3747{
3748 int err;
3749 struct inode_security_struct *isec;
3750 struct inode_security_struct *newisec;
3751
3752 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3753 if (err)
3754 return err;
3755
3756 newisec = SOCK_INODE(newsock)->i_security;
3757
3758 isec = SOCK_INODE(sock)->i_security;
3759 newisec->sclass = isec->sclass;
3760 newisec->sid = isec->sid;
3761 newisec->initialized = 1;
3762
3763 return 0;
3764}
3765
3766static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3767 int size)
3768{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003769 int rc;
3770
3771 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3772 if (rc)
3773 return rc;
3774
3775 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776}
3777
3778static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3779 int size, int flags)
3780{
3781 return socket_has_perm(current, sock, SOCKET__READ);
3782}
3783
3784static int selinux_socket_getsockname(struct socket *sock)
3785{
3786 return socket_has_perm(current, sock, SOCKET__GETATTR);
3787}
3788
3789static int selinux_socket_getpeername(struct socket *sock)
3790{
3791 return socket_has_perm(current, sock, SOCKET__GETATTR);
3792}
3793
3794static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3795{
Paul Mooref8687af2006-10-30 15:22:15 -08003796 int err;
3797
3798 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3799 if (err)
3800 return err;
3801
3802 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803}
3804
3805static int selinux_socket_getsockopt(struct socket *sock, int level,
3806 int optname)
3807{
3808 return socket_has_perm(current, sock, SOCKET__GETOPT);
3809}
3810
3811static int selinux_socket_shutdown(struct socket *sock, int how)
3812{
3813 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3814}
3815
3816static int selinux_socket_unix_stream_connect(struct socket *sock,
3817 struct socket *other,
3818 struct sock *newsk)
3819{
3820 struct sk_security_struct *ssec;
3821 struct inode_security_struct *isec;
3822 struct inode_security_struct *other_isec;
3823 struct avc_audit_data ad;
3824 int err;
3825
3826 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3827 if (err)
3828 return 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,
3838 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3839 if (err)
3840 return err;
3841
3842 /* connecting socket */
3843 ssec = sock->sk->sk_security;
3844 ssec->peer_sid = other_isec->sid;
3845
3846 /* server child socket */
3847 ssec = newsk->sk_security;
3848 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003849 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3850
3851 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852}
3853
3854static int selinux_socket_unix_may_send(struct socket *sock,
3855 struct socket *other)
3856{
3857 struct inode_security_struct *isec;
3858 struct inode_security_struct *other_isec;
3859 struct avc_audit_data ad;
3860 int err;
3861
3862 isec = SOCK_INODE(sock)->i_security;
3863 other_isec = SOCK_INODE(other)->i_security;
3864
3865 AVC_AUDIT_DATA_INIT(&ad,NET);
3866 ad.u.net.sk = other->sk;
3867
3868 err = avc_has_perm(isec->sid, other_isec->sid,
3869 isec->sclass, SOCKET__SENDTO, &ad);
3870 if (err)
3871 return err;
3872
3873 return 0;
3874}
3875
Paul Mooreeffad8d2008-01-29 08:49:27 -05003876static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3877 u32 peer_sid,
3878 struct avc_audit_data *ad)
3879{
3880 int err;
3881 u32 if_sid;
3882 u32 node_sid;
3883
3884 err = sel_netif_sid(ifindex, &if_sid);
3885 if (err)
3886 return err;
3887 err = avc_has_perm(peer_sid, if_sid,
3888 SECCLASS_NETIF, NETIF__INGRESS, ad);
3889 if (err)
3890 return err;
3891
3892 err = sel_netnode_sid(addrp, family, &node_sid);
3893 if (err)
3894 return err;
3895 return avc_has_perm(peer_sid, node_sid,
3896 SECCLASS_NODE, NODE__RECVFROM, ad);
3897}
3898
Paul Moore220deb92008-01-29 08:38:23 -05003899static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3900 struct sk_buff *skb,
3901 struct avc_audit_data *ad,
3902 u16 family,
3903 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904{
Paul Moore220deb92008-01-29 08:38:23 -05003905 int err;
3906 struct sk_security_struct *sksec = sk->sk_security;
3907 u16 sk_class;
3908 u32 netif_perm, node_perm, recv_perm;
3909 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003910
Paul Moore220deb92008-01-29 08:38:23 -05003911 sk_sid = sksec->sid;
3912 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
Paul Moore220deb92008-01-29 08:38:23 -05003914 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 case SECCLASS_UDP_SOCKET:
3916 netif_perm = NETIF__UDP_RECV;
3917 node_perm = NODE__UDP_RECV;
3918 recv_perm = UDP_SOCKET__RECV_MSG;
3919 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 case SECCLASS_TCP_SOCKET:
3921 netif_perm = NETIF__TCP_RECV;
3922 node_perm = NODE__TCP_RECV;
3923 recv_perm = TCP_SOCKET__RECV_MSG;
3924 break;
James Morris2ee92d42006-11-13 16:09:01 -08003925 case SECCLASS_DCCP_SOCKET:
3926 netif_perm = NETIF__DCCP_RECV;
3927 node_perm = NODE__DCCP_RECV;
3928 recv_perm = DCCP_SOCKET__RECV_MSG;
3929 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 default:
3931 netif_perm = NETIF__RAWIP_RECV;
3932 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003933 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 break;
3935 }
3936
Paul Moore220deb92008-01-29 08:38:23 -05003937 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003939 return err;
3940 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3941 if (err)
3942 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
Paul Moore224dfbd2008-01-29 08:38:13 -05003944 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003946 return err;
3947 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003949 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Paul Moore220deb92008-01-29 08:38:23 -05003951 if (!recv_perm)
3952 return 0;
3953 err = security_port_sid(sk->sk_family, sk->sk_type,
3954 sk->sk_protocol, ntohs(ad->u.net.sport),
3955 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05003956 if (unlikely(err)) {
3957 printk(KERN_WARNING
3958 "SELinux: failure in"
3959 " selinux_sock_rcv_skb_iptables_compat(),"
3960 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05003961 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05003962 }
Paul Moore220deb92008-01-29 08:38:23 -05003963 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3964}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
Paul Moore220deb92008-01-29 08:38:23 -05003966static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3967 struct avc_audit_data *ad,
3968 u16 family, char *addrp)
3969{
3970 int err;
3971 struct sk_security_struct *sksec = sk->sk_security;
3972 u32 peer_sid;
3973 u32 sk_sid = sksec->sid;
3974
3975 if (selinux_compat_net)
3976 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3977 family, addrp);
3978 else
3979 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3980 PACKET__RECV, ad);
3981 if (err)
3982 return err;
3983
3984 if (selinux_policycap_netpeer) {
3985 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003987 return err;
3988 err = avc_has_perm(sk_sid, peer_sid,
3989 SECCLASS_PEER, PEER__RECV, ad);
3990 } else {
3991 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3992 if (err)
3993 return err;
3994 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003996
James Morris4e5ab4c2006-06-09 00:33:33 -07003997 return err;
3998}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003999
James Morris4e5ab4c2006-06-09 00:33:33 -07004000static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4001{
Paul Moore220deb92008-01-29 08:38:23 -05004002 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004003 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004004 u16 family = sk->sk_family;
4005 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004006 struct avc_audit_data ad;
4007 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07004008
James Morris4e5ab4c2006-06-09 00:33:33 -07004009 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004010 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004011
4012 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004013 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004014 family = PF_INET;
4015
James Morris4e5ab4c2006-06-09 00:33:33 -07004016 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004017 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07004018 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004019 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004020 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004021 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004022
Paul Moore220deb92008-01-29 08:38:23 -05004023 /* If any sort of compatibility mode is enabled then handoff processing
4024 * to the selinux_sock_rcv_skb_compat() function to deal with the
4025 * special handling. We do this in an attempt to keep this function
4026 * as fast and as clean as possible. */
4027 if (selinux_compat_net || !selinux_policycap_netpeer)
4028 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4029 family, addrp);
4030
Paul Moored621d352008-01-29 08:43:36 -05004031 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4032 u32 peer_sid;
4033
4034 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4035 if (err)
4036 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004037 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4038 peer_sid, &ad);
4039 if (err)
4040 return err;
Paul Moored621d352008-01-29 08:43:36 -05004041 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4042 PEER__RECV, &ad);
4043 }
4044
Paul Mooreeffad8d2008-01-29 08:49:27 -05004045 if (selinux_secmark_enabled()) {
4046 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4047 PACKET__RECV, &ad);
4048 if (err)
4049 return err;
4050 }
4051
Paul Moored621d352008-01-29 08:43:36 -05004052 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053}
4054
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004055static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4056 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057{
4058 int err = 0;
4059 char *scontext;
4060 u32 scontext_len;
4061 struct sk_security_struct *ssec;
4062 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004063 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
4065 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004066
Paul Moore3de4bab2006-11-17 17:38:54 -05004067 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4068 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004069 ssec = sock->sk->sk_security;
4070 peer_sid = ssec->peer_sid;
4071 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004072 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 err = -ENOPROTOOPT;
4074 goto out;
4075 }
4076
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004077 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 if (err)
4080 goto out;
4081
4082 if (scontext_len > len) {
4083 err = -ERANGE;
4084 goto out_len;
4085 }
4086
4087 if (copy_to_user(optval, scontext, scontext_len))
4088 err = -EFAULT;
4089
4090out_len:
4091 if (put_user(scontext_len, optlen))
4092 err = -EFAULT;
4093
4094 kfree(scontext);
4095out:
4096 return err;
4097}
4098
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004099static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004100{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004101 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004102 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004103
Paul Moore75e22912008-01-29 08:38:04 -05004104 if (sock)
4105 family = sock->sk->sk_family;
4106 else if (skb && skb->sk)
4107 family = skb->sk->sk_family;
4108 else
4109 goto out;
4110
4111 if (sock && family == PF_UNIX)
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004112 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004113 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004114 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004115
Paul Moore75e22912008-01-29 08:38:04 -05004116out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004117 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004118 if (peer_secid == SECSID_NULL)
4119 return -EINVAL;
4120 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004121}
4122
Al Viro7d877f32005-10-21 03:20:43 -04004123static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
4125 return sk_alloc_security(sk, family, priority);
4126}
4127
4128static void selinux_sk_free_security(struct sock *sk)
4129{
4130 sk_free_security(sk);
4131}
4132
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004133static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4134{
4135 struct sk_security_struct *ssec = sk->sk_security;
4136 struct sk_security_struct *newssec = newsk->sk_security;
4137
4138 newssec->sid = ssec->sid;
4139 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004140 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004141
Paul Moore9f2ad662006-11-17 17:38:53 -05004142 selinux_netlbl_sk_security_clone(ssec, newssec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004143}
4144
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004145static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004146{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004147 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004148 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004149 else {
4150 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004151
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004152 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004153 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004154}
4155
Adrian Bunk9a673e52006-08-15 00:03:53 -07004156static void selinux_sock_graft(struct sock* sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004157{
4158 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4159 struct sk_security_struct *sksec = sk->sk_security;
4160
David Woodhouse2148ccc2006-09-29 15:50:25 -07004161 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4162 sk->sk_family == PF_UNIX)
4163 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004164 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004165
4166 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004167}
4168
Adrian Bunk9a673e52006-08-15 00:03:53 -07004169static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4170 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004171{
4172 struct sk_security_struct *sksec = sk->sk_security;
4173 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004174 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004175 u32 peersid;
4176
Paul Moore220deb92008-01-29 08:38:23 -05004177 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4178 if (err)
4179 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004180 if (peersid == SECSID_NULL) {
4181 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004182 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004183 return 0;
4184 }
4185
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004186 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4187 if (err)
4188 return err;
4189
4190 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004191 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004192 return 0;
4193}
4194
Adrian Bunk9a673e52006-08-15 00:03:53 -07004195static void selinux_inet_csk_clone(struct sock *newsk,
4196 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004197{
4198 struct sk_security_struct *newsksec = newsk->sk_security;
4199
4200 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004201 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004202 /* NOTE: Ideally, we should also get the isec->sid for the
4203 new socket in sync, but we don't have the isec available yet.
4204 So we will wait until sock_graft to do it, by which
4205 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004206
Paul Moore9f2ad662006-11-17 17:38:53 -05004207 /* We don't need to take any sort of lock here as we are the only
4208 * thread with access to newsksec */
4209 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004210}
4211
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004212static void selinux_inet_conn_established(struct sock *sk,
4213 struct sk_buff *skb)
4214{
4215 struct sk_security_struct *sksec = sk->sk_security;
4216
Paul Moore220deb92008-01-29 08:38:23 -05004217 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004218}
4219
Adrian Bunk9a673e52006-08-15 00:03:53 -07004220static void selinux_req_classify_flow(const struct request_sock *req,
4221 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004222{
4223 fl->secid = req->secid;
4224}
4225
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4227{
4228 int err = 0;
4229 u32 perm;
4230 struct nlmsghdr *nlh;
4231 struct socket *sock = sk->sk_socket;
4232 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4233
4234 if (skb->len < NLMSG_SPACE(0)) {
4235 err = -EINVAL;
4236 goto out;
4237 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004238 nlh = nlmsg_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
4240 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4241 if (err) {
4242 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004243 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 "SELinux: unrecognized netlink message"
4245 " type=%hu for sclass=%hu\n",
4246 nlh->nlmsg_type, isec->sclass);
4247 if (!selinux_enforcing)
4248 err = 0;
4249 }
4250
4251 /* Ignore */
4252 if (err == -ENOENT)
4253 err = 0;
4254 goto out;
4255 }
4256
4257 err = socket_has_perm(current, sock, perm);
4258out:
4259 return err;
4260}
4261
4262#ifdef CONFIG_NETFILTER
4263
Paul Mooreeffad8d2008-01-29 08:49:27 -05004264static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4265 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004267 char *addrp;
4268 u32 peer_sid;
4269 struct avc_audit_data ad;
4270 u8 secmark_active;
4271 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004272
Paul Mooreeffad8d2008-01-29 08:49:27 -05004273 if (!selinux_policycap_netpeer)
4274 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004275
Paul Mooreeffad8d2008-01-29 08:49:27 -05004276 secmark_active = selinux_secmark_enabled();
4277 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4278 if (!secmark_active && !peerlbl_active)
4279 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004280
Paul Mooreeffad8d2008-01-29 08:49:27 -05004281 AVC_AUDIT_DATA_INIT(&ad, NET);
4282 ad.u.net.netif = ifindex;
4283 ad.u.net.family = family;
4284 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4285 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
Paul Mooreeffad8d2008-01-29 08:49:27 -05004287 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4288 return NF_DROP;
4289
4290 if (peerlbl_active)
4291 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4292 peer_sid, &ad) != 0)
4293 return NF_DROP;
4294
4295 if (secmark_active)
4296 if (avc_has_perm(peer_sid, skb->secmark,
4297 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4298 return NF_DROP;
4299
4300 return NF_ACCEPT;
4301}
4302
4303static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4304 struct sk_buff *skb,
4305 const struct net_device *in,
4306 const struct net_device *out,
4307 int (*okfn)(struct sk_buff *))
4308{
4309 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4310}
4311
4312#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4313static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4314 struct sk_buff *skb,
4315 const struct net_device *in,
4316 const struct net_device *out,
4317 int (*okfn)(struct sk_buff *))
4318{
4319 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4320}
4321#endif /* IPV6 */
4322
4323static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4324 int ifindex,
4325 struct avc_audit_data *ad,
4326 u16 family, char *addrp)
4327{
4328 int err;
4329 struct sk_security_struct *sksec = sk->sk_security;
4330 u16 sk_class;
4331 u32 netif_perm, node_perm, send_perm;
4332 u32 port_sid, node_sid, if_sid, sk_sid;
4333
4334 sk_sid = sksec->sid;
4335 sk_class = sksec->sclass;
4336
4337 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 case SECCLASS_UDP_SOCKET:
4339 netif_perm = NETIF__UDP_SEND;
4340 node_perm = NODE__UDP_SEND;
4341 send_perm = UDP_SOCKET__SEND_MSG;
4342 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 case SECCLASS_TCP_SOCKET:
4344 netif_perm = NETIF__TCP_SEND;
4345 node_perm = NODE__TCP_SEND;
4346 send_perm = TCP_SOCKET__SEND_MSG;
4347 break;
James Morris2ee92d42006-11-13 16:09:01 -08004348 case SECCLASS_DCCP_SOCKET:
4349 netif_perm = NETIF__DCCP_SEND;
4350 node_perm = NODE__DCCP_SEND;
4351 send_perm = DCCP_SOCKET__SEND_MSG;
4352 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 default:
4354 netif_perm = NETIF__RAWIP_SEND;
4355 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004356 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 break;
4358 }
4359
Paul Mooreeffad8d2008-01-29 08:49:27 -05004360 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004361 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004362 return err;
4363 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4364 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Paul Moore224dfbd2008-01-29 08:38:13 -05004366 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004367 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004368 return err;
4369 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004370 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004371 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Paul Mooreeffad8d2008-01-29 08:49:27 -05004373 if (send_perm != 0)
4374 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Paul Mooreeffad8d2008-01-29 08:49:27 -05004376 err = security_port_sid(sk->sk_family, sk->sk_type,
4377 sk->sk_protocol, ntohs(ad->u.net.dport),
4378 &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004379 if (unlikely(err)) {
4380 printk(KERN_WARNING
4381 "SELinux: failure in"
4382 " selinux_ip_postroute_iptables_compat(),"
4383 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004384 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004385 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004386 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004387}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Paul Mooreeffad8d2008-01-29 08:49:27 -05004389static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4390 int ifindex,
4391 struct avc_audit_data *ad,
4392 u16 family,
4393 char *addrp,
4394 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004395{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004396 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004397 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004398
Paul Mooreeffad8d2008-01-29 08:49:27 -05004399 if (sk == NULL)
4400 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004401 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004402
Paul Mooreeffad8d2008-01-29 08:49:27 -05004403 if (selinux_compat_net) {
4404 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4405 ad, family, addrp))
4406 return NF_DROP;
4407 } else {
4408 if (avc_has_perm(sksec->sid, skb->secmark,
4409 SECCLASS_PACKET, PACKET__SEND, ad))
4410 return NF_DROP;
4411 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004412
Paul Mooreeffad8d2008-01-29 08:49:27 -05004413 if (selinux_policycap_netpeer)
4414 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4415 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004416
Paul Mooreeffad8d2008-01-29 08:49:27 -05004417 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418}
4419
Paul Mooreeffad8d2008-01-29 08:49:27 -05004420static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4421 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004423 u32 secmark_perm;
4424 u32 peer_sid;
4425 struct sock *sk;
4426 struct avc_audit_data ad;
4427 char *addrp;
4428 u8 proto;
4429 u8 secmark_active;
4430 u8 peerlbl_active;
4431
4432 AVC_AUDIT_DATA_INIT(&ad, NET);
4433 ad.u.net.netif = ifindex;
4434 ad.u.net.family = family;
4435 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4436 return NF_DROP;
4437
4438 /* If any sort of compatibility mode is enabled then handoff processing
4439 * to the selinux_ip_postroute_compat() function to deal with the
4440 * special handling. We do this in an attempt to keep this function
4441 * as fast and as clean as possible. */
4442 if (selinux_compat_net || !selinux_policycap_netpeer)
4443 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4444 family, addrp, proto);
4445
4446 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4447 * packet transformation so allow the packet to pass without any checks
4448 * since we'll have another chance to perform access control checks
4449 * when the packet is on it's final way out.
4450 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4451 * is NULL, in this case go ahead and apply access control. */
4452 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4453 return NF_ACCEPT;
4454
4455 secmark_active = selinux_secmark_enabled();
4456 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4457 if (!secmark_active && !peerlbl_active)
4458 return NF_ACCEPT;
4459
4460 /* if the packet is locally generated (skb->sk != NULL) then use the
4461 * socket's label as the peer label, otherwise the packet is being
4462 * forwarded through this system and we need to fetch the peer label
4463 * directly from the packet */
4464 sk = skb->sk;
4465 if (sk) {
4466 struct sk_security_struct *sksec = sk->sk_security;
4467 peer_sid = sksec->sid;
4468 secmark_perm = PACKET__SEND;
4469 } else {
4470 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4471 return NF_DROP;
4472 secmark_perm = PACKET__FORWARD_OUT;
4473 }
4474
4475 if (secmark_active)
4476 if (avc_has_perm(peer_sid, skb->secmark,
4477 SECCLASS_PACKET, secmark_perm, &ad))
4478 return NF_DROP;
4479
4480 if (peerlbl_active) {
4481 u32 if_sid;
4482 u32 node_sid;
4483
4484 if (sel_netif_sid(ifindex, &if_sid))
4485 return NF_DROP;
4486 if (avc_has_perm(peer_sid, if_sid,
4487 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4488 return NF_DROP;
4489
4490 if (sel_netnode_sid(addrp, family, &node_sid))
4491 return NF_DROP;
4492 if (avc_has_perm(peer_sid, node_sid,
4493 SECCLASS_NODE, NODE__SENDTO, &ad))
4494 return NF_DROP;
4495 }
4496
4497 return NF_ACCEPT;
4498}
4499
4500static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4501 struct sk_buff *skb,
4502 const struct net_device *in,
4503 const struct net_device *out,
4504 int (*okfn)(struct sk_buff *))
4505{
4506 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507}
4508
4509#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004510static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4511 struct sk_buff *skb,
4512 const struct net_device *in,
4513 const struct net_device *out,
4514 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004516 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518#endif /* IPV6 */
4519
4520#endif /* CONFIG_NETFILTER */
4521
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4523{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 int err;
4525
4526 err = secondary_ops->netlink_send(sk, skb);
4527 if (err)
4528 return err;
4529
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4531 err = selinux_nlmsg_perm(sk, skb);
4532
4533 return err;
4534}
4535
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004536static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004538 int err;
4539 struct avc_audit_data ad;
4540
4541 err = secondary_ops->netlink_recv(skb, capability);
4542 if (err)
4543 return err;
4544
4545 AVC_AUDIT_DATA_INIT(&ad, CAP);
4546 ad.u.cap = capability;
4547
4548 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
4549 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550}
4551
4552static int ipc_alloc_security(struct task_struct *task,
4553 struct kern_ipc_perm *perm,
4554 u16 sclass)
4555{
4556 struct task_security_struct *tsec = task->security;
4557 struct ipc_security_struct *isec;
4558
James Morris89d155e2005-10-30 14:59:21 -08004559 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 if (!isec)
4561 return -ENOMEM;
4562
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 isec->sclass = sclass;
4564 isec->ipc_perm = perm;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004565 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 perm->security = isec;
4567
4568 return 0;
4569}
4570
4571static void ipc_free_security(struct kern_ipc_perm *perm)
4572{
4573 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574 perm->security = NULL;
4575 kfree(isec);
4576}
4577
4578static int msg_msg_alloc_security(struct msg_msg *msg)
4579{
4580 struct msg_security_struct *msec;
4581
James Morris89d155e2005-10-30 14:59:21 -08004582 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 if (!msec)
4584 return -ENOMEM;
4585
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 msec->msg = msg;
4587 msec->sid = SECINITSID_UNLABELED;
4588 msg->security = msec;
4589
4590 return 0;
4591}
4592
4593static void msg_msg_free_security(struct msg_msg *msg)
4594{
4595 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 msg->security = NULL;
4598 kfree(msec);
4599}
4600
4601static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004602 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
4604 struct task_security_struct *tsec;
4605 struct ipc_security_struct *isec;
4606 struct avc_audit_data ad;
4607
4608 tsec = current->security;
4609 isec = ipc_perms->security;
4610
4611 AVC_AUDIT_DATA_INIT(&ad, IPC);
4612 ad.u.ipc_id = ipc_perms->key;
4613
Stephen Smalley6af963f2005-05-01 08:58:39 -07004614 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615}
4616
4617static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4618{
4619 return msg_msg_alloc_security(msg);
4620}
4621
4622static void selinux_msg_msg_free_security(struct msg_msg *msg)
4623{
4624 msg_msg_free_security(msg);
4625}
4626
4627/* message queue security operations */
4628static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4629{
4630 struct task_security_struct *tsec;
4631 struct ipc_security_struct *isec;
4632 struct avc_audit_data ad;
4633 int rc;
4634
4635 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4636 if (rc)
4637 return rc;
4638
4639 tsec = current->security;
4640 isec = msq->q_perm.security;
4641
4642 AVC_AUDIT_DATA_INIT(&ad, IPC);
4643 ad.u.ipc_id = msq->q_perm.key;
4644
4645 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4646 MSGQ__CREATE, &ad);
4647 if (rc) {
4648 ipc_free_security(&msq->q_perm);
4649 return rc;
4650 }
4651 return 0;
4652}
4653
4654static void selinux_msg_queue_free_security(struct msg_queue *msq)
4655{
4656 ipc_free_security(&msq->q_perm);
4657}
4658
4659static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4660{
4661 struct task_security_struct *tsec;
4662 struct ipc_security_struct *isec;
4663 struct avc_audit_data ad;
4664
4665 tsec = current->security;
4666 isec = msq->q_perm.security;
4667
4668 AVC_AUDIT_DATA_INIT(&ad, IPC);
4669 ad.u.ipc_id = msq->q_perm.key;
4670
4671 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4672 MSGQ__ASSOCIATE, &ad);
4673}
4674
4675static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4676{
4677 int err;
4678 int perms;
4679
4680 switch(cmd) {
4681 case IPC_INFO:
4682 case MSG_INFO:
4683 /* No specific object, just general system-wide information. */
4684 return task_has_system(current, SYSTEM__IPC_INFO);
4685 case IPC_STAT:
4686 case MSG_STAT:
4687 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4688 break;
4689 case IPC_SET:
4690 perms = MSGQ__SETATTR;
4691 break;
4692 case IPC_RMID:
4693 perms = MSGQ__DESTROY;
4694 break;
4695 default:
4696 return 0;
4697 }
4698
Stephen Smalley6af963f2005-05-01 08:58:39 -07004699 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700 return err;
4701}
4702
4703static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4704{
4705 struct task_security_struct *tsec;
4706 struct ipc_security_struct *isec;
4707 struct msg_security_struct *msec;
4708 struct avc_audit_data ad;
4709 int rc;
4710
4711 tsec = current->security;
4712 isec = msq->q_perm.security;
4713 msec = msg->security;
4714
4715 /*
4716 * First time through, need to assign label to the message
4717 */
4718 if (msec->sid == SECINITSID_UNLABELED) {
4719 /*
4720 * Compute new sid based on current process and
4721 * message queue this message will be stored in
4722 */
4723 rc = security_transition_sid(tsec->sid,
4724 isec->sid,
4725 SECCLASS_MSG,
4726 &msec->sid);
4727 if (rc)
4728 return rc;
4729 }
4730
4731 AVC_AUDIT_DATA_INIT(&ad, IPC);
4732 ad.u.ipc_id = msq->q_perm.key;
4733
4734 /* Can this process write to the queue? */
4735 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4736 MSGQ__WRITE, &ad);
4737 if (!rc)
4738 /* Can this process send the message */
4739 rc = avc_has_perm(tsec->sid, msec->sid,
4740 SECCLASS_MSG, MSG__SEND, &ad);
4741 if (!rc)
4742 /* Can the message be put in the queue? */
4743 rc = avc_has_perm(msec->sid, isec->sid,
4744 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4745
4746 return rc;
4747}
4748
4749static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4750 struct task_struct *target,
4751 long type, int mode)
4752{
4753 struct task_security_struct *tsec;
4754 struct ipc_security_struct *isec;
4755 struct msg_security_struct *msec;
4756 struct avc_audit_data ad;
4757 int rc;
4758
4759 tsec = target->security;
4760 isec = msq->q_perm.security;
4761 msec = msg->security;
4762
4763 AVC_AUDIT_DATA_INIT(&ad, IPC);
4764 ad.u.ipc_id = msq->q_perm.key;
4765
4766 rc = avc_has_perm(tsec->sid, isec->sid,
4767 SECCLASS_MSGQ, MSGQ__READ, &ad);
4768 if (!rc)
4769 rc = avc_has_perm(tsec->sid, msec->sid,
4770 SECCLASS_MSG, MSG__RECEIVE, &ad);
4771 return rc;
4772}
4773
4774/* Shared Memory security operations */
4775static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4776{
4777 struct task_security_struct *tsec;
4778 struct ipc_security_struct *isec;
4779 struct avc_audit_data ad;
4780 int rc;
4781
4782 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4783 if (rc)
4784 return rc;
4785
4786 tsec = current->security;
4787 isec = shp->shm_perm.security;
4788
4789 AVC_AUDIT_DATA_INIT(&ad, IPC);
4790 ad.u.ipc_id = shp->shm_perm.key;
4791
4792 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4793 SHM__CREATE, &ad);
4794 if (rc) {
4795 ipc_free_security(&shp->shm_perm);
4796 return rc;
4797 }
4798 return 0;
4799}
4800
4801static void selinux_shm_free_security(struct shmid_kernel *shp)
4802{
4803 ipc_free_security(&shp->shm_perm);
4804}
4805
4806static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4807{
4808 struct task_security_struct *tsec;
4809 struct ipc_security_struct *isec;
4810 struct avc_audit_data ad;
4811
4812 tsec = current->security;
4813 isec = shp->shm_perm.security;
4814
4815 AVC_AUDIT_DATA_INIT(&ad, IPC);
4816 ad.u.ipc_id = shp->shm_perm.key;
4817
4818 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4819 SHM__ASSOCIATE, &ad);
4820}
4821
4822/* Note, at this point, shp is locked down */
4823static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4824{
4825 int perms;
4826 int err;
4827
4828 switch(cmd) {
4829 case IPC_INFO:
4830 case SHM_INFO:
4831 /* No specific object, just general system-wide information. */
4832 return task_has_system(current, SYSTEM__IPC_INFO);
4833 case IPC_STAT:
4834 case SHM_STAT:
4835 perms = SHM__GETATTR | SHM__ASSOCIATE;
4836 break;
4837 case IPC_SET:
4838 perms = SHM__SETATTR;
4839 break;
4840 case SHM_LOCK:
4841 case SHM_UNLOCK:
4842 perms = SHM__LOCK;
4843 break;
4844 case IPC_RMID:
4845 perms = SHM__DESTROY;
4846 break;
4847 default:
4848 return 0;
4849 }
4850
Stephen Smalley6af963f2005-05-01 08:58:39 -07004851 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852 return err;
4853}
4854
4855static int selinux_shm_shmat(struct shmid_kernel *shp,
4856 char __user *shmaddr, int shmflg)
4857{
4858 u32 perms;
4859 int rc;
4860
4861 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4862 if (rc)
4863 return rc;
4864
4865 if (shmflg & SHM_RDONLY)
4866 perms = SHM__READ;
4867 else
4868 perms = SHM__READ | SHM__WRITE;
4869
Stephen Smalley6af963f2005-05-01 08:58:39 -07004870 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871}
4872
4873/* Semaphore security operations */
4874static int selinux_sem_alloc_security(struct sem_array *sma)
4875{
4876 struct task_security_struct *tsec;
4877 struct ipc_security_struct *isec;
4878 struct avc_audit_data ad;
4879 int rc;
4880
4881 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4882 if (rc)
4883 return rc;
4884
4885 tsec = current->security;
4886 isec = sma->sem_perm.security;
4887
4888 AVC_AUDIT_DATA_INIT(&ad, IPC);
4889 ad.u.ipc_id = sma->sem_perm.key;
4890
4891 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4892 SEM__CREATE, &ad);
4893 if (rc) {
4894 ipc_free_security(&sma->sem_perm);
4895 return rc;
4896 }
4897 return 0;
4898}
4899
4900static void selinux_sem_free_security(struct sem_array *sma)
4901{
4902 ipc_free_security(&sma->sem_perm);
4903}
4904
4905static int selinux_sem_associate(struct sem_array *sma, int semflg)
4906{
4907 struct task_security_struct *tsec;
4908 struct ipc_security_struct *isec;
4909 struct avc_audit_data ad;
4910
4911 tsec = current->security;
4912 isec = sma->sem_perm.security;
4913
4914 AVC_AUDIT_DATA_INIT(&ad, IPC);
4915 ad.u.ipc_id = sma->sem_perm.key;
4916
4917 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4918 SEM__ASSOCIATE, &ad);
4919}
4920
4921/* Note, at this point, sma is locked down */
4922static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4923{
4924 int err;
4925 u32 perms;
4926
4927 switch(cmd) {
4928 case IPC_INFO:
4929 case SEM_INFO:
4930 /* No specific object, just general system-wide information. */
4931 return task_has_system(current, SYSTEM__IPC_INFO);
4932 case GETPID:
4933 case GETNCNT:
4934 case GETZCNT:
4935 perms = SEM__GETATTR;
4936 break;
4937 case GETVAL:
4938 case GETALL:
4939 perms = SEM__READ;
4940 break;
4941 case SETVAL:
4942 case SETALL:
4943 perms = SEM__WRITE;
4944 break;
4945 case IPC_RMID:
4946 perms = SEM__DESTROY;
4947 break;
4948 case IPC_SET:
4949 perms = SEM__SETATTR;
4950 break;
4951 case IPC_STAT:
4952 case SEM_STAT:
4953 perms = SEM__GETATTR | SEM__ASSOCIATE;
4954 break;
4955 default:
4956 return 0;
4957 }
4958
Stephen Smalley6af963f2005-05-01 08:58:39 -07004959 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960 return err;
4961}
4962
4963static int selinux_sem_semop(struct sem_array *sma,
4964 struct sembuf *sops, unsigned nsops, int alter)
4965{
4966 u32 perms;
4967
4968 if (alter)
4969 perms = SEM__READ | SEM__WRITE;
4970 else
4971 perms = SEM__READ;
4972
Stephen Smalley6af963f2005-05-01 08:58:39 -07004973 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974}
4975
4976static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4977{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978 u32 av = 0;
4979
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980 av = 0;
4981 if (flag & S_IRUGO)
4982 av |= IPC__UNIX_READ;
4983 if (flag & S_IWUGO)
4984 av |= IPC__UNIX_WRITE;
4985
4986 if (av == 0)
4987 return 0;
4988
Stephen Smalley6af963f2005-05-01 08:58:39 -07004989 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990}
4991
4992/* module stacking operations */
4993static int selinux_register_security (const char *name, struct security_operations *ops)
4994{
4995 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05004996 printk(KERN_ERR "%s: There is already a secondary security "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997 "module registered.\n", __FUNCTION__);
4998 return -EINVAL;
4999 }
5000
5001 secondary_ops = ops;
5002
5003 printk(KERN_INFO "%s: Registering secondary module %s\n",
5004 __FUNCTION__,
5005 name);
5006
5007 return 0;
5008}
5009
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
5011{
5012 if (inode)
5013 inode_doinit_with_dentry(inode, dentry);
5014}
5015
5016static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005017 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018{
5019 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005020 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005022 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
5024 if (current != p) {
5025 error = task_has_perm(current, p, PROCESS__GETATTR);
5026 if (error)
5027 return error;
5028 }
5029
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030 tsec = p->security;
5031
5032 if (!strcmp(name, "current"))
5033 sid = tsec->sid;
5034 else if (!strcmp(name, "prev"))
5035 sid = tsec->osid;
5036 else if (!strcmp(name, "exec"))
5037 sid = tsec->exec_sid;
5038 else if (!strcmp(name, "fscreate"))
5039 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005040 else if (!strcmp(name, "keycreate"))
5041 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005042 else if (!strcmp(name, "sockcreate"))
5043 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 else
5045 return -EINVAL;
5046
5047 if (!sid)
5048 return 0;
5049
Al Viro04ff9702007-03-12 16:17:58 +00005050 error = security_sid_to_context(sid, value, &len);
5051 if (error)
5052 return error;
5053 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005054}
5055
5056static int selinux_setprocattr(struct task_struct *p,
5057 char *name, void *value, size_t size)
5058{
5059 struct task_security_struct *tsec;
5060 u32 sid = 0;
5061 int error;
5062 char *str = value;
5063
5064 if (current != p) {
5065 /* SELinux only allows a process to change its own
5066 security attributes. */
5067 return -EACCES;
5068 }
5069
5070 /*
5071 * Basic control over ability to set these attributes at all.
5072 * current == p, but we'll pass them separately in case the
5073 * above restriction is ever removed.
5074 */
5075 if (!strcmp(name, "exec"))
5076 error = task_has_perm(current, p, PROCESS__SETEXEC);
5077 else if (!strcmp(name, "fscreate"))
5078 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005079 else if (!strcmp(name, "keycreate"))
5080 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005081 else if (!strcmp(name, "sockcreate"))
5082 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083 else if (!strcmp(name, "current"))
5084 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5085 else
5086 error = -EINVAL;
5087 if (error)
5088 return error;
5089
5090 /* Obtain a SID for the context, if one was specified. */
5091 if (size && str[1] && str[1] != '\n') {
5092 if (str[size-1] == '\n') {
5093 str[size-1] = 0;
5094 size--;
5095 }
5096 error = security_context_to_sid(value, size, &sid);
5097 if (error)
5098 return error;
5099 }
5100
5101 /* Permission checking based on the specified context is
5102 performed during the actual operation (execve,
5103 open/mkdir/...), when we know the full context of the
5104 operation. See selinux_bprm_set_security for the execve
5105 checks and may_create for the file creation checks. The
5106 operation will then fail if the context is not permitted. */
5107 tsec = p->security;
5108 if (!strcmp(name, "exec"))
5109 tsec->exec_sid = sid;
5110 else if (!strcmp(name, "fscreate"))
5111 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005112 else if (!strcmp(name, "keycreate")) {
5113 error = may_create_key(sid, p);
5114 if (error)
5115 return error;
5116 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005117 } else if (!strcmp(name, "sockcreate"))
5118 tsec->sockcreate_sid = sid;
5119 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 struct av_decision avd;
5121
5122 if (sid == 0)
5123 return -EINVAL;
5124
5125 /* Only allow single threaded processes to change context */
5126 if (atomic_read(&p->mm->mm_users) != 1) {
5127 struct task_struct *g, *t;
5128 struct mm_struct *mm = p->mm;
5129 read_lock(&tasklist_lock);
5130 do_each_thread(g, t)
5131 if (t->mm == mm && t != p) {
5132 read_unlock(&tasklist_lock);
5133 return -EPERM;
5134 }
5135 while_each_thread(g, t);
5136 read_unlock(&tasklist_lock);
5137 }
5138
5139 /* Check permissions for the transition. */
5140 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
5141 PROCESS__DYNTRANSITION, NULL);
5142 if (error)
5143 return error;
5144
5145 /* Check for ptracing, and update the task SID if ok.
5146 Otherwise, leave SID unchanged and fail. */
5147 task_lock(p);
5148 if (p->ptrace & PT_PTRACED) {
5149 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
5150 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005151 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152 if (!error)
5153 tsec->sid = sid;
5154 task_unlock(p);
5155 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
5156 PROCESS__PTRACE, &avd, error, NULL);
5157 if (error)
5158 return error;
5159 } else {
5160 tsec->sid = sid;
5161 task_unlock(p);
5162 }
5163 }
5164 else
5165 return -EINVAL;
5166
5167 return size;
5168}
5169
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005170static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5171{
5172 return security_sid_to_context(secid, secdata, seclen);
5173}
5174
David Howells63cb3442008-01-15 23:47:35 +00005175static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
5176{
5177 return security_context_to_sid(secdata, seclen, secid);
5178}
5179
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005180static void selinux_release_secctx(char *secdata, u32 seclen)
5181{
Paul Moore088999e2007-08-01 11:12:58 -04005182 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005183}
5184
Michael LeMayd7200242006-06-22 14:47:17 -07005185#ifdef CONFIG_KEYS
5186
David Howells7e047ef2006-06-26 00:24:50 -07005187static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5188 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005189{
5190 struct task_security_struct *tsec = tsk->security;
5191 struct key_security_struct *ksec;
5192
5193 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5194 if (!ksec)
5195 return -ENOMEM;
5196
5197 ksec->obj = k;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005198 if (tsec->keycreate_sid)
5199 ksec->sid = tsec->keycreate_sid;
5200 else
5201 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005202 k->security = ksec;
5203
5204 return 0;
5205}
5206
5207static void selinux_key_free(struct key *k)
5208{
5209 struct key_security_struct *ksec = k->security;
5210
5211 k->security = NULL;
5212 kfree(ksec);
5213}
5214
5215static int selinux_key_permission(key_ref_t key_ref,
5216 struct task_struct *ctx,
5217 key_perm_t perm)
5218{
5219 struct key *key;
5220 struct task_security_struct *tsec;
5221 struct key_security_struct *ksec;
5222
5223 key = key_ref_to_ptr(key_ref);
5224
5225 tsec = ctx->security;
5226 ksec = key->security;
5227
5228 /* if no specific permissions are requested, we skip the
5229 permission check. No serious, additional covert channels
5230 appear to be created. */
5231 if (perm == 0)
5232 return 0;
5233
5234 return avc_has_perm(tsec->sid, ksec->sid,
5235 SECCLASS_KEY, perm, NULL);
5236}
5237
5238#endif
5239
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240static struct security_operations selinux_ops = {
5241 .ptrace = selinux_ptrace,
5242 .capget = selinux_capget,
5243 .capset_check = selinux_capset_check,
5244 .capset_set = selinux_capset_set,
5245 .sysctl = selinux_sysctl,
5246 .capable = selinux_capable,
5247 .quotactl = selinux_quotactl,
5248 .quota_on = selinux_quota_on,
5249 .syslog = selinux_syslog,
5250 .vm_enough_memory = selinux_vm_enough_memory,
5251
5252 .netlink_send = selinux_netlink_send,
5253 .netlink_recv = selinux_netlink_recv,
5254
5255 .bprm_alloc_security = selinux_bprm_alloc_security,
5256 .bprm_free_security = selinux_bprm_free_security,
5257 .bprm_apply_creds = selinux_bprm_apply_creds,
5258 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5259 .bprm_set_security = selinux_bprm_set_security,
5260 .bprm_check_security = selinux_bprm_check_security,
5261 .bprm_secureexec = selinux_bprm_secureexec,
5262
5263 .sb_alloc_security = selinux_sb_alloc_security,
5264 .sb_free_security = selinux_sb_free_security,
5265 .sb_copy_data = selinux_sb_copy_data,
5266 .sb_kern_mount = selinux_sb_kern_mount,
5267 .sb_statfs = selinux_sb_statfs,
5268 .sb_mount = selinux_mount,
5269 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005270 .sb_get_mnt_opts = selinux_get_mnt_opts,
5271 .sb_set_mnt_opts = selinux_set_mnt_opts,
5272 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005273 .sb_parse_opts_str = selinux_parse_opts_str,
5274
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275
5276 .inode_alloc_security = selinux_inode_alloc_security,
5277 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005278 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281 .inode_unlink = selinux_inode_unlink,
5282 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284 .inode_rmdir = selinux_inode_rmdir,
5285 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287 .inode_readlink = selinux_inode_readlink,
5288 .inode_follow_link = selinux_inode_follow_link,
5289 .inode_permission = selinux_inode_permission,
5290 .inode_setattr = selinux_inode_setattr,
5291 .inode_getattr = selinux_inode_getattr,
5292 .inode_setxattr = selinux_inode_setxattr,
5293 .inode_post_setxattr = selinux_inode_post_setxattr,
5294 .inode_getxattr = selinux_inode_getxattr,
5295 .inode_listxattr = selinux_inode_listxattr,
5296 .inode_removexattr = selinux_inode_removexattr,
5297 .inode_getsecurity = selinux_inode_getsecurity,
5298 .inode_setsecurity = selinux_inode_setsecurity,
5299 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005300 .inode_need_killpriv = selinux_inode_need_killpriv,
5301 .inode_killpriv = selinux_inode_killpriv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
5303 .file_permission = selinux_file_permission,
5304 .file_alloc_security = selinux_file_alloc_security,
5305 .file_free_security = selinux_file_free_security,
5306 .file_ioctl = selinux_file_ioctl,
5307 .file_mmap = selinux_file_mmap,
5308 .file_mprotect = selinux_file_mprotect,
5309 .file_lock = selinux_file_lock,
5310 .file_fcntl = selinux_file_fcntl,
5311 .file_set_fowner = selinux_file_set_fowner,
5312 .file_send_sigiotask = selinux_file_send_sigiotask,
5313 .file_receive = selinux_file_receive,
5314
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005315 .dentry_open = selinux_dentry_open,
5316
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317 .task_create = selinux_task_create,
5318 .task_alloc_security = selinux_task_alloc_security,
5319 .task_free_security = selinux_task_free_security,
5320 .task_setuid = selinux_task_setuid,
5321 .task_post_setuid = selinux_task_post_setuid,
5322 .task_setgid = selinux_task_setgid,
5323 .task_setpgid = selinux_task_setpgid,
5324 .task_getpgid = selinux_task_getpgid,
5325 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005326 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327 .task_setgroups = selinux_task_setgroups,
5328 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005329 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005330 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331 .task_setrlimit = selinux_task_setrlimit,
5332 .task_setscheduler = selinux_task_setscheduler,
5333 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005334 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 .task_kill = selinux_task_kill,
5336 .task_wait = selinux_task_wait,
5337 .task_prctl = selinux_task_prctl,
5338 .task_reparent_to_init = selinux_task_reparent_to_init,
5339 .task_to_inode = selinux_task_to_inode,
5340
5341 .ipc_permission = selinux_ipc_permission,
5342
5343 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5344 .msg_msg_free_security = selinux_msg_msg_free_security,
5345
5346 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5347 .msg_queue_free_security = selinux_msg_queue_free_security,
5348 .msg_queue_associate = selinux_msg_queue_associate,
5349 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5350 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5351 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5352
5353 .shm_alloc_security = selinux_shm_alloc_security,
5354 .shm_free_security = selinux_shm_free_security,
5355 .shm_associate = selinux_shm_associate,
5356 .shm_shmctl = selinux_shm_shmctl,
5357 .shm_shmat = selinux_shm_shmat,
5358
5359 .sem_alloc_security = selinux_sem_alloc_security,
5360 .sem_free_security = selinux_sem_free_security,
5361 .sem_associate = selinux_sem_associate,
5362 .sem_semctl = selinux_sem_semctl,
5363 .sem_semop = selinux_sem_semop,
5364
5365 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366
5367 .d_instantiate = selinux_d_instantiate,
5368
5369 .getprocattr = selinux_getprocattr,
5370 .setprocattr = selinux_setprocattr,
5371
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005372 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005373 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005374 .release_secctx = selinux_release_secctx,
5375
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 .unix_stream_connect = selinux_socket_unix_stream_connect,
5377 .unix_may_send = selinux_socket_unix_may_send,
5378
5379 .socket_create = selinux_socket_create,
5380 .socket_post_create = selinux_socket_post_create,
5381 .socket_bind = selinux_socket_bind,
5382 .socket_connect = selinux_socket_connect,
5383 .socket_listen = selinux_socket_listen,
5384 .socket_accept = selinux_socket_accept,
5385 .socket_sendmsg = selinux_socket_sendmsg,
5386 .socket_recvmsg = selinux_socket_recvmsg,
5387 .socket_getsockname = selinux_socket_getsockname,
5388 .socket_getpeername = selinux_socket_getpeername,
5389 .socket_getsockopt = selinux_socket_getsockopt,
5390 .socket_setsockopt = selinux_socket_setsockopt,
5391 .socket_shutdown = selinux_socket_shutdown,
5392 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005393 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5394 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395 .sk_alloc_security = selinux_sk_alloc_security,
5396 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005397 .sk_clone_security = selinux_sk_clone_security,
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005398 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005399 .sock_graft = selinux_sock_graft,
5400 .inet_conn_request = selinux_inet_conn_request,
5401 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005402 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005403 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005404
5405#ifdef CONFIG_SECURITY_NETWORK_XFRM
5406 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5407 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5408 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005409 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005410 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5411 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005412 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005413 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005414 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005415 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005417
5418#ifdef CONFIG_KEYS
5419 .key_alloc = selinux_key_alloc,
5420 .key_free = selinux_key_free,
5421 .key_permission = selinux_key_permission,
5422#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423};
5424
5425static __init int selinux_init(void)
5426{
5427 struct task_security_struct *tsec;
5428
5429 if (!selinux_enabled) {
5430 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5431 return 0;
5432 }
5433
5434 printk(KERN_INFO "SELinux: Initializing.\n");
5435
5436 /* Set the security state for the initial task. */
5437 if (task_alloc_security(current))
5438 panic("SELinux: Failed to initialize initial task.\n");
5439 tsec = current->security;
5440 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5441
James Morris7cae7e22006-03-22 00:09:22 -08005442 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5443 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005444 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445 avc_init();
5446
5447 original_ops = secondary_ops = security_ops;
5448 if (!secondary_ops)
5449 panic ("SELinux: No initial security operations\n");
5450 if (register_security (&selinux_ops))
5451 panic("SELinux: Unable to register with kernel.\n");
5452
5453 if (selinux_enforcing) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005454 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455 } else {
Eric Parisfadcdb42007-02-22 18:11:31 -05005456 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457 }
Michael LeMayd7200242006-06-22 14:47:17 -07005458
5459#ifdef CONFIG_KEYS
5460 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005461 selinux_key_alloc(&root_user_keyring, current,
5462 KEY_ALLOC_NOT_IN_QUOTA);
5463 selinux_key_alloc(&root_session_keyring, current,
5464 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005465#endif
5466
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467 return 0;
5468}
5469
5470void selinux_complete_init(void)
5471{
Eric Parisfadcdb42007-02-22 18:11:31 -05005472 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
5474 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005475 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005476 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477 spin_lock(&sb_security_lock);
5478next_sb:
5479 if (!list_empty(&superblock_security_head)) {
5480 struct superblock_security_struct *sbsec =
5481 list_entry(superblock_security_head.next,
5482 struct superblock_security_struct,
5483 list);
5484 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005485 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005487 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488 down_read(&sb->s_umount);
5489 if (sb->s_root)
5490 superblock_doinit(sb, NULL);
5491 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005492 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493 spin_lock(&sb_security_lock);
5494 list_del_init(&sbsec->list);
5495 goto next_sb;
5496 }
5497 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005498 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499}
5500
5501/* SELinux requires early initialization in order to label
5502 all processes and objects when they are created. */
5503security_initcall(selinux_init);
5504
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005505#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506
Paul Mooreeffad8d2008-01-29 08:49:27 -05005507static struct nf_hook_ops selinux_ipv4_ops[] = {
5508 {
5509 .hook = selinux_ipv4_postroute,
5510 .owner = THIS_MODULE,
5511 .pf = PF_INET,
5512 .hooknum = NF_INET_POST_ROUTING,
5513 .priority = NF_IP_PRI_SELINUX_LAST,
5514 },
5515 {
5516 .hook = selinux_ipv4_forward,
5517 .owner = THIS_MODULE,
5518 .pf = PF_INET,
5519 .hooknum = NF_INET_FORWARD,
5520 .priority = NF_IP_PRI_SELINUX_FIRST,
5521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522};
5523
5524#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5525
Paul Mooreeffad8d2008-01-29 08:49:27 -05005526static struct nf_hook_ops selinux_ipv6_ops[] = {
5527 {
5528 .hook = selinux_ipv6_postroute,
5529 .owner = THIS_MODULE,
5530 .pf = PF_INET6,
5531 .hooknum = NF_INET_POST_ROUTING,
5532 .priority = NF_IP6_PRI_SELINUX_LAST,
5533 },
5534 {
5535 .hook = selinux_ipv6_forward,
5536 .owner = THIS_MODULE,
5537 .pf = PF_INET6,
5538 .hooknum = NF_INET_FORWARD,
5539 .priority = NF_IP6_PRI_SELINUX_FIRST,
5540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541};
5542
5543#endif /* IPV6 */
5544
5545static int __init selinux_nf_ip_init(void)
5546{
5547 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005548 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549
5550 if (!selinux_enabled)
5551 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005552
5553 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5554
Paul Mooreeffad8d2008-01-29 08:49:27 -05005555 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5556 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5557 if (err)
5558 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5559 err);
5560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561
5562#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005563 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5564 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5565 if (err)
5566 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5567 err);
5568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005569#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005570
Linus Torvalds1da177e2005-04-16 15:20:36 -07005571out:
5572 return err;
5573}
5574
5575__initcall(selinux_nf_ip_init);
5576
5577#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5578static void selinux_nf_ip_exit(void)
5579{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005580 u32 iter;
5581
Eric Parisfadcdb42007-02-22 18:11:31 -05005582 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
Paul Mooreeffad8d2008-01-29 08:49:27 -05005584 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5585 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005587 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5588 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589#endif /* IPV6 */
5590}
5591#endif
5592
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005593#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594
5595#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5596#define selinux_nf_ip_exit()
5597#endif
5598
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005599#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600
5601#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5602int selinux_disable(void)
5603{
5604 extern void exit_sel_fs(void);
5605 static int selinux_disabled = 0;
5606
5607 if (ss_initialized) {
5608 /* Not permitted after initial policy load. */
5609 return -EINVAL;
5610 }
5611
5612 if (selinux_disabled) {
5613 /* Only do this once. */
5614 return -EINVAL;
5615 }
5616
5617 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5618
5619 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005620 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621
5622 /* Reset security_ops to the secondary module, dummy or capability. */
5623 security_ops = secondary_ops;
5624
5625 /* Unregister netfilter hooks. */
5626 selinux_nf_ip_exit();
5627
5628 /* Unregister selinuxfs. */
5629 exit_sel_fs();
5630
5631 return 0;
5632}
5633#endif
5634
5635