blob: b3c064744d324f030f09c5b46e7173d80eeeb1ad [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
Dustin Kirkland8c8570f2005-11-03 17:15:16 +0000139/* Return security context for a given sid or just the context
140 length if the buffer is null or length is 0 */
141static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
142{
143 char *context;
144 unsigned len;
145 int rc;
146
147 rc = security_sid_to_context(sid, &context, &len);
148 if (rc)
149 return rc;
150
151 if (!buffer || !size)
152 goto getsecurity_exit;
153
154 if (size < len) {
155 len = -ERANGE;
156 goto getsecurity_exit;
157 }
158 memcpy(buffer, context, len);
159
160getsecurity_exit:
161 kfree(context);
162 return len;
163}
164
Paul Moored621d352008-01-29 08:43:36 -0500165/**
166 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
167 *
168 * Description:
169 * This function checks the SECMARK reference counter to see if any SECMARK
170 * targets are currently configured, if the reference counter is greater than
171 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
172 * enabled, false (0) if SECMARK is disabled.
173 *
174 */
175static int selinux_secmark_enabled(void)
176{
177 return (atomic_read(&selinux_secmark_refcount) > 0);
178}
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180/* Allocate and free functions for each kind of security blob. */
181
182static int task_alloc_security(struct task_struct *task)
183{
184 struct task_security_struct *tsec;
185
James Morris89d155e2005-10-30 14:59:21 -0800186 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 if (!tsec)
188 return -ENOMEM;
189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 tsec->task = task;
191 tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
192 task->security = tsec;
193
194 return 0;
195}
196
197static void task_free_security(struct task_struct *task)
198{
199 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 task->security = NULL;
201 kfree(tsec);
202}
203
204static int inode_alloc_security(struct inode *inode)
205{
206 struct task_security_struct *tsec = current->security;
207 struct inode_security_struct *isec;
208
Robert P. J. Dayc3762222007-02-10 01:45:03 -0800209 isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 if (!isec)
211 return -ENOMEM;
212
Eric Paris23970742006-09-25 23:32:01 -0700213 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 isec->inode = inode;
216 isec->sid = SECINITSID_UNLABELED;
217 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800218 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 inode->i_security = isec;
220
221 return 0;
222}
223
224static void inode_free_security(struct inode *inode)
225{
226 struct inode_security_struct *isec = inode->i_security;
227 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 spin_lock(&sbsec->isec_lock);
230 if (!list_empty(&isec->list))
231 list_del_init(&isec->list);
232 spin_unlock(&sbsec->isec_lock);
233
234 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800235 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236}
237
238static int file_alloc_security(struct file *file)
239{
240 struct task_security_struct *tsec = current->security;
241 struct file_security_struct *fsec;
242
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800243 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (!fsec)
245 return -ENOMEM;
246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 fsec->file = file;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800248 fsec->sid = tsec->sid;
249 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 file->f_security = fsec;
251
252 return 0;
253}
254
255static void file_free_security(struct file *file)
256{
257 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 file->f_security = NULL;
259 kfree(fsec);
260}
261
262static int superblock_alloc_security(struct super_block *sb)
263{
264 struct superblock_security_struct *sbsec;
265
James Morris89d155e2005-10-30 14:59:21 -0800266 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 if (!sbsec)
268 return -ENOMEM;
269
Eric Parisbc7e9822006-09-25 23:32:02 -0700270 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 INIT_LIST_HEAD(&sbsec->list);
272 INIT_LIST_HEAD(&sbsec->isec_head);
273 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 sbsec->sb = sb;
275 sbsec->sid = SECINITSID_UNLABELED;
276 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700277 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 sb->s_security = sbsec;
279
280 return 0;
281}
282
283static void superblock_free_security(struct super_block *sb)
284{
285 struct superblock_security_struct *sbsec = sb->s_security;
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 spin_lock(&sb_security_lock);
288 if (!list_empty(&sbsec->list))
289 list_del_init(&sbsec->list);
290 spin_unlock(&sb_security_lock);
291
292 sb->s_security = NULL;
293 kfree(sbsec);
294}
295
Al Viro7d877f32005-10-21 03:20:43 -0400296static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
298 struct sk_security_struct *ssec;
299
James Morris89d155e2005-10-30 14:59:21 -0800300 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 if (!ssec)
302 return -ENOMEM;
303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 ssec->sk = sk;
305 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700306 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 sk->sk_security = ssec;
308
Paul Moore99f59ed2006-08-29 17:53:48 -0700309 selinux_netlbl_sk_security_init(ssec, family);
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 return 0;
312}
313
314static void sk_free_security(struct sock *sk)
315{
316 struct sk_security_struct *ssec = sk->sk_security;
317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 sk->sk_security = NULL;
319 kfree(ssec);
320}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
322/* The security server must be initialized before
323 any labeling or access decisions can be provided. */
324extern int ss_initialized;
325
326/* The file system's label must be initialized prior to use. */
327
328static char *labeling_behaviors[6] = {
329 "uses xattr",
330 "uses transition SIDs",
331 "uses task SIDs",
332 "uses genfs_contexts",
333 "not configured for labeling",
334 "uses mountpoint labeling",
335};
336
337static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
338
339static inline int inode_doinit(struct inode *inode)
340{
341 return inode_doinit_with_dentry(inode, NULL);
342}
343
344enum {
Eric Paris31e87932007-09-19 17:19:12 -0400345 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 Opt_context = 1,
347 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500348 Opt_defcontext = 3,
349 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350};
351
352static match_table_t tokens = {
353 {Opt_context, "context=%s"},
354 {Opt_fscontext, "fscontext=%s"},
355 {Opt_defcontext, "defcontext=%s"},
Eric Paris08089252006-07-10 04:43:55 -0700356 {Opt_rootcontext, "rootcontext=%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400357 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358};
359
360#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
361
Eric Parisc312feb2006-07-10 04:43:53 -0700362static int may_context_mount_sb_relabel(u32 sid,
363 struct superblock_security_struct *sbsec,
364 struct task_security_struct *tsec)
365{
366 int rc;
367
368 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
369 FILESYSTEM__RELABELFROM, NULL);
370 if (rc)
371 return rc;
372
373 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
374 FILESYSTEM__RELABELTO, NULL);
375 return rc;
376}
377
Eric Paris08089252006-07-10 04:43:55 -0700378static int may_context_mount_inode_relabel(u32 sid,
379 struct superblock_security_struct *sbsec,
380 struct task_security_struct *tsec)
381{
382 int rc;
383 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
384 FILESYSTEM__RELABELFROM, NULL);
385 if (rc)
386 return rc;
387
388 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
389 FILESYSTEM__ASSOCIATE, NULL);
390 return rc;
391}
392
Eric Parisc9180a52007-11-30 13:00:35 -0500393static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
395 struct superblock_security_struct *sbsec = sb->s_security;
396 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500397 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 int rc = 0;
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
401 /* Make sure that the xattr handler exists and that no
402 error other than -ENODATA is returned by getxattr on
403 the root directory. -ENODATA is ok, as this may be
404 the first boot of the SELinux kernel before we have
405 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500406 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
408 "xattr support\n", sb->s_id, sb->s_type->name);
409 rc = -EOPNOTSUPP;
410 goto out;
411 }
Eric Parisc9180a52007-11-30 13:00:35 -0500412 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (rc < 0 && rc != -ENODATA) {
414 if (rc == -EOPNOTSUPP)
415 printk(KERN_WARNING "SELinux: (dev %s, type "
416 "%s) has no security xattr handler\n",
417 sb->s_id, sb->s_type->name);
418 else
419 printk(KERN_WARNING "SELinux: (dev %s, type "
420 "%s) getxattr errno %d\n", sb->s_id,
421 sb->s_type->name, -rc);
422 goto out;
423 }
424 }
425
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 sbsec->initialized = 1;
427
Eric Parisc9180a52007-11-30 13:00:35 -0500428 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500429 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500431 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500432 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 sb->s_id, sb->s_type->name,
434 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500437 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 /* Initialize any other inodes associated with the superblock, e.g.
440 inodes created prior to initial policy load or inodes created
441 during get_sb by a pseudo filesystem that directly
442 populates itself. */
443 spin_lock(&sbsec->isec_lock);
444next_inode:
445 if (!list_empty(&sbsec->isec_head)) {
446 struct inode_security_struct *isec =
447 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500448 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct inode *inode = isec->inode;
450 spin_unlock(&sbsec->isec_lock);
451 inode = igrab(inode);
452 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500453 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 inode_doinit(inode);
455 iput(inode);
456 }
457 spin_lock(&sbsec->isec_lock);
458 list_del_init(&isec->list);
459 goto next_inode;
460 }
461 spin_unlock(&sbsec->isec_lock);
462out:
Eric Parisc9180a52007-11-30 13:00:35 -0500463 return rc;
464}
465
466/*
467 * This function should allow an FS to ask what it's mount security
468 * options were so it can use those later for submounts, displaying
469 * mount options, or whatever.
470 */
471static int selinux_get_mnt_opts(const struct super_block *sb,
472 char ***mount_options, int **mnt_opts_flags,
473 int *num_opts)
474{
475 int rc = 0, i;
476 struct superblock_security_struct *sbsec = sb->s_security;
477 char *context = NULL;
478 u32 len;
479 char tmp;
480
481 *num_opts = 0;
482 *mount_options = NULL;
483 *mnt_opts_flags = NULL;
484
485 if (!sbsec->initialized)
486 return -EINVAL;
487
488 if (!ss_initialized)
489 return -EINVAL;
490
491 /*
492 * if we ever use sbsec flags for anything other than tracking mount
493 * settings this is going to need a mask
494 */
495 tmp = sbsec->flags;
496 /* count the number of mount options for this sb */
497 for (i = 0; i < 8; i++) {
498 if (tmp & 0x01)
499 (*num_opts)++;
500 tmp >>= 1;
501 }
502
503 *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
504 if (!*mount_options) {
505 rc = -ENOMEM;
506 goto out_free;
507 }
508
509 *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
510 if (!*mnt_opts_flags) {
511 rc = -ENOMEM;
512 goto out_free;
513 }
514
515 i = 0;
516 if (sbsec->flags & FSCONTEXT_MNT) {
517 rc = security_sid_to_context(sbsec->sid, &context, &len);
518 if (rc)
519 goto out_free;
520 (*mount_options)[i] = context;
521 (*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
522 }
523 if (sbsec->flags & CONTEXT_MNT) {
524 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
525 if (rc)
526 goto out_free;
527 (*mount_options)[i] = context;
528 (*mnt_opts_flags)[i++] = CONTEXT_MNT;
529 }
530 if (sbsec->flags & DEFCONTEXT_MNT) {
531 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
532 if (rc)
533 goto out_free;
534 (*mount_options)[i] = context;
535 (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
536 }
537 if (sbsec->flags & ROOTCONTEXT_MNT) {
538 struct inode *root = sbsec->sb->s_root->d_inode;
539 struct inode_security_struct *isec = root->i_security;
540
541 rc = security_sid_to_context(isec->sid, &context, &len);
542 if (rc)
543 goto out_free;
544 (*mount_options)[i] = context;
545 (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
546 }
547
548 BUG_ON(i != *num_opts);
549
550 return 0;
551
552out_free:
553 /* don't leak context string if security_sid_to_context had an error */
554 if (*mount_options && i)
555 for (; i > 0; i--)
556 kfree((*mount_options)[i-1]);
557 kfree(*mount_options);
558 *mount_options = NULL;
559 kfree(*mnt_opts_flags);
560 *mnt_opts_flags = NULL;
561 *num_opts = 0;
562 return rc;
563}
564
565static int bad_option(struct superblock_security_struct *sbsec, char flag,
566 u32 old_sid, u32 new_sid)
567{
568 /* check if the old mount command had the same options */
569 if (sbsec->initialized)
570 if (!(sbsec->flags & flag) ||
571 (old_sid != new_sid))
572 return 1;
573
574 /* check if we were passed the same options twice,
575 * aka someone passed context=a,context=b
576 */
577 if (!sbsec->initialized)
578 if (sbsec->flags & flag)
579 return 1;
580 return 0;
581}
582/*
583 * Allow filesystems with binary mount data to explicitly set mount point
584 * labeling information.
585 */
586int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
587 int *flags, int num_opts)
588{
589 int rc = 0, i;
590 struct task_security_struct *tsec = current->security;
591 struct superblock_security_struct *sbsec = sb->s_security;
592 const char *name = sb->s_type->name;
593 struct inode *inode = sbsec->sb->s_root->d_inode;
594 struct inode_security_struct *root_isec = inode->i_security;
595 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
596 u32 defcontext_sid = 0;
597
598 mutex_lock(&sbsec->lock);
599
600 if (!ss_initialized) {
601 if (!num_opts) {
602 /* Defer initialization until selinux_complete_init,
603 after the initial policy is loaded and the security
604 server is ready to handle calls. */
605 spin_lock(&sb_security_lock);
606 if (list_empty(&sbsec->list))
607 list_add(&sbsec->list, &superblock_security_head);
608 spin_unlock(&sb_security_lock);
609 goto out;
610 }
611 rc = -EINVAL;
612 printk(KERN_WARNING "Unable to set superblock options before "
613 "the security server is initialized\n");
614 goto out;
615 }
616
617 /*
618 * parse the mount options, check if they are valid sids.
619 * also check if someone is trying to mount the same sb more
620 * than once with different security options.
621 */
622 for (i = 0; i < num_opts; i++) {
623 u32 sid;
624 rc = security_context_to_sid(mount_options[i],
625 strlen(mount_options[i]), &sid);
626 if (rc) {
627 printk(KERN_WARNING "SELinux: security_context_to_sid"
628 "(%s) failed for (dev %s, type %s) errno=%d\n",
629 mount_options[i], sb->s_id, name, rc);
630 goto out;
631 }
632 switch (flags[i]) {
633 case FSCONTEXT_MNT:
634 fscontext_sid = sid;
635
636 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
637 fscontext_sid))
638 goto out_double_mount;
639
640 sbsec->flags |= FSCONTEXT_MNT;
641 break;
642 case CONTEXT_MNT:
643 context_sid = sid;
644
645 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
646 context_sid))
647 goto out_double_mount;
648
649 sbsec->flags |= CONTEXT_MNT;
650 break;
651 case ROOTCONTEXT_MNT:
652 rootcontext_sid = sid;
653
654 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
655 rootcontext_sid))
656 goto out_double_mount;
657
658 sbsec->flags |= ROOTCONTEXT_MNT;
659
660 break;
661 case DEFCONTEXT_MNT:
662 defcontext_sid = sid;
663
664 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
665 defcontext_sid))
666 goto out_double_mount;
667
668 sbsec->flags |= DEFCONTEXT_MNT;
669
670 break;
671 default:
672 rc = -EINVAL;
673 goto out;
674 }
675 }
676
677 if (sbsec->initialized) {
678 /* previously mounted with options, but not on this attempt? */
679 if (sbsec->flags && !num_opts)
680 goto out_double_mount;
681 rc = 0;
682 goto out;
683 }
684
685 if (strcmp(sb->s_type->name, "proc") == 0)
686 sbsec->proc = 1;
687
688 /* Determine the labeling behavior to use for this filesystem type. */
689 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
690 if (rc) {
691 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
692 __FUNCTION__, sb->s_type->name, rc);
693 goto out;
694 }
695
696 /* sets the context of the superblock for the fs being mounted. */
697 if (fscontext_sid) {
698
699 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
700 if (rc)
701 goto out;
702
703 sbsec->sid = fscontext_sid;
704 }
705
706 /*
707 * Switch to using mount point labeling behavior.
708 * sets the label used on all file below the mountpoint, and will set
709 * the superblock context if not already set.
710 */
711 if (context_sid) {
712 if (!fscontext_sid) {
713 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
714 if (rc)
715 goto out;
716 sbsec->sid = context_sid;
717 } else {
718 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
719 if (rc)
720 goto out;
721 }
722 if (!rootcontext_sid)
723 rootcontext_sid = context_sid;
724
725 sbsec->mntpoint_sid = context_sid;
726 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
727 }
728
729 if (rootcontext_sid) {
730 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
731 if (rc)
732 goto out;
733
734 root_isec->sid = rootcontext_sid;
735 root_isec->initialized = 1;
736 }
737
738 if (defcontext_sid) {
739 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
740 rc = -EINVAL;
741 printk(KERN_WARNING "SELinux: defcontext option is "
742 "invalid for this filesystem type\n");
743 goto out;
744 }
745
746 if (defcontext_sid != sbsec->def_sid) {
747 rc = may_context_mount_inode_relabel(defcontext_sid,
748 sbsec, tsec);
749 if (rc)
750 goto out;
751 }
752
753 sbsec->def_sid = defcontext_sid;
754 }
755
756 rc = sb_finish_set_opts(sb);
757out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700758 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500760out_double_mount:
761 rc = -EINVAL;
762 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
763 "security settings for (dev %s, type %s)\n", sb->s_id, name);
764 goto out;
765}
766
767static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
768 struct super_block *newsb)
769{
770 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
771 struct superblock_security_struct *newsbsec = newsb->s_security;
772
773 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
774 int set_context = (oldsbsec->flags & CONTEXT_MNT);
775 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
776
777 /* we can't error, we can't save the info, this shouldn't get called
778 * this early in the boot process. */
779 BUG_ON(!ss_initialized);
780
781 /* this might go away sometime down the line if there is a new user
782 * of clone, but for now, nfs better not get here... */
783 BUG_ON(newsbsec->initialized);
784
785 /* how can we clone if the old one wasn't set up?? */
786 BUG_ON(!oldsbsec->initialized);
787
788 mutex_lock(&newsbsec->lock);
789
790 newsbsec->flags = oldsbsec->flags;
791
792 newsbsec->sid = oldsbsec->sid;
793 newsbsec->def_sid = oldsbsec->def_sid;
794 newsbsec->behavior = oldsbsec->behavior;
795
796 if (set_context) {
797 u32 sid = oldsbsec->mntpoint_sid;
798
799 if (!set_fscontext)
800 newsbsec->sid = sid;
801 if (!set_rootcontext) {
802 struct inode *newinode = newsb->s_root->d_inode;
803 struct inode_security_struct *newisec = newinode->i_security;
804 newisec->sid = sid;
805 }
806 newsbsec->mntpoint_sid = sid;
807 }
808 if (set_rootcontext) {
809 const struct inode *oldinode = oldsb->s_root->d_inode;
810 const struct inode_security_struct *oldisec = oldinode->i_security;
811 struct inode *newinode = newsb->s_root->d_inode;
812 struct inode_security_struct *newisec = newinode->i_security;
813
814 newisec->sid = oldisec->sid;
815 }
816
817 sb_finish_set_opts(newsb);
818 mutex_unlock(&newsbsec->lock);
819}
820
821/*
822 * string mount options parsing and call set the sbsec
823 */
824static int superblock_doinit(struct super_block *sb, void *data)
825{
826 char *context = NULL, *defcontext = NULL;
827 char *fscontext = NULL, *rootcontext = NULL;
828 int rc = 0;
829 char *p, *options = data;
830 /* selinux only know about a fixed number of mount options */
831 char *mnt_opts[NUM_SEL_MNT_OPTS];
832 int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
833
834 if (!data)
835 goto out;
836
837 /* with the nfs patch this will become a goto out; */
838 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
839 const char *name = sb->s_type->name;
840 /* NFS we understand. */
841 if (!strcmp(name, "nfs")) {
842 struct nfs_mount_data *d = data;
843
844 if (d->version != NFS_MOUNT_VERSION)
845 goto out;
846
847 if (d->context[0]) {
848 context = kstrdup(d->context, GFP_KERNEL);
849 if (!context) {
850 rc = -ENOMEM;
851 goto out;
852 }
853 }
854 goto build_flags;
855 } else
856 goto out;
857 }
858
859 /* Standard string-based options. */
860 while ((p = strsep(&options, "|")) != NULL) {
861 int token;
862 substring_t args[MAX_OPT_ARGS];
863
864 if (!*p)
865 continue;
866
867 token = match_token(p, tokens, args);
868
869 switch (token) {
870 case Opt_context:
871 if (context || defcontext) {
872 rc = -EINVAL;
873 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
874 goto out_err;
875 }
876 context = match_strdup(&args[0]);
877 if (!context) {
878 rc = -ENOMEM;
879 goto out_err;
880 }
881 break;
882
883 case Opt_fscontext:
884 if (fscontext) {
885 rc = -EINVAL;
886 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
887 goto out_err;
888 }
889 fscontext = match_strdup(&args[0]);
890 if (!fscontext) {
891 rc = -ENOMEM;
892 goto out_err;
893 }
894 break;
895
896 case Opt_rootcontext:
897 if (rootcontext) {
898 rc = -EINVAL;
899 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
900 goto out_err;
901 }
902 rootcontext = match_strdup(&args[0]);
903 if (!rootcontext) {
904 rc = -ENOMEM;
905 goto out_err;
906 }
907 break;
908
909 case Opt_defcontext:
910 if (context || defcontext) {
911 rc = -EINVAL;
912 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
913 goto out_err;
914 }
915 defcontext = match_strdup(&args[0]);
916 if (!defcontext) {
917 rc = -ENOMEM;
918 goto out_err;
919 }
920 break;
921
922 default:
923 rc = -EINVAL;
924 printk(KERN_WARNING "SELinux: unknown mount option\n");
925 goto out_err;
926
927 }
928 }
929
930build_flags:
931 if (fscontext) {
932 mnt_opts[num_mnt_opts] = fscontext;
933 mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
934 }
935 if (context) {
936 mnt_opts[num_mnt_opts] = context;
937 mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
938 }
939 if (rootcontext) {
940 mnt_opts[num_mnt_opts] = rootcontext;
941 mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
942 }
943 if (defcontext) {
944 mnt_opts[num_mnt_opts] = defcontext;
945 mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
946 }
947
948out:
949 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
950out_err:
951 kfree(context);
952 kfree(defcontext);
953 kfree(fscontext);
954 kfree(rootcontext);
955 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956}
957
958static inline u16 inode_mode_to_security_class(umode_t mode)
959{
960 switch (mode & S_IFMT) {
961 case S_IFSOCK:
962 return SECCLASS_SOCK_FILE;
963 case S_IFLNK:
964 return SECCLASS_LNK_FILE;
965 case S_IFREG:
966 return SECCLASS_FILE;
967 case S_IFBLK:
968 return SECCLASS_BLK_FILE;
969 case S_IFDIR:
970 return SECCLASS_DIR;
971 case S_IFCHR:
972 return SECCLASS_CHR_FILE;
973 case S_IFIFO:
974 return SECCLASS_FIFO_FILE;
975
976 }
977
978 return SECCLASS_FILE;
979}
980
James Morris13402582005-09-30 14:24:34 -0400981static inline int default_protocol_stream(int protocol)
982{
983 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
984}
985
986static inline int default_protocol_dgram(int protocol)
987{
988 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
989}
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991static inline u16 socket_type_to_security_class(int family, int type, int protocol)
992{
993 switch (family) {
994 case PF_UNIX:
995 switch (type) {
996 case SOCK_STREAM:
997 case SOCK_SEQPACKET:
998 return SECCLASS_UNIX_STREAM_SOCKET;
999 case SOCK_DGRAM:
1000 return SECCLASS_UNIX_DGRAM_SOCKET;
1001 }
1002 break;
1003 case PF_INET:
1004 case PF_INET6:
1005 switch (type) {
1006 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001007 if (default_protocol_stream(protocol))
1008 return SECCLASS_TCP_SOCKET;
1009 else
1010 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001012 if (default_protocol_dgram(protocol))
1013 return SECCLASS_UDP_SOCKET;
1014 else
1015 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001016 case SOCK_DCCP:
1017 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001018 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return SECCLASS_RAWIP_SOCKET;
1020 }
1021 break;
1022 case PF_NETLINK:
1023 switch (protocol) {
1024 case NETLINK_ROUTE:
1025 return SECCLASS_NETLINK_ROUTE_SOCKET;
1026 case NETLINK_FIREWALL:
1027 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001028 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1030 case NETLINK_NFLOG:
1031 return SECCLASS_NETLINK_NFLOG_SOCKET;
1032 case NETLINK_XFRM:
1033 return SECCLASS_NETLINK_XFRM_SOCKET;
1034 case NETLINK_SELINUX:
1035 return SECCLASS_NETLINK_SELINUX_SOCKET;
1036 case NETLINK_AUDIT:
1037 return SECCLASS_NETLINK_AUDIT_SOCKET;
1038 case NETLINK_IP6_FW:
1039 return SECCLASS_NETLINK_IP6FW_SOCKET;
1040 case NETLINK_DNRTMSG:
1041 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001042 case NETLINK_KOBJECT_UEVENT:
1043 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 default:
1045 return SECCLASS_NETLINK_SOCKET;
1046 }
1047 case PF_PACKET:
1048 return SECCLASS_PACKET_SOCKET;
1049 case PF_KEY:
1050 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001051 case PF_APPLETALK:
1052 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054
1055 return SECCLASS_SOCKET;
1056}
1057
1058#ifdef CONFIG_PROC_FS
1059static int selinux_proc_get_sid(struct proc_dir_entry *de,
1060 u16 tclass,
1061 u32 *sid)
1062{
1063 int buflen, rc;
1064 char *buffer, *path, *end;
1065
1066 buffer = (char*)__get_free_page(GFP_KERNEL);
1067 if (!buffer)
1068 return -ENOMEM;
1069
1070 buflen = PAGE_SIZE;
1071 end = buffer+buflen;
1072 *--end = '\0';
1073 buflen--;
1074 path = end-1;
1075 *path = '/';
1076 while (de && de != de->parent) {
1077 buflen -= de->namelen + 1;
1078 if (buflen < 0)
1079 break;
1080 end -= de->namelen;
1081 memcpy(end, de->name, de->namelen);
1082 *--end = '/';
1083 path = end;
1084 de = de->parent;
1085 }
1086 rc = security_genfs_sid("proc", path, tclass, sid);
1087 free_page((unsigned long)buffer);
1088 return rc;
1089}
1090#else
1091static int selinux_proc_get_sid(struct proc_dir_entry *de,
1092 u16 tclass,
1093 u32 *sid)
1094{
1095 return -EINVAL;
1096}
1097#endif
1098
1099/* The inode's security attributes must be initialized before first use. */
1100static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1101{
1102 struct superblock_security_struct *sbsec = NULL;
1103 struct inode_security_struct *isec = inode->i_security;
1104 u32 sid;
1105 struct dentry *dentry;
1106#define INITCONTEXTLEN 255
1107 char *context = NULL;
1108 unsigned len = 0;
1109 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111 if (isec->initialized)
1112 goto out;
1113
Eric Paris23970742006-09-25 23:32:01 -07001114 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001116 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118 sbsec = inode->i_sb->s_security;
1119 if (!sbsec->initialized) {
1120 /* Defer initialization until selinux_complete_init,
1121 after the initial policy is loaded and the security
1122 server is ready to handle calls. */
1123 spin_lock(&sbsec->isec_lock);
1124 if (list_empty(&isec->list))
1125 list_add(&isec->list, &sbsec->isec_head);
1126 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001127 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129
1130 switch (sbsec->behavior) {
1131 case SECURITY_FS_USE_XATTR:
1132 if (!inode->i_op->getxattr) {
1133 isec->sid = sbsec->def_sid;
1134 break;
1135 }
1136
1137 /* Need a dentry, since the xattr API requires one.
1138 Life would be simpler if we could just pass the inode. */
1139 if (opt_dentry) {
1140 /* Called from d_instantiate or d_splice_alias. */
1141 dentry = dget(opt_dentry);
1142 } else {
1143 /* Called from selinux_complete_init, try to find a dentry. */
1144 dentry = d_find_alias(inode);
1145 }
1146 if (!dentry) {
1147 printk(KERN_WARNING "%s: no dentry for dev=%s "
1148 "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
1149 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001150 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
1152
1153 len = INITCONTEXTLEN;
1154 context = kmalloc(len, GFP_KERNEL);
1155 if (!context) {
1156 rc = -ENOMEM;
1157 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001158 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
1160 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1161 context, len);
1162 if (rc == -ERANGE) {
1163 /* Need a larger buffer. Query for the right size. */
1164 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1165 NULL, 0);
1166 if (rc < 0) {
1167 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001168 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 }
1170 kfree(context);
1171 len = rc;
1172 context = kmalloc(len, GFP_KERNEL);
1173 if (!context) {
1174 rc = -ENOMEM;
1175 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001176 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
1178 rc = inode->i_op->getxattr(dentry,
1179 XATTR_NAME_SELINUX,
1180 context, len);
1181 }
1182 dput(dentry);
1183 if (rc < 0) {
1184 if (rc != -ENODATA) {
1185 printk(KERN_WARNING "%s: getxattr returned "
1186 "%d for dev=%s ino=%ld\n", __FUNCTION__,
1187 -rc, inode->i_sb->s_id, inode->i_ino);
1188 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001189 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 }
1191 /* Map ENODATA to the default file SID */
1192 sid = sbsec->def_sid;
1193 rc = 0;
1194 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001195 rc = security_context_to_sid_default(context, rc, &sid,
1196 sbsec->def_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 if (rc) {
1198 printk(KERN_WARNING "%s: context_to_sid(%s) "
1199 "returned %d for dev=%s ino=%ld\n",
1200 __FUNCTION__, context, -rc,
1201 inode->i_sb->s_id, inode->i_ino);
1202 kfree(context);
1203 /* Leave with the unlabeled SID */
1204 rc = 0;
1205 break;
1206 }
1207 }
1208 kfree(context);
1209 isec->sid = sid;
1210 break;
1211 case SECURITY_FS_USE_TASK:
1212 isec->sid = isec->task_sid;
1213 break;
1214 case SECURITY_FS_USE_TRANS:
1215 /* Default to the fs SID. */
1216 isec->sid = sbsec->sid;
1217
1218 /* Try to obtain a transition SID. */
1219 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1220 rc = security_transition_sid(isec->task_sid,
1221 sbsec->sid,
1222 isec->sclass,
1223 &sid);
1224 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001225 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 isec->sid = sid;
1227 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001228 case SECURITY_FS_USE_MNTPOINT:
1229 isec->sid = sbsec->mntpoint_sid;
1230 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001232 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 isec->sid = sbsec->sid;
1234
1235 if (sbsec->proc) {
1236 struct proc_inode *proci = PROC_I(inode);
1237 if (proci->pde) {
1238 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1239 rc = selinux_proc_get_sid(proci->pde,
1240 isec->sclass,
1241 &sid);
1242 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001243 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 isec->sid = sid;
1245 }
1246 }
1247 break;
1248 }
1249
1250 isec->initialized = 1;
1251
Eric Paris23970742006-09-25 23:32:01 -07001252out_unlock:
1253 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254out:
1255 if (isec->sclass == SECCLASS_FILE)
1256 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 return rc;
1258}
1259
1260/* Convert a Linux signal to an access vector. */
1261static inline u32 signal_to_av(int sig)
1262{
1263 u32 perm = 0;
1264
1265 switch (sig) {
1266 case SIGCHLD:
1267 /* Commonly granted from child to parent. */
1268 perm = PROCESS__SIGCHLD;
1269 break;
1270 case SIGKILL:
1271 /* Cannot be caught or ignored */
1272 perm = PROCESS__SIGKILL;
1273 break;
1274 case SIGSTOP:
1275 /* Cannot be caught or ignored */
1276 perm = PROCESS__SIGSTOP;
1277 break;
1278 default:
1279 /* All other signals. */
1280 perm = PROCESS__SIGNAL;
1281 break;
1282 }
1283
1284 return perm;
1285}
1286
1287/* Check permission betweeen a pair of tasks, e.g. signal checks,
1288 fork check, ptrace check, etc. */
1289static int task_has_perm(struct task_struct *tsk1,
1290 struct task_struct *tsk2,
1291 u32 perms)
1292{
1293 struct task_security_struct *tsec1, *tsec2;
1294
1295 tsec1 = tsk1->security;
1296 tsec2 = tsk2->security;
1297 return avc_has_perm(tsec1->sid, tsec2->sid,
1298 SECCLASS_PROCESS, perms, NULL);
1299}
1300
1301/* Check whether a task is allowed to use a capability. */
1302static int task_has_capability(struct task_struct *tsk,
1303 int cap)
1304{
1305 struct task_security_struct *tsec;
1306 struct avc_audit_data ad;
1307
1308 tsec = tsk->security;
1309
1310 AVC_AUDIT_DATA_INIT(&ad,CAP);
1311 ad.tsk = tsk;
1312 ad.u.cap = cap;
1313
1314 return avc_has_perm(tsec->sid, tsec->sid,
1315 SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
1316}
1317
1318/* Check whether a task is allowed to use a system operation. */
1319static int task_has_system(struct task_struct *tsk,
1320 u32 perms)
1321{
1322 struct task_security_struct *tsec;
1323
1324 tsec = tsk->security;
1325
1326 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1327 SECCLASS_SYSTEM, perms, NULL);
1328}
1329
1330/* Check whether a task has a particular permission to an inode.
1331 The 'adp' parameter is optional and allows other audit
1332 data to be passed (e.g. the dentry). */
1333static int inode_has_perm(struct task_struct *tsk,
1334 struct inode *inode,
1335 u32 perms,
1336 struct avc_audit_data *adp)
1337{
1338 struct task_security_struct *tsec;
1339 struct inode_security_struct *isec;
1340 struct avc_audit_data ad;
1341
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001342 if (unlikely (IS_PRIVATE (inode)))
1343 return 0;
1344
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 tsec = tsk->security;
1346 isec = inode->i_security;
1347
1348 if (!adp) {
1349 adp = &ad;
1350 AVC_AUDIT_DATA_INIT(&ad, FS);
1351 ad.u.fs.inode = inode;
1352 }
1353
1354 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1355}
1356
1357/* Same as inode_has_perm, but pass explicit audit data containing
1358 the dentry to help the auditing code to more easily generate the
1359 pathname if needed. */
1360static inline int dentry_has_perm(struct task_struct *tsk,
1361 struct vfsmount *mnt,
1362 struct dentry *dentry,
1363 u32 av)
1364{
1365 struct inode *inode = dentry->d_inode;
1366 struct avc_audit_data ad;
1367 AVC_AUDIT_DATA_INIT(&ad,FS);
1368 ad.u.fs.mnt = mnt;
1369 ad.u.fs.dentry = dentry;
1370 return inode_has_perm(tsk, inode, av, &ad);
1371}
1372
1373/* Check whether a task can use an open file descriptor to
1374 access an inode in a given way. Check access to the
1375 descriptor itself, and then use dentry_has_perm to
1376 check a particular permission to the file.
1377 Access to the descriptor is implicitly granted if it
1378 has the same SID as the process. If av is zero, then
1379 access to the file is not checked, e.g. for cases
1380 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001381static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 struct file *file,
1383 u32 av)
1384{
1385 struct task_security_struct *tsec = tsk->security;
1386 struct file_security_struct *fsec = file->f_security;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001387 struct vfsmount *mnt = file->f_path.mnt;
1388 struct dentry *dentry = file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 struct inode *inode = dentry->d_inode;
1390 struct avc_audit_data ad;
1391 int rc;
1392
1393 AVC_AUDIT_DATA_INIT(&ad, FS);
1394 ad.u.fs.mnt = mnt;
1395 ad.u.fs.dentry = dentry;
1396
1397 if (tsec->sid != fsec->sid) {
1398 rc = avc_has_perm(tsec->sid, fsec->sid,
1399 SECCLASS_FD,
1400 FD__USE,
1401 &ad);
1402 if (rc)
1403 return rc;
1404 }
1405
1406 /* av is zero if only checking access to the descriptor. */
1407 if (av)
1408 return inode_has_perm(tsk, inode, av, &ad);
1409
1410 return 0;
1411}
1412
1413/* Check whether a task can create a file. */
1414static int may_create(struct inode *dir,
1415 struct dentry *dentry,
1416 u16 tclass)
1417{
1418 struct task_security_struct *tsec;
1419 struct inode_security_struct *dsec;
1420 struct superblock_security_struct *sbsec;
1421 u32 newsid;
1422 struct avc_audit_data ad;
1423 int rc;
1424
1425 tsec = current->security;
1426 dsec = dir->i_security;
1427 sbsec = dir->i_sb->s_security;
1428
1429 AVC_AUDIT_DATA_INIT(&ad, FS);
1430 ad.u.fs.dentry = dentry;
1431
1432 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1433 DIR__ADD_NAME | DIR__SEARCH,
1434 &ad);
1435 if (rc)
1436 return rc;
1437
1438 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1439 newsid = tsec->create_sid;
1440 } else {
1441 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1442 &newsid);
1443 if (rc)
1444 return rc;
1445 }
1446
1447 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1448 if (rc)
1449 return rc;
1450
1451 return avc_has_perm(newsid, sbsec->sid,
1452 SECCLASS_FILESYSTEM,
1453 FILESYSTEM__ASSOCIATE, &ad);
1454}
1455
Michael LeMay4eb582c2006-06-26 00:24:57 -07001456/* Check whether a task can create a key. */
1457static int may_create_key(u32 ksid,
1458 struct task_struct *ctx)
1459{
1460 struct task_security_struct *tsec;
1461
1462 tsec = ctx->security;
1463
1464 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1465}
1466
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467#define MAY_LINK 0
1468#define MAY_UNLINK 1
1469#define MAY_RMDIR 2
1470
1471/* Check whether a task can link, unlink, or rmdir a file/directory. */
1472static int may_link(struct inode *dir,
1473 struct dentry *dentry,
1474 int kind)
1475
1476{
1477 struct task_security_struct *tsec;
1478 struct inode_security_struct *dsec, *isec;
1479 struct avc_audit_data ad;
1480 u32 av;
1481 int rc;
1482
1483 tsec = current->security;
1484 dsec = dir->i_security;
1485 isec = dentry->d_inode->i_security;
1486
1487 AVC_AUDIT_DATA_INIT(&ad, FS);
1488 ad.u.fs.dentry = dentry;
1489
1490 av = DIR__SEARCH;
1491 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1492 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1493 if (rc)
1494 return rc;
1495
1496 switch (kind) {
1497 case MAY_LINK:
1498 av = FILE__LINK;
1499 break;
1500 case MAY_UNLINK:
1501 av = FILE__UNLINK;
1502 break;
1503 case MAY_RMDIR:
1504 av = DIR__RMDIR;
1505 break;
1506 default:
1507 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1508 return 0;
1509 }
1510
1511 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1512 return rc;
1513}
1514
1515static inline int may_rename(struct inode *old_dir,
1516 struct dentry *old_dentry,
1517 struct inode *new_dir,
1518 struct dentry *new_dentry)
1519{
1520 struct task_security_struct *tsec;
1521 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1522 struct avc_audit_data ad;
1523 u32 av;
1524 int old_is_dir, new_is_dir;
1525 int rc;
1526
1527 tsec = current->security;
1528 old_dsec = old_dir->i_security;
1529 old_isec = old_dentry->d_inode->i_security;
1530 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1531 new_dsec = new_dir->i_security;
1532
1533 AVC_AUDIT_DATA_INIT(&ad, FS);
1534
1535 ad.u.fs.dentry = old_dentry;
1536 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1537 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1538 if (rc)
1539 return rc;
1540 rc = avc_has_perm(tsec->sid, old_isec->sid,
1541 old_isec->sclass, FILE__RENAME, &ad);
1542 if (rc)
1543 return rc;
1544 if (old_is_dir && new_dir != old_dir) {
1545 rc = avc_has_perm(tsec->sid, old_isec->sid,
1546 old_isec->sclass, DIR__REPARENT, &ad);
1547 if (rc)
1548 return rc;
1549 }
1550
1551 ad.u.fs.dentry = new_dentry;
1552 av = DIR__ADD_NAME | DIR__SEARCH;
1553 if (new_dentry->d_inode)
1554 av |= DIR__REMOVE_NAME;
1555 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1556 if (rc)
1557 return rc;
1558 if (new_dentry->d_inode) {
1559 new_isec = new_dentry->d_inode->i_security;
1560 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1561 rc = avc_has_perm(tsec->sid, new_isec->sid,
1562 new_isec->sclass,
1563 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1564 if (rc)
1565 return rc;
1566 }
1567
1568 return 0;
1569}
1570
1571/* Check whether a task can perform a filesystem operation. */
1572static int superblock_has_perm(struct task_struct *tsk,
1573 struct super_block *sb,
1574 u32 perms,
1575 struct avc_audit_data *ad)
1576{
1577 struct task_security_struct *tsec;
1578 struct superblock_security_struct *sbsec;
1579
1580 tsec = tsk->security;
1581 sbsec = sb->s_security;
1582 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1583 perms, ad);
1584}
1585
1586/* Convert a Linux mode and permission mask to an access vector. */
1587static inline u32 file_mask_to_av(int mode, int mask)
1588{
1589 u32 av = 0;
1590
1591 if ((mode & S_IFMT) != S_IFDIR) {
1592 if (mask & MAY_EXEC)
1593 av |= FILE__EXECUTE;
1594 if (mask & MAY_READ)
1595 av |= FILE__READ;
1596
1597 if (mask & MAY_APPEND)
1598 av |= FILE__APPEND;
1599 else if (mask & MAY_WRITE)
1600 av |= FILE__WRITE;
1601
1602 } else {
1603 if (mask & MAY_EXEC)
1604 av |= DIR__SEARCH;
1605 if (mask & MAY_WRITE)
1606 av |= DIR__WRITE;
1607 if (mask & MAY_READ)
1608 av |= DIR__READ;
1609 }
1610
1611 return av;
1612}
1613
1614/* Convert a Linux file to an access vector. */
1615static inline u32 file_to_av(struct file *file)
1616{
1617 u32 av = 0;
1618
1619 if (file->f_mode & FMODE_READ)
1620 av |= FILE__READ;
1621 if (file->f_mode & FMODE_WRITE) {
1622 if (file->f_flags & O_APPEND)
1623 av |= FILE__APPEND;
1624 else
1625 av |= FILE__WRITE;
1626 }
1627
1628 return av;
1629}
1630
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631/* Hook functions begin here. */
1632
1633static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1634{
1635 struct task_security_struct *psec = parent->security;
1636 struct task_security_struct *csec = child->security;
1637 int rc;
1638
1639 rc = secondary_ops->ptrace(parent,child);
1640 if (rc)
1641 return rc;
1642
1643 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1644 /* Save the SID of the tracing process for later use in apply_creds. */
Stephen Smalley341c2d82006-03-11 03:27:16 -08001645 if (!(child->ptrace & PT_PTRACED) && !rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 csec->ptrace_sid = psec->sid;
1647 return rc;
1648}
1649
1650static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1651 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1652{
1653 int error;
1654
1655 error = task_has_perm(current, target, PROCESS__GETCAP);
1656 if (error)
1657 return error;
1658
1659 return secondary_ops->capget(target, effective, inheritable, permitted);
1660}
1661
1662static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1663 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1664{
1665 int error;
1666
1667 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1668 if (error)
1669 return error;
1670
1671 return task_has_perm(current, target, PROCESS__SETCAP);
1672}
1673
1674static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1675 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1676{
1677 secondary_ops->capset_set(target, effective, inheritable, permitted);
1678}
1679
1680static int selinux_capable(struct task_struct *tsk, int cap)
1681{
1682 int rc;
1683
1684 rc = secondary_ops->capable(tsk, cap);
1685 if (rc)
1686 return rc;
1687
1688 return task_has_capability(tsk,cap);
1689}
1690
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001691static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1692{
1693 int buflen, rc;
1694 char *buffer, *path, *end;
1695
1696 rc = -ENOMEM;
1697 buffer = (char*)__get_free_page(GFP_KERNEL);
1698 if (!buffer)
1699 goto out;
1700
1701 buflen = PAGE_SIZE;
1702 end = buffer+buflen;
1703 *--end = '\0';
1704 buflen--;
1705 path = end-1;
1706 *path = '/';
1707 while (table) {
1708 const char *name = table->procname;
1709 size_t namelen = strlen(name);
1710 buflen -= namelen + 1;
1711 if (buflen < 0)
1712 goto out_free;
1713 end -= namelen;
1714 memcpy(end, name, namelen);
1715 *--end = '/';
1716 path = end;
1717 table = table->parent;
1718 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001719 buflen -= 4;
1720 if (buflen < 0)
1721 goto out_free;
1722 end -= 4;
1723 memcpy(end, "/sys", 4);
1724 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001725 rc = security_genfs_sid("proc", path, tclass, sid);
1726out_free:
1727 free_page((unsigned long)buffer);
1728out:
1729 return rc;
1730}
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732static int selinux_sysctl(ctl_table *table, int op)
1733{
1734 int error = 0;
1735 u32 av;
1736 struct task_security_struct *tsec;
1737 u32 tsid;
1738 int rc;
1739
1740 rc = secondary_ops->sysctl(table, op);
1741 if (rc)
1742 return rc;
1743
1744 tsec = current->security;
1745
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001746 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1747 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 if (rc) {
1749 /* Default to the well-defined sysctl SID. */
1750 tsid = SECINITSID_SYSCTL;
1751 }
1752
1753 /* The op values are "defined" in sysctl.c, thereby creating
1754 * a bad coupling between this module and sysctl.c */
1755 if(op == 001) {
1756 error = avc_has_perm(tsec->sid, tsid,
1757 SECCLASS_DIR, DIR__SEARCH, NULL);
1758 } else {
1759 av = 0;
1760 if (op & 004)
1761 av |= FILE__READ;
1762 if (op & 002)
1763 av |= FILE__WRITE;
1764 if (av)
1765 error = avc_has_perm(tsec->sid, tsid,
1766 SECCLASS_FILE, av, NULL);
1767 }
1768
1769 return error;
1770}
1771
1772static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1773{
1774 int rc = 0;
1775
1776 if (!sb)
1777 return 0;
1778
1779 switch (cmds) {
1780 case Q_SYNC:
1781 case Q_QUOTAON:
1782 case Q_QUOTAOFF:
1783 case Q_SETINFO:
1784 case Q_SETQUOTA:
1785 rc = superblock_has_perm(current,
1786 sb,
1787 FILESYSTEM__QUOTAMOD, NULL);
1788 break;
1789 case Q_GETFMT:
1790 case Q_GETINFO:
1791 case Q_GETQUOTA:
1792 rc = superblock_has_perm(current,
1793 sb,
1794 FILESYSTEM__QUOTAGET, NULL);
1795 break;
1796 default:
1797 rc = 0; /* let the kernel handle invalid cmds */
1798 break;
1799 }
1800 return rc;
1801}
1802
1803static int selinux_quota_on(struct dentry *dentry)
1804{
1805 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1806}
1807
1808static int selinux_syslog(int type)
1809{
1810 int rc;
1811
1812 rc = secondary_ops->syslog(type);
1813 if (rc)
1814 return rc;
1815
1816 switch (type) {
1817 case 3: /* Read last kernel messages */
1818 case 10: /* Return size of the log buffer */
1819 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1820 break;
1821 case 6: /* Disable logging to console */
1822 case 7: /* Enable logging to console */
1823 case 8: /* Set level of messages printed to console */
1824 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1825 break;
1826 case 0: /* Close log */
1827 case 1: /* Open log */
1828 case 2: /* Read from log */
1829 case 4: /* Read/clear last kernel messages */
1830 case 5: /* Clear ring buffer */
1831 default:
1832 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1833 break;
1834 }
1835 return rc;
1836}
1837
1838/*
1839 * Check that a process has enough memory to allocate a new virtual
1840 * mapping. 0 means there is enough memory for the allocation to
1841 * succeed and -ENOMEM implies there is not.
1842 *
1843 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1844 * if the capability is granted, but __vm_enough_memory requires 1 if
1845 * the capability is granted.
1846 *
1847 * Do not audit the selinux permission check, as this is applied to all
1848 * processes that allocate mappings.
1849 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001850static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851{
1852 int rc, cap_sys_admin = 0;
1853 struct task_security_struct *tsec = current->security;
1854
1855 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1856 if (rc == 0)
1857 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001858 SECCLASS_CAPABILITY,
1859 CAP_TO_MASK(CAP_SYS_ADMIN),
1860 0,
1861 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
1863 if (rc == 0)
1864 cap_sys_admin = 1;
1865
Alan Cox34b4e4a2007-08-22 14:01:28 -07001866 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867}
1868
1869/* binprm security operations */
1870
1871static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1872{
1873 struct bprm_security_struct *bsec;
1874
James Morris89d155e2005-10-30 14:59:21 -08001875 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 if (!bsec)
1877 return -ENOMEM;
1878
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 bsec->bprm = bprm;
1880 bsec->sid = SECINITSID_UNLABELED;
1881 bsec->set = 0;
1882
1883 bprm->security = bsec;
1884 return 0;
1885}
1886
1887static int selinux_bprm_set_security(struct linux_binprm *bprm)
1888{
1889 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001890 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 struct inode_security_struct *isec;
1892 struct bprm_security_struct *bsec;
1893 u32 newsid;
1894 struct avc_audit_data ad;
1895 int rc;
1896
1897 rc = secondary_ops->bprm_set_security(bprm);
1898 if (rc)
1899 return rc;
1900
1901 bsec = bprm->security;
1902
1903 if (bsec->set)
1904 return 0;
1905
1906 tsec = current->security;
1907 isec = inode->i_security;
1908
1909 /* Default to the current task SID. */
1910 bsec->sid = tsec->sid;
1911
Michael LeMay28eba5b2006-06-27 02:53:42 -07001912 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001914 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001915 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 if (tsec->exec_sid) {
1918 newsid = tsec->exec_sid;
1919 /* Reset exec SID on execve. */
1920 tsec->exec_sid = 0;
1921 } else {
1922 /* Check for a default transition on this program. */
1923 rc = security_transition_sid(tsec->sid, isec->sid,
1924 SECCLASS_PROCESS, &newsid);
1925 if (rc)
1926 return rc;
1927 }
1928
1929 AVC_AUDIT_DATA_INIT(&ad, FS);
Josef Sipek3d5ff522006-12-08 02:37:38 -08001930 ad.u.fs.mnt = bprm->file->f_path.mnt;
1931 ad.u.fs.dentry = bprm->file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Josef Sipek3d5ff522006-12-08 02:37:38 -08001933 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 newsid = tsec->sid;
1935
1936 if (tsec->sid == newsid) {
1937 rc = avc_has_perm(tsec->sid, isec->sid,
1938 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1939 if (rc)
1940 return rc;
1941 } else {
1942 /* Check permissions for the transition. */
1943 rc = avc_has_perm(tsec->sid, newsid,
1944 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1945 if (rc)
1946 return rc;
1947
1948 rc = avc_has_perm(newsid, isec->sid,
1949 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1950 if (rc)
1951 return rc;
1952
1953 /* Clear any possibly unsafe personality bits on exec: */
1954 current->personality &= ~PER_CLEAR_ON_SETID;
1955
1956 /* Set the security field to the new SID. */
1957 bsec->sid = newsid;
1958 }
1959
1960 bsec->set = 1;
1961 return 0;
1962}
1963
1964static int selinux_bprm_check_security (struct linux_binprm *bprm)
1965{
1966 return secondary_ops->bprm_check_security(bprm);
1967}
1968
1969
1970static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1971{
1972 struct task_security_struct *tsec = current->security;
1973 int atsecure = 0;
1974
1975 if (tsec->osid != tsec->sid) {
1976 /* Enable secure mode for SIDs transitions unless
1977 the noatsecure permission is granted between
1978 the two SIDs, i.e. ahp returns 0. */
1979 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1980 SECCLASS_PROCESS,
1981 PROCESS__NOATSECURE, NULL);
1982 }
1983
1984 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1985}
1986
1987static void selinux_bprm_free_security(struct linux_binprm *bprm)
1988{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07001989 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991}
1992
1993extern struct vfsmount *selinuxfs_mount;
1994extern struct dentry *selinux_null;
1995
1996/* Derived from fs/exec.c:flush_old_files. */
1997static inline void flush_unauthorized_files(struct files_struct * files)
1998{
1999 struct avc_audit_data ad;
2000 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002001 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002002 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002004 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002006 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002007 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 if (tty) {
2009 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08002010 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 if (file) {
2012 /* Revalidate access to controlling tty.
2013 Use inode_has_perm on the tty inode directly rather
2014 than using file_has_perm, as this particular open
2015 file may belong to another process and we are only
2016 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002017 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 if (inode_has_perm(current, inode,
2019 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002020 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 }
2022 }
2023 file_list_unlock();
2024 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002025 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002026 /* Reset controlling tty. */
2027 if (drop_tty)
2028 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
2030 /* Revalidate access to inherited open files. */
2031
2032 AVC_AUDIT_DATA_INIT(&ad,FS);
2033
2034 spin_lock(&files->file_lock);
2035 for (;;) {
2036 unsigned long set, i;
2037 int fd;
2038
2039 j++;
2040 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002041 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002042 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002044 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 if (!set)
2046 continue;
2047 spin_unlock(&files->file_lock);
2048 for ( ; set ; i++,set >>= 1) {
2049 if (set & 1) {
2050 file = fget(i);
2051 if (!file)
2052 continue;
2053 if (file_has_perm(current,
2054 file,
2055 file_to_av(file))) {
2056 sys_close(i);
2057 fd = get_unused_fd();
2058 if (fd != i) {
2059 if (fd >= 0)
2060 put_unused_fd(fd);
2061 fput(file);
2062 continue;
2063 }
2064 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002065 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 } else {
2067 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002068 if (IS_ERR(devnull)) {
2069 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 put_unused_fd(fd);
2071 fput(file);
2072 continue;
2073 }
2074 }
2075 fd_install(fd, devnull);
2076 }
2077 fput(file);
2078 }
2079 }
2080 spin_lock(&files->file_lock);
2081
2082 }
2083 spin_unlock(&files->file_lock);
2084}
2085
2086static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2087{
2088 struct task_security_struct *tsec;
2089 struct bprm_security_struct *bsec;
2090 u32 sid;
2091 int rc;
2092
2093 secondary_ops->bprm_apply_creds(bprm, unsafe);
2094
2095 tsec = current->security;
2096
2097 bsec = bprm->security;
2098 sid = bsec->sid;
2099
2100 tsec->osid = tsec->sid;
2101 bsec->unsafe = 0;
2102 if (tsec->sid != sid) {
2103 /* Check for shared state. If not ok, leave SID
2104 unchanged and kill. */
2105 if (unsafe & LSM_UNSAFE_SHARE) {
2106 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2107 PROCESS__SHARE, NULL);
2108 if (rc) {
2109 bsec->unsafe = 1;
2110 return;
2111 }
2112 }
2113
2114 /* Check for ptracing, and update the task SID if ok.
2115 Otherwise, leave SID unchanged and kill. */
2116 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2117 rc = avc_has_perm(tsec->ptrace_sid, sid,
2118 SECCLASS_PROCESS, PROCESS__PTRACE,
2119 NULL);
2120 if (rc) {
2121 bsec->unsafe = 1;
2122 return;
2123 }
2124 }
2125 tsec->sid = sid;
2126 }
2127}
2128
2129/*
2130 * called after apply_creds without the task lock held
2131 */
2132static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2133{
2134 struct task_security_struct *tsec;
2135 struct rlimit *rlim, *initrlim;
2136 struct itimerval itimer;
2137 struct bprm_security_struct *bsec;
2138 int rc, i;
2139
2140 tsec = current->security;
2141 bsec = bprm->security;
2142
2143 if (bsec->unsafe) {
2144 force_sig_specific(SIGKILL, current);
2145 return;
2146 }
2147 if (tsec->osid == tsec->sid)
2148 return;
2149
2150 /* Close files for which the new task SID is not authorized. */
2151 flush_unauthorized_files(current->files);
2152
2153 /* Check whether the new SID can inherit signal state
2154 from the old SID. If not, clear itimers to avoid
2155 subsequent signal generation and flush and unblock
2156 signals. This must occur _after_ the task SID has
2157 been updated so that any kill done after the flush
2158 will be checked against the new SID. */
2159 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2160 PROCESS__SIGINH, NULL);
2161 if (rc) {
2162 memset(&itimer, 0, sizeof itimer);
2163 for (i = 0; i < 3; i++)
2164 do_setitimer(i, &itimer, NULL);
2165 flush_signals(current);
2166 spin_lock_irq(&current->sighand->siglock);
2167 flush_signal_handlers(current, 1);
2168 sigemptyset(&current->blocked);
2169 recalc_sigpending();
2170 spin_unlock_irq(&current->sighand->siglock);
2171 }
2172
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002173 /* Always clear parent death signal on SID transitions. */
2174 current->pdeath_signal = 0;
2175
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 /* Check whether the new SID can inherit resource limits
2177 from the old SID. If not, reset all soft limits to
2178 the lower of the current task's hard limit and the init
2179 task's soft limit. Note that the setting of hard limits
2180 (even to lower them) can be controlled by the setrlimit
2181 check. The inclusion of the init task's soft limit into
2182 the computation is to avoid resetting soft limits higher
2183 than the default soft limit for cases where the default
2184 is lower than the hard limit, e.g. RLIMIT_CORE or
2185 RLIMIT_STACK.*/
2186 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2187 PROCESS__RLIMITINH, NULL);
2188 if (rc) {
2189 for (i = 0; i < RLIM_NLIMITS; i++) {
2190 rlim = current->signal->rlim + i;
2191 initrlim = init_task.signal->rlim+i;
2192 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
2193 }
2194 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2195 /*
2196 * This will cause RLIMIT_CPU calculations
2197 * to be refigured.
2198 */
2199 current->it_prof_expires = jiffies_to_cputime(1);
2200 }
2201 }
2202
2203 /* Wake up the parent if it is waiting so that it can
2204 recheck wait permission to the new task SID. */
2205 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2206}
2207
2208/* superblock security operations */
2209
2210static int selinux_sb_alloc_security(struct super_block *sb)
2211{
2212 return superblock_alloc_security(sb);
2213}
2214
2215static void selinux_sb_free_security(struct super_block *sb)
2216{
2217 superblock_free_security(sb);
2218}
2219
2220static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2221{
2222 if (plen > olen)
2223 return 0;
2224
2225 return !memcmp(prefix, option, plen);
2226}
2227
2228static inline int selinux_option(char *option, int len)
2229{
2230 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
2231 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
Eric Paris08089252006-07-10 04:43:55 -07002232 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
2233 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234}
2235
2236static inline void take_option(char **to, char *from, int *first, int len)
2237{
2238 if (!*first) {
2239 **to = ',';
2240 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002241 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 *first = 0;
2243 memcpy(*to, from, len);
2244 *to += len;
2245}
2246
Cory Olmo3528a952006-09-29 01:58:44 -07002247static inline void take_selinux_option(char **to, char *from, int *first,
2248 int len)
2249{
2250 int current_size = 0;
2251
2252 if (!*first) {
2253 **to = '|';
2254 *to += 1;
2255 }
2256 else
2257 *first = 0;
2258
2259 while (current_size < len) {
2260 if (*from != '"') {
2261 **to = *from;
2262 *to += 1;
2263 }
2264 from += 1;
2265 current_size += 1;
2266 }
2267}
2268
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
2270{
2271 int fnosec, fsec, rc = 0;
2272 char *in_save, *in_curr, *in_end;
2273 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002274 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
2276 in_curr = orig;
2277 sec_curr = copy;
2278
2279 /* Binary mount data: just copy */
2280 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2281 copy_page(sec_curr, in_curr);
2282 goto out;
2283 }
2284
2285 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2286 if (!nosec) {
2287 rc = -ENOMEM;
2288 goto out;
2289 }
2290
2291 nosec_save = nosec;
2292 fnosec = fsec = 1;
2293 in_save = in_end = orig;
2294
2295 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002296 if (*in_end == '"')
2297 open_quote = !open_quote;
2298 if ((*in_end == ',' && open_quote == 0) ||
2299 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 int len = in_end - in_curr;
2301
2302 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002303 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 else
2305 take_option(&nosec, in_curr, &fnosec, len);
2306
2307 in_curr = in_end + 1;
2308 }
2309 } while (*in_end++);
2310
Eric Paris6931dfc2005-06-30 02:58:51 -07002311 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002312 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313out:
2314 return rc;
2315}
2316
2317static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2318{
2319 struct avc_audit_data ad;
2320 int rc;
2321
2322 rc = superblock_doinit(sb, data);
2323 if (rc)
2324 return rc;
2325
2326 AVC_AUDIT_DATA_INIT(&ad,FS);
2327 ad.u.fs.dentry = sb->s_root;
2328 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2329}
2330
David Howells726c3342006-06-23 02:02:58 -07002331static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
2333 struct avc_audit_data ad;
2334
2335 AVC_AUDIT_DATA_INIT(&ad,FS);
David Howells726c3342006-06-23 02:02:58 -07002336 ad.u.fs.dentry = dentry->d_sb->s_root;
2337 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338}
2339
2340static int selinux_mount(char * dev_name,
2341 struct nameidata *nd,
2342 char * type,
2343 unsigned long flags,
2344 void * data)
2345{
2346 int rc;
2347
2348 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2349 if (rc)
2350 return rc;
2351
2352 if (flags & MS_REMOUNT)
2353 return superblock_has_perm(current, nd->mnt->mnt_sb,
2354 FILESYSTEM__REMOUNT, NULL);
2355 else
2356 return dentry_has_perm(current, nd->mnt, nd->dentry,
2357 FILE__MOUNTON);
2358}
2359
2360static int selinux_umount(struct vfsmount *mnt, int flags)
2361{
2362 int rc;
2363
2364 rc = secondary_ops->sb_umount(mnt, flags);
2365 if (rc)
2366 return rc;
2367
2368 return superblock_has_perm(current,mnt->mnt_sb,
2369 FILESYSTEM__UNMOUNT,NULL);
2370}
2371
2372/* inode security operations */
2373
2374static int selinux_inode_alloc_security(struct inode *inode)
2375{
2376 return inode_alloc_security(inode);
2377}
2378
2379static void selinux_inode_free_security(struct inode *inode)
2380{
2381 inode_free_security(inode);
2382}
2383
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002384static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2385 char **name, void **value,
2386 size_t *len)
2387{
2388 struct task_security_struct *tsec;
2389 struct inode_security_struct *dsec;
2390 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002391 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002392 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002393 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002394
2395 tsec = current->security;
2396 dsec = dir->i_security;
2397 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002398
2399 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2400 newsid = tsec->create_sid;
2401 } else {
2402 rc = security_transition_sid(tsec->sid, dsec->sid,
2403 inode_mode_to_security_class(inode->i_mode),
2404 &newsid);
2405 if (rc) {
2406 printk(KERN_WARNING "%s: "
2407 "security_transition_sid failed, rc=%d (dev=%s "
2408 "ino=%ld)\n",
2409 __FUNCTION__,
2410 -rc, inode->i_sb->s_id, inode->i_ino);
2411 return rc;
2412 }
2413 }
2414
Eric Paris296fddf2006-09-25 23:32:00 -07002415 /* Possibly defer initialization to selinux_complete_init. */
2416 if (sbsec->initialized) {
2417 struct inode_security_struct *isec = inode->i_security;
2418 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2419 isec->sid = newsid;
2420 isec->initialized = 1;
2421 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002422
Stephen Smalley8aad3872006-03-22 00:09:13 -08002423 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002424 return -EOPNOTSUPP;
2425
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002426 if (name) {
2427 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
2428 if (!namep)
2429 return -ENOMEM;
2430 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002431 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002432
2433 if (value && len) {
2434 rc = security_sid_to_context(newsid, &context, &clen);
2435 if (rc) {
2436 kfree(namep);
2437 return rc;
2438 }
2439 *value = context;
2440 *len = clen;
2441 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002442
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002443 return 0;
2444}
2445
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2447{
2448 return may_create(dir, dentry, SECCLASS_FILE);
2449}
2450
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2452{
2453 int rc;
2454
2455 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2456 if (rc)
2457 return rc;
2458 return may_link(dir, old_dentry, MAY_LINK);
2459}
2460
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2462{
2463 int rc;
2464
2465 rc = secondary_ops->inode_unlink(dir, dentry);
2466 if (rc)
2467 return rc;
2468 return may_link(dir, dentry, MAY_UNLINK);
2469}
2470
2471static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2472{
2473 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2474}
2475
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2477{
2478 return may_create(dir, dentry, SECCLASS_DIR);
2479}
2480
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2482{
2483 return may_link(dir, dentry, MAY_RMDIR);
2484}
2485
2486static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2487{
2488 int rc;
2489
2490 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2491 if (rc)
2492 return rc;
2493
2494 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2495}
2496
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2498 struct inode *new_inode, struct dentry *new_dentry)
2499{
2500 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2501}
2502
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503static int selinux_inode_readlink(struct dentry *dentry)
2504{
2505 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2506}
2507
2508static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2509{
2510 int rc;
2511
2512 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2513 if (rc)
2514 return rc;
2515 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2516}
2517
2518static int selinux_inode_permission(struct inode *inode, int mask,
2519 struct nameidata *nd)
2520{
2521 int rc;
2522
2523 rc = secondary_ops->inode_permission(inode, mask, nd);
2524 if (rc)
2525 return rc;
2526
2527 if (!mask) {
2528 /* No permission to check. Existence test. */
2529 return 0;
2530 }
2531
2532 return inode_has_perm(current, inode,
2533 file_mask_to_av(inode->i_mode, mask), NULL);
2534}
2535
2536static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2537{
2538 int rc;
2539
2540 rc = secondary_ops->inode_setattr(dentry, iattr);
2541 if (rc)
2542 return rc;
2543
2544 if (iattr->ia_valid & ATTR_FORCE)
2545 return 0;
2546
2547 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2548 ATTR_ATIME_SET | ATTR_MTIME_SET))
2549 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2550
2551 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2552}
2553
2554static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2555{
2556 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2557}
2558
Serge E. Hallynb5376772007-10-16 23:31:36 -07002559static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2560{
2561 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2562 sizeof XATTR_SECURITY_PREFIX - 1)) {
2563 if (!strcmp(name, XATTR_NAME_CAPS)) {
2564 if (!capable(CAP_SETFCAP))
2565 return -EPERM;
2566 } else if (!capable(CAP_SYS_ADMIN)) {
2567 /* A different attribute in the security namespace.
2568 Restrict to administrator. */
2569 return -EPERM;
2570 }
2571 }
2572
2573 /* Not an attribute we recognize, so just check the
2574 ordinary setattr permission. */
2575 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2576}
2577
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2579{
2580 struct task_security_struct *tsec = current->security;
2581 struct inode *inode = dentry->d_inode;
2582 struct inode_security_struct *isec = inode->i_security;
2583 struct superblock_security_struct *sbsec;
2584 struct avc_audit_data ad;
2585 u32 newsid;
2586 int rc = 0;
2587
Serge E. Hallynb5376772007-10-16 23:31:36 -07002588 if (strcmp(name, XATTR_NAME_SELINUX))
2589 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
2591 sbsec = inode->i_sb->s_security;
2592 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2593 return -EOPNOTSUPP;
2594
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302595 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 return -EPERM;
2597
2598 AVC_AUDIT_DATA_INIT(&ad,FS);
2599 ad.u.fs.dentry = dentry;
2600
2601 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2602 FILE__RELABELFROM, &ad);
2603 if (rc)
2604 return rc;
2605
2606 rc = security_context_to_sid(value, size, &newsid);
2607 if (rc)
2608 return rc;
2609
2610 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2611 FILE__RELABELTO, &ad);
2612 if (rc)
2613 return rc;
2614
2615 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2616 isec->sclass);
2617 if (rc)
2618 return rc;
2619
2620 return avc_has_perm(newsid,
2621 sbsec->sid,
2622 SECCLASS_FILESYSTEM,
2623 FILESYSTEM__ASSOCIATE,
2624 &ad);
2625}
2626
2627static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2628 void *value, size_t size, int flags)
2629{
2630 struct inode *inode = dentry->d_inode;
2631 struct inode_security_struct *isec = inode->i_security;
2632 u32 newsid;
2633 int rc;
2634
2635 if (strcmp(name, XATTR_NAME_SELINUX)) {
2636 /* Not an attribute we recognize, so nothing to do. */
2637 return;
2638 }
2639
2640 rc = security_context_to_sid(value, size, &newsid);
2641 if (rc) {
2642 printk(KERN_WARNING "%s: unable to obtain SID for context "
2643 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2644 return;
2645 }
2646
2647 isec->sid = newsid;
2648 return;
2649}
2650
2651static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2652{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2654}
2655
2656static int selinux_inode_listxattr (struct dentry *dentry)
2657{
2658 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2659}
2660
2661static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2662{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002663 if (strcmp(name, XATTR_NAME_SELINUX))
2664 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
2666 /* No one is allowed to remove a SELinux security label.
2667 You can change the label, but all data must be labeled. */
2668 return -EACCES;
2669}
2670
James Morrisd381d8a2005-10-30 14:59:22 -08002671/*
2672 * Copy the in-core inode security context value to the user. If the
2673 * getxattr() prior to this succeeded, check to see if we need to
2674 * canonicalize the value to be finally returned to the user.
2675 *
2676 * Permission check is handled by selinux_inode_getxattr hook.
2677 */
Dustin Kirkland7306a0b2005-11-16 15:53:13 +00002678static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679{
2680 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002682 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2683 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002685 return selinux_getsecurity(isec->sid, buffer, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
2688static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2689 const void *value, size_t size, int flags)
2690{
2691 struct inode_security_struct *isec = inode->i_security;
2692 u32 newsid;
2693 int rc;
2694
2695 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2696 return -EOPNOTSUPP;
2697
2698 if (!value || !size)
2699 return -EACCES;
2700
2701 rc = security_context_to_sid((void*)value, size, &newsid);
2702 if (rc)
2703 return rc;
2704
2705 isec->sid = newsid;
2706 return 0;
2707}
2708
2709static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2710{
2711 const int len = sizeof(XATTR_NAME_SELINUX);
2712 if (buffer && len <= buffer_size)
2713 memcpy(buffer, XATTR_NAME_SELINUX, len);
2714 return len;
2715}
2716
Serge E. Hallynb5376772007-10-16 23:31:36 -07002717static int selinux_inode_need_killpriv(struct dentry *dentry)
2718{
2719 return secondary_ops->inode_need_killpriv(dentry);
2720}
2721
2722static int selinux_inode_killpriv(struct dentry *dentry)
2723{
2724 return secondary_ops->inode_killpriv(dentry);
2725}
2726
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727/* file security operations */
2728
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002729static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002731 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002732 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
2734 if (!mask) {
2735 /* No permission to check. Existence test. */
2736 return 0;
2737 }
2738
2739 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2740 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2741 mask |= MAY_APPEND;
2742
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002743 rc = file_has_perm(current, file,
2744 file_mask_to_av(inode->i_mode, mask));
2745 if (rc)
2746 return rc;
2747
2748 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749}
2750
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002751static int selinux_file_permission(struct file *file, int mask)
2752{
2753 struct inode *inode = file->f_path.dentry->d_inode;
2754 struct task_security_struct *tsec = current->security;
2755 struct file_security_struct *fsec = file->f_security;
2756 struct inode_security_struct *isec = inode->i_security;
2757
2758 if (!mask) {
2759 /* No permission to check. Existence test. */
2760 return 0;
2761 }
2762
2763 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2764 && fsec->pseqno == avc_policy_seqno())
2765 return selinux_netlbl_inode_permission(inode, mask);
2766
2767 return selinux_revalidate_file_permission(file, mask);
2768}
2769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770static int selinux_file_alloc_security(struct file *file)
2771{
2772 return file_alloc_security(file);
2773}
2774
2775static void selinux_file_free_security(struct file *file)
2776{
2777 file_free_security(file);
2778}
2779
2780static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2781 unsigned long arg)
2782{
2783 int error = 0;
2784
2785 switch (cmd) {
2786 case FIONREAD:
2787 /* fall through */
2788 case FIBMAP:
2789 /* fall through */
2790 case FIGETBSZ:
2791 /* fall through */
2792 case EXT2_IOC_GETFLAGS:
2793 /* fall through */
2794 case EXT2_IOC_GETVERSION:
2795 error = file_has_perm(current, file, FILE__GETATTR);
2796 break;
2797
2798 case EXT2_IOC_SETFLAGS:
2799 /* fall through */
2800 case EXT2_IOC_SETVERSION:
2801 error = file_has_perm(current, file, FILE__SETATTR);
2802 break;
2803
2804 /* sys_ioctl() checks */
2805 case FIONBIO:
2806 /* fall through */
2807 case FIOASYNC:
2808 error = file_has_perm(current, file, 0);
2809 break;
2810
2811 case KDSKBENT:
2812 case KDSKBSENT:
2813 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2814 break;
2815
2816 /* default case assumes that the command will go
2817 * to the file's ioctl() function.
2818 */
2819 default:
2820 error = file_has_perm(current, file, FILE__IOCTL);
2821
2822 }
2823 return error;
2824}
2825
2826static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2827{
2828#ifndef CONFIG_PPC32
2829 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2830 /*
2831 * We are making executable an anonymous mapping or a
2832 * private file mapping that will also be writable.
2833 * This has an additional check.
2834 */
2835 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2836 if (rc)
2837 return rc;
2838 }
2839#endif
2840
2841 if (file) {
2842 /* read access is always possible with a mapping */
2843 u32 av = FILE__READ;
2844
2845 /* write access only matters if the mapping is shared */
2846 if (shared && (prot & PROT_WRITE))
2847 av |= FILE__WRITE;
2848
2849 if (prot & PROT_EXEC)
2850 av |= FILE__EXECUTE;
2851
2852 return file_has_perm(current, file, av);
2853 }
2854 return 0;
2855}
2856
2857static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002858 unsigned long prot, unsigned long flags,
2859 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
Eric Parised032182007-06-28 15:55:21 -04002861 int rc = 0;
2862 u32 sid = ((struct task_security_struct*)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
Eric Parised032182007-06-28 15:55:21 -04002864 if (addr < mmap_min_addr)
2865 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2866 MEMPROTECT__MMAP_ZERO, NULL);
2867 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 return rc;
2869
2870 if (selinux_checkreqprot)
2871 prot = reqprot;
2872
2873 return file_map_prot_check(file, prot,
2874 (flags & MAP_TYPE) == MAP_SHARED);
2875}
2876
2877static int selinux_file_mprotect(struct vm_area_struct *vma,
2878 unsigned long reqprot,
2879 unsigned long prot)
2880{
2881 int rc;
2882
2883 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2884 if (rc)
2885 return rc;
2886
2887 if (selinux_checkreqprot)
2888 prot = reqprot;
2889
2890#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002891 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2892 rc = 0;
2893 if (vma->vm_start >= vma->vm_mm->start_brk &&
2894 vma->vm_end <= vma->vm_mm->brk) {
2895 rc = task_has_perm(current, current,
2896 PROCESS__EXECHEAP);
2897 } else if (!vma->vm_file &&
2898 vma->vm_start <= vma->vm_mm->start_stack &&
2899 vma->vm_end >= vma->vm_mm->start_stack) {
2900 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2901 } else if (vma->vm_file && vma->anon_vma) {
2902 /*
2903 * We are making executable a file mapping that has
2904 * had some COW done. Since pages might have been
2905 * written, check ability to execute the possibly
2906 * modified content. This typically should only
2907 * occur for text relocations.
2908 */
2909 rc = file_has_perm(current, vma->vm_file,
2910 FILE__EXECMOD);
2911 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002912 if (rc)
2913 return rc;
2914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915#endif
2916
2917 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2918}
2919
2920static int selinux_file_lock(struct file *file, unsigned int cmd)
2921{
2922 return file_has_perm(current, file, FILE__LOCK);
2923}
2924
2925static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2926 unsigned long arg)
2927{
2928 int err = 0;
2929
2930 switch (cmd) {
2931 case F_SETFL:
Josef Sipek3d5ff522006-12-08 02:37:38 -08002932 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 err = -EINVAL;
2934 break;
2935 }
2936
2937 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2938 err = file_has_perm(current, file,FILE__WRITE);
2939 break;
2940 }
2941 /* fall through */
2942 case F_SETOWN:
2943 case F_SETSIG:
2944 case F_GETFL:
2945 case F_GETOWN:
2946 case F_GETSIG:
2947 /* Just check FD__USE permission */
2948 err = file_has_perm(current, file, 0);
2949 break;
2950 case F_GETLK:
2951 case F_SETLK:
2952 case F_SETLKW:
2953#if BITS_PER_LONG == 32
2954 case F_GETLK64:
2955 case F_SETLK64:
2956 case F_SETLKW64:
2957#endif
Josef Sipek3d5ff522006-12-08 02:37:38 -08002958 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 err = -EINVAL;
2960 break;
2961 }
2962 err = file_has_perm(current, file, FILE__LOCK);
2963 break;
2964 }
2965
2966 return err;
2967}
2968
2969static int selinux_file_set_fowner(struct file *file)
2970{
2971 struct task_security_struct *tsec;
2972 struct file_security_struct *fsec;
2973
2974 tsec = current->security;
2975 fsec = file->f_security;
2976 fsec->fown_sid = tsec->sid;
2977
2978 return 0;
2979}
2980
2981static int selinux_file_send_sigiotask(struct task_struct *tsk,
2982 struct fown_struct *fown, int signum)
2983{
2984 struct file *file;
2985 u32 perm;
2986 struct task_security_struct *tsec;
2987 struct file_security_struct *fsec;
2988
2989 /* struct fown_struct is never outside the context of a struct file */
Robert P. J. Dayb385a142007-02-10 01:46:25 -08002990 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 tsec = tsk->security;
2993 fsec = file->f_security;
2994
2995 if (!signum)
2996 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
2997 else
2998 perm = signal_to_av(signum);
2999
3000 return avc_has_perm(fsec->fown_sid, tsec->sid,
3001 SECCLASS_PROCESS, perm, NULL);
3002}
3003
3004static int selinux_file_receive(struct file *file)
3005{
3006 return file_has_perm(current, file, file_to_av(file));
3007}
3008
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003009static int selinux_dentry_open(struct file *file)
3010{
3011 struct file_security_struct *fsec;
3012 struct inode *inode;
3013 struct inode_security_struct *isec;
3014 inode = file->f_path.dentry->d_inode;
3015 fsec = file->f_security;
3016 isec = inode->i_security;
3017 /*
3018 * Save inode label and policy sequence number
3019 * at open-time so that selinux_file_permission
3020 * can determine whether revalidation is necessary.
3021 * Task label is already saved in the file security
3022 * struct as its SID.
3023 */
3024 fsec->isid = isec->sid;
3025 fsec->pseqno = avc_policy_seqno();
3026 /*
3027 * Since the inode label or policy seqno may have changed
3028 * between the selinux_inode_permission check and the saving
3029 * of state above, recheck that access is still permitted.
3030 * Otherwise, access might never be revalidated against the
3031 * new inode label or new policy.
3032 * This check is not redundant - do not remove.
3033 */
3034 return inode_has_perm(current, inode, file_to_av(file), NULL);
3035}
3036
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037/* task security operations */
3038
3039static int selinux_task_create(unsigned long clone_flags)
3040{
3041 int rc;
3042
3043 rc = secondary_ops->task_create(clone_flags);
3044 if (rc)
3045 return rc;
3046
3047 return task_has_perm(current, current, PROCESS__FORK);
3048}
3049
3050static int selinux_task_alloc_security(struct task_struct *tsk)
3051{
3052 struct task_security_struct *tsec1, *tsec2;
3053 int rc;
3054
3055 tsec1 = current->security;
3056
3057 rc = task_alloc_security(tsk);
3058 if (rc)
3059 return rc;
3060 tsec2 = tsk->security;
3061
3062 tsec2->osid = tsec1->osid;
3063 tsec2->sid = tsec1->sid;
3064
Michael LeMay28eba5b2006-06-27 02:53:42 -07003065 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 tsec2->exec_sid = tsec1->exec_sid;
3067 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003068 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003069 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
3071 /* Retain ptracer SID across fork, if any.
3072 This will be reset by the ptrace hook upon any
3073 subsequent ptrace_attach operations. */
3074 tsec2->ptrace_sid = tsec1->ptrace_sid;
3075
3076 return 0;
3077}
3078
3079static void selinux_task_free_security(struct task_struct *tsk)
3080{
3081 task_free_security(tsk);
3082}
3083
3084static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3085{
3086 /* Since setuid only affects the current process, and
3087 since the SELinux controls are not based on the Linux
3088 identity attributes, SELinux does not need to control
3089 this operation. However, SELinux does control the use
3090 of the CAP_SETUID and CAP_SETGID capabilities using the
3091 capable hook. */
3092 return 0;
3093}
3094
3095static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3096{
3097 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
3098}
3099
3100static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3101{
3102 /* See the comment for setuid above. */
3103 return 0;
3104}
3105
3106static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3107{
3108 return task_has_perm(current, p, PROCESS__SETPGID);
3109}
3110
3111static int selinux_task_getpgid(struct task_struct *p)
3112{
3113 return task_has_perm(current, p, PROCESS__GETPGID);
3114}
3115
3116static int selinux_task_getsid(struct task_struct *p)
3117{
3118 return task_has_perm(current, p, PROCESS__GETSESSION);
3119}
3120
David Quigleyf9008e42006-06-30 01:55:46 -07003121static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3122{
3123 selinux_get_task_sid(p, secid);
3124}
3125
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126static int selinux_task_setgroups(struct group_info *group_info)
3127{
3128 /* See the comment for setuid above. */
3129 return 0;
3130}
3131
3132static int selinux_task_setnice(struct task_struct *p, int nice)
3133{
3134 int rc;
3135
3136 rc = secondary_ops->task_setnice(p, nice);
3137 if (rc)
3138 return rc;
3139
3140 return task_has_perm(current,p, PROCESS__SETSCHED);
3141}
3142
James Morris03e68062006-06-23 02:03:58 -07003143static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3144{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003145 int rc;
3146
3147 rc = secondary_ops->task_setioprio(p, ioprio);
3148 if (rc)
3149 return rc;
3150
James Morris03e68062006-06-23 02:03:58 -07003151 return task_has_perm(current, p, PROCESS__SETSCHED);
3152}
3153
David Quigleya1836a42006-06-30 01:55:49 -07003154static int selinux_task_getioprio(struct task_struct *p)
3155{
3156 return task_has_perm(current, p, PROCESS__GETSCHED);
3157}
3158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3160{
3161 struct rlimit *old_rlim = current->signal->rlim + resource;
3162 int rc;
3163
3164 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3165 if (rc)
3166 return rc;
3167
3168 /* Control the ability to change the hard limit (whether
3169 lowering or raising it), so that the hard limit can
3170 later be used as a safe reset point for the soft limit
3171 upon context transitions. See selinux_bprm_apply_creds. */
3172 if (old_rlim->rlim_max != new_rlim->rlim_max)
3173 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3174
3175 return 0;
3176}
3177
3178static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3179{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003180 int rc;
3181
3182 rc = secondary_ops->task_setscheduler(p, policy, lp);
3183 if (rc)
3184 return rc;
3185
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return task_has_perm(current, p, PROCESS__SETSCHED);
3187}
3188
3189static int selinux_task_getscheduler(struct task_struct *p)
3190{
3191 return task_has_perm(current, p, PROCESS__GETSCHED);
3192}
3193
David Quigley35601542006-06-23 02:04:01 -07003194static int selinux_task_movememory(struct task_struct *p)
3195{
3196 return task_has_perm(current, p, PROCESS__SETSCHED);
3197}
3198
David Quigleyf9008e42006-06-30 01:55:46 -07003199static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3200 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201{
3202 u32 perm;
3203 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003204 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
David Quigleyf9008e42006-06-30 01:55:46 -07003206 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 if (rc)
3208 return rc;
3209
Oleg Nesterov621d3122005-10-30 15:03:45 -08003210 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 return 0;
3212
3213 if (!sig)
3214 perm = PROCESS__SIGNULL; /* null signal; existence test */
3215 else
3216 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003217 tsec = p->security;
3218 if (secid)
3219 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3220 else
3221 rc = task_has_perm(current, p, perm);
3222 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223}
3224
3225static int selinux_task_prctl(int option,
3226 unsigned long arg2,
3227 unsigned long arg3,
3228 unsigned long arg4,
3229 unsigned long arg5)
3230{
3231 /* The current prctl operations do not appear to require
3232 any SELinux controls since they merely observe or modify
3233 the state of the current process. */
3234 return 0;
3235}
3236
3237static int selinux_task_wait(struct task_struct *p)
3238{
Eric Paris8a535142007-10-22 16:10:31 -04003239 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240}
3241
3242static void selinux_task_reparent_to_init(struct task_struct *p)
3243{
3244 struct task_security_struct *tsec;
3245
3246 secondary_ops->task_reparent_to_init(p);
3247
3248 tsec = p->security;
3249 tsec->osid = tsec->sid;
3250 tsec->sid = SECINITSID_KERNEL;
3251 return;
3252}
3253
3254static void selinux_task_to_inode(struct task_struct *p,
3255 struct inode *inode)
3256{
3257 struct task_security_struct *tsec = p->security;
3258 struct inode_security_struct *isec = inode->i_security;
3259
3260 isec->sid = tsec->sid;
3261 isec->initialized = 1;
3262 return;
3263}
3264
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003266static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3267 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268{
3269 int offset, ihlen, ret = -EINVAL;
3270 struct iphdr _iph, *ih;
3271
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003272 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3274 if (ih == NULL)
3275 goto out;
3276
3277 ihlen = ih->ihl * 4;
3278 if (ihlen < sizeof(_iph))
3279 goto out;
3280
3281 ad->u.net.v4info.saddr = ih->saddr;
3282 ad->u.net.v4info.daddr = ih->daddr;
3283 ret = 0;
3284
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003285 if (proto)
3286 *proto = ih->protocol;
3287
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 switch (ih->protocol) {
3289 case IPPROTO_TCP: {
3290 struct tcphdr _tcph, *th;
3291
3292 if (ntohs(ih->frag_off) & IP_OFFSET)
3293 break;
3294
3295 offset += ihlen;
3296 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3297 if (th == NULL)
3298 break;
3299
3300 ad->u.net.sport = th->source;
3301 ad->u.net.dport = th->dest;
3302 break;
3303 }
3304
3305 case IPPROTO_UDP: {
3306 struct udphdr _udph, *uh;
3307
3308 if (ntohs(ih->frag_off) & IP_OFFSET)
3309 break;
3310
3311 offset += ihlen;
3312 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3313 if (uh == NULL)
3314 break;
3315
3316 ad->u.net.sport = uh->source;
3317 ad->u.net.dport = uh->dest;
3318 break;
3319 }
3320
James Morris2ee92d42006-11-13 16:09:01 -08003321 case IPPROTO_DCCP: {
3322 struct dccp_hdr _dccph, *dh;
3323
3324 if (ntohs(ih->frag_off) & IP_OFFSET)
3325 break;
3326
3327 offset += ihlen;
3328 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3329 if (dh == NULL)
3330 break;
3331
3332 ad->u.net.sport = dh->dccph_sport;
3333 ad->u.net.dport = dh->dccph_dport;
3334 break;
3335 }
3336
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 default:
3338 break;
3339 }
3340out:
3341 return ret;
3342}
3343
3344#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3345
3346/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003347static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3348 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349{
3350 u8 nexthdr;
3351 int ret = -EINVAL, offset;
3352 struct ipv6hdr _ipv6h, *ip6;
3353
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003354 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3356 if (ip6 == NULL)
3357 goto out;
3358
3359 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3360 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3361 ret = 0;
3362
3363 nexthdr = ip6->nexthdr;
3364 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003365 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 if (offset < 0)
3367 goto out;
3368
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003369 if (proto)
3370 *proto = nexthdr;
3371
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 switch (nexthdr) {
3373 case IPPROTO_TCP: {
3374 struct tcphdr _tcph, *th;
3375
3376 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3377 if (th == NULL)
3378 break;
3379
3380 ad->u.net.sport = th->source;
3381 ad->u.net.dport = th->dest;
3382 break;
3383 }
3384
3385 case IPPROTO_UDP: {
3386 struct udphdr _udph, *uh;
3387
3388 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3389 if (uh == NULL)
3390 break;
3391
3392 ad->u.net.sport = uh->source;
3393 ad->u.net.dport = uh->dest;
3394 break;
3395 }
3396
James Morris2ee92d42006-11-13 16:09:01 -08003397 case IPPROTO_DCCP: {
3398 struct dccp_hdr _dccph, *dh;
3399
3400 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3401 if (dh == NULL)
3402 break;
3403
3404 ad->u.net.sport = dh->dccph_sport;
3405 ad->u.net.dport = dh->dccph_dport;
3406 break;
3407 }
3408
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 /* includes fragments */
3410 default:
3411 break;
3412 }
3413out:
3414 return ret;
3415}
3416
3417#endif /* IPV6 */
3418
3419static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003420 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421{
3422 int ret = 0;
3423
3424 switch (ad->u.net.family) {
3425 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003426 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 if (ret || !addrp)
3428 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3430 &ad->u.net.v4info.daddr);
3431 break;
3432
3433#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3434 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003435 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 if (ret || !addrp)
3437 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3439 &ad->u.net.v6info.daddr);
3440 break;
3441#endif /* IPV6 */
3442 default:
3443 break;
3444 }
3445
3446 return ret;
3447}
3448
Paul Moore4f6a9932007-03-01 14:35:22 -05003449/**
Paul Moore220deb92008-01-29 08:38:23 -05003450 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003451 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003452 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003453 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003454 *
3455 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003456 * Check the various different forms of network peer labeling and determine
3457 * the peer label/SID for the packet; most of the magic actually occurs in
3458 * the security server function security_net_peersid_cmp(). The function
3459 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3460 * or -EACCES if @sid is invalid due to inconsistencies with the different
3461 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003462 *
3463 */
Paul Moore220deb92008-01-29 08:38:23 -05003464static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003465{
3466 u32 xfrm_sid;
3467 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003468 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003469
3470 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003471 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003472
3473 if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
3474 xfrm_sid,
3475 sid) != 0)
3476 return -EACCES;
3477
3478 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003479}
3480
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481/* socket security operations */
3482static int socket_has_perm(struct task_struct *task, struct socket *sock,
3483 u32 perms)
3484{
3485 struct inode_security_struct *isec;
3486 struct task_security_struct *tsec;
3487 struct avc_audit_data ad;
3488 int err = 0;
3489
3490 tsec = task->security;
3491 isec = SOCK_INODE(sock)->i_security;
3492
3493 if (isec->sid == SECINITSID_KERNEL)
3494 goto out;
3495
3496 AVC_AUDIT_DATA_INIT(&ad,NET);
3497 ad.u.net.sk = sock->sk;
3498 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3499
3500out:
3501 return err;
3502}
3503
3504static int selinux_socket_create(int family, int type,
3505 int protocol, int kern)
3506{
3507 int err = 0;
3508 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003509 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510
3511 if (kern)
3512 goto out;
3513
3514 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003515 newsid = tsec->sockcreate_sid ? : tsec->sid;
3516 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 socket_type_to_security_class(family, type,
3518 protocol), SOCKET__CREATE, NULL);
3519
3520out:
3521 return err;
3522}
3523
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003524static int selinux_socket_post_create(struct socket *sock, int family,
3525 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003527 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 struct inode_security_struct *isec;
3529 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003530 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003531 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532
3533 isec = SOCK_INODE(sock)->i_security;
3534
3535 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003536 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003538 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 isec->initialized = 1;
3540
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003541 if (sock->sk) {
3542 sksec = sock->sk->sk_security;
3543 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003544 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003545 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003546 }
3547
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003548 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549}
3550
3551/* Range of port numbers used to automatically bind.
3552 Need to determine whether we should perform a name_bind
3553 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554
3555static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3556{
3557 u16 family;
3558 int err;
3559
3560 err = socket_has_perm(current, sock, SOCKET__BIND);
3561 if (err)
3562 goto out;
3563
3564 /*
3565 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003566 * Multiple address binding for SCTP is not supported yet: we just
3567 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 */
3569 family = sock->sk->sk_family;
3570 if (family == PF_INET || family == PF_INET6) {
3571 char *addrp;
3572 struct inode_security_struct *isec;
3573 struct task_security_struct *tsec;
3574 struct avc_audit_data ad;
3575 struct sockaddr_in *addr4 = NULL;
3576 struct sockaddr_in6 *addr6 = NULL;
3577 unsigned short snum;
3578 struct sock *sk = sock->sk;
3579 u32 sid, node_perm, addrlen;
3580
3581 tsec = current->security;
3582 isec = SOCK_INODE(sock)->i_security;
3583
3584 if (family == PF_INET) {
3585 addr4 = (struct sockaddr_in *)address;
3586 snum = ntohs(addr4->sin_port);
3587 addrlen = sizeof(addr4->sin_addr.s_addr);
3588 addrp = (char *)&addr4->sin_addr.s_addr;
3589 } else {
3590 addr6 = (struct sockaddr_in6 *)address;
3591 snum = ntohs(addr6->sin6_port);
3592 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3593 addrp = (char *)&addr6->sin6_addr.s6_addr;
3594 }
3595
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003596 if (snum) {
3597 int low, high;
3598
3599 inet_get_local_port_range(&low, &high);
3600
3601 if (snum < max(PROT_SOCK, low) || snum > high) {
3602 err = security_port_sid(sk->sk_family,
3603 sk->sk_type,
3604 sk->sk_protocol, snum,
3605 &sid);
3606 if (err)
3607 goto out;
3608 AVC_AUDIT_DATA_INIT(&ad,NET);
3609 ad.u.net.sport = htons(snum);
3610 ad.u.net.family = family;
3611 err = avc_has_perm(isec->sid, sid,
3612 isec->sclass,
3613 SOCKET__NAME_BIND, &ad);
3614 if (err)
3615 goto out;
3616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 }
3618
James Morris13402582005-09-30 14:24:34 -04003619 switch(isec->sclass) {
3620 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 node_perm = TCP_SOCKET__NODE_BIND;
3622 break;
3623
James Morris13402582005-09-30 14:24:34 -04003624 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 node_perm = UDP_SOCKET__NODE_BIND;
3626 break;
James Morris2ee92d42006-11-13 16:09:01 -08003627
3628 case SECCLASS_DCCP_SOCKET:
3629 node_perm = DCCP_SOCKET__NODE_BIND;
3630 break;
3631
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 default:
3633 node_perm = RAWIP_SOCKET__NODE_BIND;
3634 break;
3635 }
3636
Paul Moore224dfbd2008-01-29 08:38:13 -05003637 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 if (err)
3639 goto out;
3640
3641 AVC_AUDIT_DATA_INIT(&ad,NET);
3642 ad.u.net.sport = htons(snum);
3643 ad.u.net.family = family;
3644
3645 if (family == PF_INET)
3646 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3647 else
3648 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3649
3650 err = avc_has_perm(isec->sid, sid,
3651 isec->sclass, node_perm, &ad);
3652 if (err)
3653 goto out;
3654 }
3655out:
3656 return err;
3657}
3658
3659static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3660{
3661 struct inode_security_struct *isec;
3662 int err;
3663
3664 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3665 if (err)
3666 return err;
3667
3668 /*
James Morris2ee92d42006-11-13 16:09:01 -08003669 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 */
3671 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003672 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3673 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674 struct sock *sk = sock->sk;
3675 struct avc_audit_data ad;
3676 struct sockaddr_in *addr4 = NULL;
3677 struct sockaddr_in6 *addr6 = NULL;
3678 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003679 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
3681 if (sk->sk_family == PF_INET) {
3682 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003683 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 return -EINVAL;
3685 snum = ntohs(addr4->sin_port);
3686 } else {
3687 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003688 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 return -EINVAL;
3690 snum = ntohs(addr6->sin6_port);
3691 }
3692
3693 err = security_port_sid(sk->sk_family, sk->sk_type,
3694 sk->sk_protocol, snum, &sid);
3695 if (err)
3696 goto out;
3697
James Morris2ee92d42006-11-13 16:09:01 -08003698 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3699 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3700
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 AVC_AUDIT_DATA_INIT(&ad,NET);
3702 ad.u.net.dport = htons(snum);
3703 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003704 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 if (err)
3706 goto out;
3707 }
3708
3709out:
3710 return err;
3711}
3712
3713static int selinux_socket_listen(struct socket *sock, int backlog)
3714{
3715 return socket_has_perm(current, sock, SOCKET__LISTEN);
3716}
3717
3718static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3719{
3720 int err;
3721 struct inode_security_struct *isec;
3722 struct inode_security_struct *newisec;
3723
3724 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3725 if (err)
3726 return err;
3727
3728 newisec = SOCK_INODE(newsock)->i_security;
3729
3730 isec = SOCK_INODE(sock)->i_security;
3731 newisec->sclass = isec->sclass;
3732 newisec->sid = isec->sid;
3733 newisec->initialized = 1;
3734
3735 return 0;
3736}
3737
3738static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3739 int size)
3740{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003741 int rc;
3742
3743 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3744 if (rc)
3745 return rc;
3746
3747 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748}
3749
3750static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3751 int size, int flags)
3752{
3753 return socket_has_perm(current, sock, SOCKET__READ);
3754}
3755
3756static int selinux_socket_getsockname(struct socket *sock)
3757{
3758 return socket_has_perm(current, sock, SOCKET__GETATTR);
3759}
3760
3761static int selinux_socket_getpeername(struct socket *sock)
3762{
3763 return socket_has_perm(current, sock, SOCKET__GETATTR);
3764}
3765
3766static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3767{
Paul Mooref8687af2006-10-30 15:22:15 -08003768 int err;
3769
3770 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3771 if (err)
3772 return err;
3773
3774 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775}
3776
3777static int selinux_socket_getsockopt(struct socket *sock, int level,
3778 int optname)
3779{
3780 return socket_has_perm(current, sock, SOCKET__GETOPT);
3781}
3782
3783static int selinux_socket_shutdown(struct socket *sock, int how)
3784{
3785 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3786}
3787
3788static int selinux_socket_unix_stream_connect(struct socket *sock,
3789 struct socket *other,
3790 struct sock *newsk)
3791{
3792 struct sk_security_struct *ssec;
3793 struct inode_security_struct *isec;
3794 struct inode_security_struct *other_isec;
3795 struct avc_audit_data ad;
3796 int err;
3797
3798 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3799 if (err)
3800 return err;
3801
3802 isec = SOCK_INODE(sock)->i_security;
3803 other_isec = SOCK_INODE(other)->i_security;
3804
3805 AVC_AUDIT_DATA_INIT(&ad,NET);
3806 ad.u.net.sk = other->sk;
3807
3808 err = avc_has_perm(isec->sid, other_isec->sid,
3809 isec->sclass,
3810 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3811 if (err)
3812 return err;
3813
3814 /* connecting socket */
3815 ssec = sock->sk->sk_security;
3816 ssec->peer_sid = other_isec->sid;
3817
3818 /* server child socket */
3819 ssec = newsk->sk_security;
3820 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003821 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3822
3823 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824}
3825
3826static int selinux_socket_unix_may_send(struct socket *sock,
3827 struct socket *other)
3828{
3829 struct inode_security_struct *isec;
3830 struct inode_security_struct *other_isec;
3831 struct avc_audit_data ad;
3832 int err;
3833
3834 isec = SOCK_INODE(sock)->i_security;
3835 other_isec = SOCK_INODE(other)->i_security;
3836
3837 AVC_AUDIT_DATA_INIT(&ad,NET);
3838 ad.u.net.sk = other->sk;
3839
3840 err = avc_has_perm(isec->sid, other_isec->sid,
3841 isec->sclass, SOCKET__SENDTO, &ad);
3842 if (err)
3843 return err;
3844
3845 return 0;
3846}
3847
Paul Mooreeffad8d2008-01-29 08:49:27 -05003848static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3849 u32 peer_sid,
3850 struct avc_audit_data *ad)
3851{
3852 int err;
3853 u32 if_sid;
3854 u32 node_sid;
3855
3856 err = sel_netif_sid(ifindex, &if_sid);
3857 if (err)
3858 return err;
3859 err = avc_has_perm(peer_sid, if_sid,
3860 SECCLASS_NETIF, NETIF__INGRESS, ad);
3861 if (err)
3862 return err;
3863
3864 err = sel_netnode_sid(addrp, family, &node_sid);
3865 if (err)
3866 return err;
3867 return avc_has_perm(peer_sid, node_sid,
3868 SECCLASS_NODE, NODE__RECVFROM, ad);
3869}
3870
Paul Moore220deb92008-01-29 08:38:23 -05003871static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3872 struct sk_buff *skb,
3873 struct avc_audit_data *ad,
3874 u16 family,
3875 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876{
Paul Moore220deb92008-01-29 08:38:23 -05003877 int err;
3878 struct sk_security_struct *sksec = sk->sk_security;
3879 u16 sk_class;
3880 u32 netif_perm, node_perm, recv_perm;
3881 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003882
Paul Moore220deb92008-01-29 08:38:23 -05003883 sk_sid = sksec->sid;
3884 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
Paul Moore220deb92008-01-29 08:38:23 -05003886 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 case SECCLASS_UDP_SOCKET:
3888 netif_perm = NETIF__UDP_RECV;
3889 node_perm = NODE__UDP_RECV;
3890 recv_perm = UDP_SOCKET__RECV_MSG;
3891 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 case SECCLASS_TCP_SOCKET:
3893 netif_perm = NETIF__TCP_RECV;
3894 node_perm = NODE__TCP_RECV;
3895 recv_perm = TCP_SOCKET__RECV_MSG;
3896 break;
James Morris2ee92d42006-11-13 16:09:01 -08003897 case SECCLASS_DCCP_SOCKET:
3898 netif_perm = NETIF__DCCP_RECV;
3899 node_perm = NODE__DCCP_RECV;
3900 recv_perm = DCCP_SOCKET__RECV_MSG;
3901 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 default:
3903 netif_perm = NETIF__RAWIP_RECV;
3904 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003905 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 break;
3907 }
3908
Paul Moore220deb92008-01-29 08:38:23 -05003909 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003911 return err;
3912 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3913 if (err)
3914 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
Paul Moore224dfbd2008-01-29 08:38:13 -05003916 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003918 return err;
3919 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003921 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
Paul Moore220deb92008-01-29 08:38:23 -05003923 if (!recv_perm)
3924 return 0;
3925 err = security_port_sid(sk->sk_family, sk->sk_type,
3926 sk->sk_protocol, ntohs(ad->u.net.sport),
3927 &port_sid);
3928 if (err)
3929 return err;
3930 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3931}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932
Paul Moore220deb92008-01-29 08:38:23 -05003933static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3934 struct avc_audit_data *ad,
3935 u16 family, char *addrp)
3936{
3937 int err;
3938 struct sk_security_struct *sksec = sk->sk_security;
3939 u32 peer_sid;
3940 u32 sk_sid = sksec->sid;
3941
3942 if (selinux_compat_net)
3943 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3944 family, addrp);
3945 else
3946 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3947 PACKET__RECV, ad);
3948 if (err)
3949 return err;
3950
3951 if (selinux_policycap_netpeer) {
3952 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003954 return err;
3955 err = avc_has_perm(sk_sid, peer_sid,
3956 SECCLASS_PEER, PEER__RECV, ad);
3957 } else {
3958 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3959 if (err)
3960 return err;
3961 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003963
James Morris4e5ab4c2006-06-09 00:33:33 -07003964 return err;
3965}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003966
James Morris4e5ab4c2006-06-09 00:33:33 -07003967static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3968{
Paul Moore220deb92008-01-29 08:38:23 -05003969 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003970 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05003971 u16 family = sk->sk_family;
3972 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003973 struct avc_audit_data ad;
3974 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07003975
James Morris4e5ab4c2006-06-09 00:33:33 -07003976 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05003977 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07003978
3979 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00003980 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07003981 family = PF_INET;
3982
James Morris4e5ab4c2006-06-09 00:33:33 -07003983 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05003984 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07003985 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05003986 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07003987 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003988 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07003989
Paul Moore220deb92008-01-29 08:38:23 -05003990 /* If any sort of compatibility mode is enabled then handoff processing
3991 * to the selinux_sock_rcv_skb_compat() function to deal with the
3992 * special handling. We do this in an attempt to keep this function
3993 * as fast and as clean as possible. */
3994 if (selinux_compat_net || !selinux_policycap_netpeer)
3995 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3996 family, addrp);
3997
Paul Moored621d352008-01-29 08:43:36 -05003998 if (netlbl_enabled() || selinux_xfrm_enabled()) {
3999 u32 peer_sid;
4000
4001 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4002 if (err)
4003 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004004 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4005 peer_sid, &ad);
4006 if (err)
4007 return err;
Paul Moored621d352008-01-29 08:43:36 -05004008 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4009 PEER__RECV, &ad);
4010 }
4011
Paul Mooreeffad8d2008-01-29 08:49:27 -05004012 if (selinux_secmark_enabled()) {
4013 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4014 PACKET__RECV, &ad);
4015 if (err)
4016 return err;
4017 }
4018
Paul Moored621d352008-01-29 08:43:36 -05004019 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020}
4021
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004022static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4023 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024{
4025 int err = 0;
4026 char *scontext;
4027 u32 scontext_len;
4028 struct sk_security_struct *ssec;
4029 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004030 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
4032 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004033
Paul Moore3de4bab2006-11-17 17:38:54 -05004034 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4035 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004036 ssec = sock->sk->sk_security;
4037 peer_sid = ssec->peer_sid;
4038 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004039 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040 err = -ENOPROTOOPT;
4041 goto out;
4042 }
4043
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004044 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 if (err)
4047 goto out;
4048
4049 if (scontext_len > len) {
4050 err = -ERANGE;
4051 goto out_len;
4052 }
4053
4054 if (copy_to_user(optval, scontext, scontext_len))
4055 err = -EFAULT;
4056
4057out_len:
4058 if (put_user(scontext_len, optlen))
4059 err = -EFAULT;
4060
4061 kfree(scontext);
4062out:
4063 return err;
4064}
4065
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004066static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004067{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004068 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004069 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004070
Paul Moore75e22912008-01-29 08:38:04 -05004071 if (sock)
4072 family = sock->sk->sk_family;
4073 else if (skb && skb->sk)
4074 family = skb->sk->sk_family;
4075 else
4076 goto out;
4077
4078 if (sock && family == PF_UNIX)
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004079 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004080 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004081 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004082
Paul Moore75e22912008-01-29 08:38:04 -05004083out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004084 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004085 if (peer_secid == SECSID_NULL)
4086 return -EINVAL;
4087 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004088}
4089
Al Viro7d877f32005-10-21 03:20:43 -04004090static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091{
4092 return sk_alloc_security(sk, family, priority);
4093}
4094
4095static void selinux_sk_free_security(struct sock *sk)
4096{
4097 sk_free_security(sk);
4098}
4099
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004100static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4101{
4102 struct sk_security_struct *ssec = sk->sk_security;
4103 struct sk_security_struct *newssec = newsk->sk_security;
4104
4105 newssec->sid = ssec->sid;
4106 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004107 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004108
Paul Moore9f2ad662006-11-17 17:38:53 -05004109 selinux_netlbl_sk_security_clone(ssec, newssec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004110}
4111
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004112static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004113{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004114 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004115 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004116 else {
4117 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004118
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004119 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004120 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004121}
4122
Adrian Bunk9a673e52006-08-15 00:03:53 -07004123static void selinux_sock_graft(struct sock* sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004124{
4125 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4126 struct sk_security_struct *sksec = sk->sk_security;
4127
David Woodhouse2148ccc2006-09-29 15:50:25 -07004128 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4129 sk->sk_family == PF_UNIX)
4130 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004131 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004132
4133 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004134}
4135
Adrian Bunk9a673e52006-08-15 00:03:53 -07004136static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4137 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004138{
4139 struct sk_security_struct *sksec = sk->sk_security;
4140 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004141 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004142 u32 peersid;
4143
Paul Moore220deb92008-01-29 08:38:23 -05004144 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4145 if (err)
4146 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004147 if (peersid == SECSID_NULL) {
4148 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004149 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004150 return 0;
4151 }
4152
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004153 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4154 if (err)
4155 return err;
4156
4157 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004158 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004159 return 0;
4160}
4161
Adrian Bunk9a673e52006-08-15 00:03:53 -07004162static void selinux_inet_csk_clone(struct sock *newsk,
4163 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004164{
4165 struct sk_security_struct *newsksec = newsk->sk_security;
4166
4167 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004168 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004169 /* NOTE: Ideally, we should also get the isec->sid for the
4170 new socket in sync, but we don't have the isec available yet.
4171 So we will wait until sock_graft to do it, by which
4172 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004173
Paul Moore9f2ad662006-11-17 17:38:53 -05004174 /* We don't need to take any sort of lock here as we are the only
4175 * thread with access to newsksec */
4176 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004177}
4178
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004179static void selinux_inet_conn_established(struct sock *sk,
4180 struct sk_buff *skb)
4181{
4182 struct sk_security_struct *sksec = sk->sk_security;
4183
Paul Moore220deb92008-01-29 08:38:23 -05004184 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004185}
4186
Adrian Bunk9a673e52006-08-15 00:03:53 -07004187static void selinux_req_classify_flow(const struct request_sock *req,
4188 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004189{
4190 fl->secid = req->secid;
4191}
4192
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4194{
4195 int err = 0;
4196 u32 perm;
4197 struct nlmsghdr *nlh;
4198 struct socket *sock = sk->sk_socket;
4199 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4200
4201 if (skb->len < NLMSG_SPACE(0)) {
4202 err = -EINVAL;
4203 goto out;
4204 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004205 nlh = nlmsg_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
4207 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4208 if (err) {
4209 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004210 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 "SELinux: unrecognized netlink message"
4212 " type=%hu for sclass=%hu\n",
4213 nlh->nlmsg_type, isec->sclass);
4214 if (!selinux_enforcing)
4215 err = 0;
4216 }
4217
4218 /* Ignore */
4219 if (err == -ENOENT)
4220 err = 0;
4221 goto out;
4222 }
4223
4224 err = socket_has_perm(current, sock, perm);
4225out:
4226 return err;
4227}
4228
4229#ifdef CONFIG_NETFILTER
4230
Paul Mooreeffad8d2008-01-29 08:49:27 -05004231static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4232 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004234 char *addrp;
4235 u32 peer_sid;
4236 struct avc_audit_data ad;
4237 u8 secmark_active;
4238 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004239
Paul Mooreeffad8d2008-01-29 08:49:27 -05004240 if (!selinux_policycap_netpeer)
4241 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004242
Paul Mooreeffad8d2008-01-29 08:49:27 -05004243 secmark_active = selinux_secmark_enabled();
4244 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4245 if (!secmark_active && !peerlbl_active)
4246 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004247
Paul Mooreeffad8d2008-01-29 08:49:27 -05004248 AVC_AUDIT_DATA_INIT(&ad, NET);
4249 ad.u.net.netif = ifindex;
4250 ad.u.net.family = family;
4251 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4252 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Paul Mooreeffad8d2008-01-29 08:49:27 -05004254 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4255 return NF_DROP;
4256
4257 if (peerlbl_active)
4258 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4259 peer_sid, &ad) != 0)
4260 return NF_DROP;
4261
4262 if (secmark_active)
4263 if (avc_has_perm(peer_sid, skb->secmark,
4264 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4265 return NF_DROP;
4266
4267 return NF_ACCEPT;
4268}
4269
4270static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4271 struct sk_buff *skb,
4272 const struct net_device *in,
4273 const struct net_device *out,
4274 int (*okfn)(struct sk_buff *))
4275{
4276 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4277}
4278
4279#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4280static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4281 struct sk_buff *skb,
4282 const struct net_device *in,
4283 const struct net_device *out,
4284 int (*okfn)(struct sk_buff *))
4285{
4286 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4287}
4288#endif /* IPV6 */
4289
4290static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4291 int ifindex,
4292 struct avc_audit_data *ad,
4293 u16 family, char *addrp)
4294{
4295 int err;
4296 struct sk_security_struct *sksec = sk->sk_security;
4297 u16 sk_class;
4298 u32 netif_perm, node_perm, send_perm;
4299 u32 port_sid, node_sid, if_sid, sk_sid;
4300
4301 sk_sid = sksec->sid;
4302 sk_class = sksec->sclass;
4303
4304 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 case SECCLASS_UDP_SOCKET:
4306 netif_perm = NETIF__UDP_SEND;
4307 node_perm = NODE__UDP_SEND;
4308 send_perm = UDP_SOCKET__SEND_MSG;
4309 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 case SECCLASS_TCP_SOCKET:
4311 netif_perm = NETIF__TCP_SEND;
4312 node_perm = NODE__TCP_SEND;
4313 send_perm = TCP_SOCKET__SEND_MSG;
4314 break;
James Morris2ee92d42006-11-13 16:09:01 -08004315 case SECCLASS_DCCP_SOCKET:
4316 netif_perm = NETIF__DCCP_SEND;
4317 node_perm = NODE__DCCP_SEND;
4318 send_perm = DCCP_SOCKET__SEND_MSG;
4319 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320 default:
4321 netif_perm = NETIF__RAWIP_SEND;
4322 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004323 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 break;
4325 }
4326
Paul Mooreeffad8d2008-01-29 08:49:27 -05004327 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004328 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004329 return err;
4330 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4331 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Paul Moore224dfbd2008-01-29 08:38:13 -05004333 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004334 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004335 return err;
4336 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004337 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004338 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
Paul Mooreeffad8d2008-01-29 08:49:27 -05004340 if (send_perm != 0)
4341 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Paul Mooreeffad8d2008-01-29 08:49:27 -05004343 err = security_port_sid(sk->sk_family, sk->sk_type,
4344 sk->sk_protocol, ntohs(ad->u.net.dport),
4345 &port_sid);
4346 if (err)
4347 return err;
4348 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004349}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Paul Mooreeffad8d2008-01-29 08:49:27 -05004351static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4352 int ifindex,
4353 struct avc_audit_data *ad,
4354 u16 family,
4355 char *addrp,
4356 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004357{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004358 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004359 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004360
Paul Mooreeffad8d2008-01-29 08:49:27 -05004361 if (sk == NULL)
4362 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004363 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004364
Paul Mooreeffad8d2008-01-29 08:49:27 -05004365 if (selinux_compat_net) {
4366 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4367 ad, family, addrp))
4368 return NF_DROP;
4369 } else {
4370 if (avc_has_perm(sksec->sid, skb->secmark,
4371 SECCLASS_PACKET, PACKET__SEND, ad))
4372 return NF_DROP;
4373 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004374
Paul Mooreeffad8d2008-01-29 08:49:27 -05004375 if (selinux_policycap_netpeer)
4376 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4377 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004378
Paul Mooreeffad8d2008-01-29 08:49:27 -05004379 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380}
4381
Paul Mooreeffad8d2008-01-29 08:49:27 -05004382static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4383 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004385 u32 secmark_perm;
4386 u32 peer_sid;
4387 struct sock *sk;
4388 struct avc_audit_data ad;
4389 char *addrp;
4390 u8 proto;
4391 u8 secmark_active;
4392 u8 peerlbl_active;
4393
4394 AVC_AUDIT_DATA_INIT(&ad, NET);
4395 ad.u.net.netif = ifindex;
4396 ad.u.net.family = family;
4397 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4398 return NF_DROP;
4399
4400 /* If any sort of compatibility mode is enabled then handoff processing
4401 * to the selinux_ip_postroute_compat() function to deal with the
4402 * special handling. We do this in an attempt to keep this function
4403 * as fast and as clean as possible. */
4404 if (selinux_compat_net || !selinux_policycap_netpeer)
4405 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4406 family, addrp, proto);
4407
4408 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4409 * packet transformation so allow the packet to pass without any checks
4410 * since we'll have another chance to perform access control checks
4411 * when the packet is on it's final way out.
4412 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4413 * is NULL, in this case go ahead and apply access control. */
4414 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4415 return NF_ACCEPT;
4416
4417 secmark_active = selinux_secmark_enabled();
4418 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4419 if (!secmark_active && !peerlbl_active)
4420 return NF_ACCEPT;
4421
4422 /* if the packet is locally generated (skb->sk != NULL) then use the
4423 * socket's label as the peer label, otherwise the packet is being
4424 * forwarded through this system and we need to fetch the peer label
4425 * directly from the packet */
4426 sk = skb->sk;
4427 if (sk) {
4428 struct sk_security_struct *sksec = sk->sk_security;
4429 peer_sid = sksec->sid;
4430 secmark_perm = PACKET__SEND;
4431 } else {
4432 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4433 return NF_DROP;
4434 secmark_perm = PACKET__FORWARD_OUT;
4435 }
4436
4437 if (secmark_active)
4438 if (avc_has_perm(peer_sid, skb->secmark,
4439 SECCLASS_PACKET, secmark_perm, &ad))
4440 return NF_DROP;
4441
4442 if (peerlbl_active) {
4443 u32 if_sid;
4444 u32 node_sid;
4445
4446 if (sel_netif_sid(ifindex, &if_sid))
4447 return NF_DROP;
4448 if (avc_has_perm(peer_sid, if_sid,
4449 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4450 return NF_DROP;
4451
4452 if (sel_netnode_sid(addrp, family, &node_sid))
4453 return NF_DROP;
4454 if (avc_has_perm(peer_sid, node_sid,
4455 SECCLASS_NODE, NODE__SENDTO, &ad))
4456 return NF_DROP;
4457 }
4458
4459 return NF_ACCEPT;
4460}
4461
4462static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4463 struct sk_buff *skb,
4464 const struct net_device *in,
4465 const struct net_device *out,
4466 int (*okfn)(struct sk_buff *))
4467{
4468 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469}
4470
4471#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004472static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4473 struct sk_buff *skb,
4474 const struct net_device *in,
4475 const struct net_device *out,
4476 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004478 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480#endif /* IPV6 */
4481
4482#endif /* CONFIG_NETFILTER */
4483
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4485{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 int err;
4487
4488 err = secondary_ops->netlink_send(sk, skb);
4489 if (err)
4490 return err;
4491
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4493 err = selinux_nlmsg_perm(sk, skb);
4494
4495 return err;
4496}
4497
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004498static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004500 int err;
4501 struct avc_audit_data ad;
4502
4503 err = secondary_ops->netlink_recv(skb, capability);
4504 if (err)
4505 return err;
4506
4507 AVC_AUDIT_DATA_INIT(&ad, CAP);
4508 ad.u.cap = capability;
4509
4510 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
4511 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512}
4513
4514static int ipc_alloc_security(struct task_struct *task,
4515 struct kern_ipc_perm *perm,
4516 u16 sclass)
4517{
4518 struct task_security_struct *tsec = task->security;
4519 struct ipc_security_struct *isec;
4520
James Morris89d155e2005-10-30 14:59:21 -08004521 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522 if (!isec)
4523 return -ENOMEM;
4524
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 isec->sclass = sclass;
4526 isec->ipc_perm = perm;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004527 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 perm->security = isec;
4529
4530 return 0;
4531}
4532
4533static void ipc_free_security(struct kern_ipc_perm *perm)
4534{
4535 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536 perm->security = NULL;
4537 kfree(isec);
4538}
4539
4540static int msg_msg_alloc_security(struct msg_msg *msg)
4541{
4542 struct msg_security_struct *msec;
4543
James Morris89d155e2005-10-30 14:59:21 -08004544 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 if (!msec)
4546 return -ENOMEM;
4547
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 msec->msg = msg;
4549 msec->sid = SECINITSID_UNLABELED;
4550 msg->security = msec;
4551
4552 return 0;
4553}
4554
4555static void msg_msg_free_security(struct msg_msg *msg)
4556{
4557 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558
4559 msg->security = NULL;
4560 kfree(msec);
4561}
4562
4563static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004564 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565{
4566 struct task_security_struct *tsec;
4567 struct ipc_security_struct *isec;
4568 struct avc_audit_data ad;
4569
4570 tsec = current->security;
4571 isec = ipc_perms->security;
4572
4573 AVC_AUDIT_DATA_INIT(&ad, IPC);
4574 ad.u.ipc_id = ipc_perms->key;
4575
Stephen Smalley6af963f2005-05-01 08:58:39 -07004576 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577}
4578
4579static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4580{
4581 return msg_msg_alloc_security(msg);
4582}
4583
4584static void selinux_msg_msg_free_security(struct msg_msg *msg)
4585{
4586 msg_msg_free_security(msg);
4587}
4588
4589/* message queue security operations */
4590static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4591{
4592 struct task_security_struct *tsec;
4593 struct ipc_security_struct *isec;
4594 struct avc_audit_data ad;
4595 int rc;
4596
4597 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4598 if (rc)
4599 return rc;
4600
4601 tsec = current->security;
4602 isec = msq->q_perm.security;
4603
4604 AVC_AUDIT_DATA_INIT(&ad, IPC);
4605 ad.u.ipc_id = msq->q_perm.key;
4606
4607 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4608 MSGQ__CREATE, &ad);
4609 if (rc) {
4610 ipc_free_security(&msq->q_perm);
4611 return rc;
4612 }
4613 return 0;
4614}
4615
4616static void selinux_msg_queue_free_security(struct msg_queue *msq)
4617{
4618 ipc_free_security(&msq->q_perm);
4619}
4620
4621static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4622{
4623 struct task_security_struct *tsec;
4624 struct ipc_security_struct *isec;
4625 struct avc_audit_data ad;
4626
4627 tsec = current->security;
4628 isec = msq->q_perm.security;
4629
4630 AVC_AUDIT_DATA_INIT(&ad, IPC);
4631 ad.u.ipc_id = msq->q_perm.key;
4632
4633 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4634 MSGQ__ASSOCIATE, &ad);
4635}
4636
4637static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4638{
4639 int err;
4640 int perms;
4641
4642 switch(cmd) {
4643 case IPC_INFO:
4644 case MSG_INFO:
4645 /* No specific object, just general system-wide information. */
4646 return task_has_system(current, SYSTEM__IPC_INFO);
4647 case IPC_STAT:
4648 case MSG_STAT:
4649 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4650 break;
4651 case IPC_SET:
4652 perms = MSGQ__SETATTR;
4653 break;
4654 case IPC_RMID:
4655 perms = MSGQ__DESTROY;
4656 break;
4657 default:
4658 return 0;
4659 }
4660
Stephen Smalley6af963f2005-05-01 08:58:39 -07004661 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 return err;
4663}
4664
4665static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4666{
4667 struct task_security_struct *tsec;
4668 struct ipc_security_struct *isec;
4669 struct msg_security_struct *msec;
4670 struct avc_audit_data ad;
4671 int rc;
4672
4673 tsec = current->security;
4674 isec = msq->q_perm.security;
4675 msec = msg->security;
4676
4677 /*
4678 * First time through, need to assign label to the message
4679 */
4680 if (msec->sid == SECINITSID_UNLABELED) {
4681 /*
4682 * Compute new sid based on current process and
4683 * message queue this message will be stored in
4684 */
4685 rc = security_transition_sid(tsec->sid,
4686 isec->sid,
4687 SECCLASS_MSG,
4688 &msec->sid);
4689 if (rc)
4690 return rc;
4691 }
4692
4693 AVC_AUDIT_DATA_INIT(&ad, IPC);
4694 ad.u.ipc_id = msq->q_perm.key;
4695
4696 /* Can this process write to the queue? */
4697 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4698 MSGQ__WRITE, &ad);
4699 if (!rc)
4700 /* Can this process send the message */
4701 rc = avc_has_perm(tsec->sid, msec->sid,
4702 SECCLASS_MSG, MSG__SEND, &ad);
4703 if (!rc)
4704 /* Can the message be put in the queue? */
4705 rc = avc_has_perm(msec->sid, isec->sid,
4706 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4707
4708 return rc;
4709}
4710
4711static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4712 struct task_struct *target,
4713 long type, int mode)
4714{
4715 struct task_security_struct *tsec;
4716 struct ipc_security_struct *isec;
4717 struct msg_security_struct *msec;
4718 struct avc_audit_data ad;
4719 int rc;
4720
4721 tsec = target->security;
4722 isec = msq->q_perm.security;
4723 msec = msg->security;
4724
4725 AVC_AUDIT_DATA_INIT(&ad, IPC);
4726 ad.u.ipc_id = msq->q_perm.key;
4727
4728 rc = avc_has_perm(tsec->sid, isec->sid,
4729 SECCLASS_MSGQ, MSGQ__READ, &ad);
4730 if (!rc)
4731 rc = avc_has_perm(tsec->sid, msec->sid,
4732 SECCLASS_MSG, MSG__RECEIVE, &ad);
4733 return rc;
4734}
4735
4736/* Shared Memory security operations */
4737static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4738{
4739 struct task_security_struct *tsec;
4740 struct ipc_security_struct *isec;
4741 struct avc_audit_data ad;
4742 int rc;
4743
4744 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4745 if (rc)
4746 return rc;
4747
4748 tsec = current->security;
4749 isec = shp->shm_perm.security;
4750
4751 AVC_AUDIT_DATA_INIT(&ad, IPC);
4752 ad.u.ipc_id = shp->shm_perm.key;
4753
4754 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4755 SHM__CREATE, &ad);
4756 if (rc) {
4757 ipc_free_security(&shp->shm_perm);
4758 return rc;
4759 }
4760 return 0;
4761}
4762
4763static void selinux_shm_free_security(struct shmid_kernel *shp)
4764{
4765 ipc_free_security(&shp->shm_perm);
4766}
4767
4768static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4769{
4770 struct task_security_struct *tsec;
4771 struct ipc_security_struct *isec;
4772 struct avc_audit_data ad;
4773
4774 tsec = current->security;
4775 isec = shp->shm_perm.security;
4776
4777 AVC_AUDIT_DATA_INIT(&ad, IPC);
4778 ad.u.ipc_id = shp->shm_perm.key;
4779
4780 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4781 SHM__ASSOCIATE, &ad);
4782}
4783
4784/* Note, at this point, shp is locked down */
4785static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4786{
4787 int perms;
4788 int err;
4789
4790 switch(cmd) {
4791 case IPC_INFO:
4792 case SHM_INFO:
4793 /* No specific object, just general system-wide information. */
4794 return task_has_system(current, SYSTEM__IPC_INFO);
4795 case IPC_STAT:
4796 case SHM_STAT:
4797 perms = SHM__GETATTR | SHM__ASSOCIATE;
4798 break;
4799 case IPC_SET:
4800 perms = SHM__SETATTR;
4801 break;
4802 case SHM_LOCK:
4803 case SHM_UNLOCK:
4804 perms = SHM__LOCK;
4805 break;
4806 case IPC_RMID:
4807 perms = SHM__DESTROY;
4808 break;
4809 default:
4810 return 0;
4811 }
4812
Stephen Smalley6af963f2005-05-01 08:58:39 -07004813 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814 return err;
4815}
4816
4817static int selinux_shm_shmat(struct shmid_kernel *shp,
4818 char __user *shmaddr, int shmflg)
4819{
4820 u32 perms;
4821 int rc;
4822
4823 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4824 if (rc)
4825 return rc;
4826
4827 if (shmflg & SHM_RDONLY)
4828 perms = SHM__READ;
4829 else
4830 perms = SHM__READ | SHM__WRITE;
4831
Stephen Smalley6af963f2005-05-01 08:58:39 -07004832 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833}
4834
4835/* Semaphore security operations */
4836static int selinux_sem_alloc_security(struct sem_array *sma)
4837{
4838 struct task_security_struct *tsec;
4839 struct ipc_security_struct *isec;
4840 struct avc_audit_data ad;
4841 int rc;
4842
4843 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4844 if (rc)
4845 return rc;
4846
4847 tsec = current->security;
4848 isec = sma->sem_perm.security;
4849
4850 AVC_AUDIT_DATA_INIT(&ad, IPC);
4851 ad.u.ipc_id = sma->sem_perm.key;
4852
4853 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4854 SEM__CREATE, &ad);
4855 if (rc) {
4856 ipc_free_security(&sma->sem_perm);
4857 return rc;
4858 }
4859 return 0;
4860}
4861
4862static void selinux_sem_free_security(struct sem_array *sma)
4863{
4864 ipc_free_security(&sma->sem_perm);
4865}
4866
4867static int selinux_sem_associate(struct sem_array *sma, int semflg)
4868{
4869 struct task_security_struct *tsec;
4870 struct ipc_security_struct *isec;
4871 struct avc_audit_data ad;
4872
4873 tsec = current->security;
4874 isec = sma->sem_perm.security;
4875
4876 AVC_AUDIT_DATA_INIT(&ad, IPC);
4877 ad.u.ipc_id = sma->sem_perm.key;
4878
4879 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4880 SEM__ASSOCIATE, &ad);
4881}
4882
4883/* Note, at this point, sma is locked down */
4884static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4885{
4886 int err;
4887 u32 perms;
4888
4889 switch(cmd) {
4890 case IPC_INFO:
4891 case SEM_INFO:
4892 /* No specific object, just general system-wide information. */
4893 return task_has_system(current, SYSTEM__IPC_INFO);
4894 case GETPID:
4895 case GETNCNT:
4896 case GETZCNT:
4897 perms = SEM__GETATTR;
4898 break;
4899 case GETVAL:
4900 case GETALL:
4901 perms = SEM__READ;
4902 break;
4903 case SETVAL:
4904 case SETALL:
4905 perms = SEM__WRITE;
4906 break;
4907 case IPC_RMID:
4908 perms = SEM__DESTROY;
4909 break;
4910 case IPC_SET:
4911 perms = SEM__SETATTR;
4912 break;
4913 case IPC_STAT:
4914 case SEM_STAT:
4915 perms = SEM__GETATTR | SEM__ASSOCIATE;
4916 break;
4917 default:
4918 return 0;
4919 }
4920
Stephen Smalley6af963f2005-05-01 08:58:39 -07004921 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922 return err;
4923}
4924
4925static int selinux_sem_semop(struct sem_array *sma,
4926 struct sembuf *sops, unsigned nsops, int alter)
4927{
4928 u32 perms;
4929
4930 if (alter)
4931 perms = SEM__READ | SEM__WRITE;
4932 else
4933 perms = SEM__READ;
4934
Stephen Smalley6af963f2005-05-01 08:58:39 -07004935 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936}
4937
4938static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4939{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940 u32 av = 0;
4941
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942 av = 0;
4943 if (flag & S_IRUGO)
4944 av |= IPC__UNIX_READ;
4945 if (flag & S_IWUGO)
4946 av |= IPC__UNIX_WRITE;
4947
4948 if (av == 0)
4949 return 0;
4950
Stephen Smalley6af963f2005-05-01 08:58:39 -07004951 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952}
4953
4954/* module stacking operations */
4955static int selinux_register_security (const char *name, struct security_operations *ops)
4956{
4957 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05004958 printk(KERN_ERR "%s: There is already a secondary security "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 "module registered.\n", __FUNCTION__);
4960 return -EINVAL;
4961 }
4962
4963 secondary_ops = ops;
4964
4965 printk(KERN_INFO "%s: Registering secondary module %s\n",
4966 __FUNCTION__,
4967 name);
4968
4969 return 0;
4970}
4971
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
4973{
4974 if (inode)
4975 inode_doinit_with_dentry(inode, dentry);
4976}
4977
4978static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00004979 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980{
4981 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00004982 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 int error;
Al Viro04ff9702007-03-12 16:17:58 +00004984 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985
4986 if (current != p) {
4987 error = task_has_perm(current, p, PROCESS__GETATTR);
4988 if (error)
4989 return error;
4990 }
4991
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992 tsec = p->security;
4993
4994 if (!strcmp(name, "current"))
4995 sid = tsec->sid;
4996 else if (!strcmp(name, "prev"))
4997 sid = tsec->osid;
4998 else if (!strcmp(name, "exec"))
4999 sid = tsec->exec_sid;
5000 else if (!strcmp(name, "fscreate"))
5001 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005002 else if (!strcmp(name, "keycreate"))
5003 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005004 else if (!strcmp(name, "sockcreate"))
5005 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006 else
5007 return -EINVAL;
5008
5009 if (!sid)
5010 return 0;
5011
Al Viro04ff9702007-03-12 16:17:58 +00005012 error = security_sid_to_context(sid, value, &len);
5013 if (error)
5014 return error;
5015 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016}
5017
5018static int selinux_setprocattr(struct task_struct *p,
5019 char *name, void *value, size_t size)
5020{
5021 struct task_security_struct *tsec;
5022 u32 sid = 0;
5023 int error;
5024 char *str = value;
5025
5026 if (current != p) {
5027 /* SELinux only allows a process to change its own
5028 security attributes. */
5029 return -EACCES;
5030 }
5031
5032 /*
5033 * Basic control over ability to set these attributes at all.
5034 * current == p, but we'll pass them separately in case the
5035 * above restriction is ever removed.
5036 */
5037 if (!strcmp(name, "exec"))
5038 error = task_has_perm(current, p, PROCESS__SETEXEC);
5039 else if (!strcmp(name, "fscreate"))
5040 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005041 else if (!strcmp(name, "keycreate"))
5042 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005043 else if (!strcmp(name, "sockcreate"))
5044 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 else if (!strcmp(name, "current"))
5046 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5047 else
5048 error = -EINVAL;
5049 if (error)
5050 return error;
5051
5052 /* Obtain a SID for the context, if one was specified. */
5053 if (size && str[1] && str[1] != '\n') {
5054 if (str[size-1] == '\n') {
5055 str[size-1] = 0;
5056 size--;
5057 }
5058 error = security_context_to_sid(value, size, &sid);
5059 if (error)
5060 return error;
5061 }
5062
5063 /* Permission checking based on the specified context is
5064 performed during the actual operation (execve,
5065 open/mkdir/...), when we know the full context of the
5066 operation. See selinux_bprm_set_security for the execve
5067 checks and may_create for the file creation checks. The
5068 operation will then fail if the context is not permitted. */
5069 tsec = p->security;
5070 if (!strcmp(name, "exec"))
5071 tsec->exec_sid = sid;
5072 else if (!strcmp(name, "fscreate"))
5073 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005074 else if (!strcmp(name, "keycreate")) {
5075 error = may_create_key(sid, p);
5076 if (error)
5077 return error;
5078 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005079 } else if (!strcmp(name, "sockcreate"))
5080 tsec->sockcreate_sid = sid;
5081 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 struct av_decision avd;
5083
5084 if (sid == 0)
5085 return -EINVAL;
5086
5087 /* Only allow single threaded processes to change context */
5088 if (atomic_read(&p->mm->mm_users) != 1) {
5089 struct task_struct *g, *t;
5090 struct mm_struct *mm = p->mm;
5091 read_lock(&tasklist_lock);
5092 do_each_thread(g, t)
5093 if (t->mm == mm && t != p) {
5094 read_unlock(&tasklist_lock);
5095 return -EPERM;
5096 }
5097 while_each_thread(g, t);
5098 read_unlock(&tasklist_lock);
5099 }
5100
5101 /* Check permissions for the transition. */
5102 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
5103 PROCESS__DYNTRANSITION, NULL);
5104 if (error)
5105 return error;
5106
5107 /* Check for ptracing, and update the task SID if ok.
5108 Otherwise, leave SID unchanged and fail. */
5109 task_lock(p);
5110 if (p->ptrace & PT_PTRACED) {
5111 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
5112 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005113 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114 if (!error)
5115 tsec->sid = sid;
5116 task_unlock(p);
5117 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
5118 PROCESS__PTRACE, &avd, error, NULL);
5119 if (error)
5120 return error;
5121 } else {
5122 tsec->sid = sid;
5123 task_unlock(p);
5124 }
5125 }
5126 else
5127 return -EINVAL;
5128
5129 return size;
5130}
5131
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005132static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5133{
5134 return security_sid_to_context(secid, secdata, seclen);
5135}
5136
David Howells63cb3442008-01-15 23:47:35 +00005137static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
5138{
5139 return security_context_to_sid(secdata, seclen, secid);
5140}
5141
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005142static void selinux_release_secctx(char *secdata, u32 seclen)
5143{
Paul Moore088999e2007-08-01 11:12:58 -04005144 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005145}
5146
Michael LeMayd7200242006-06-22 14:47:17 -07005147#ifdef CONFIG_KEYS
5148
David Howells7e047ef2006-06-26 00:24:50 -07005149static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5150 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005151{
5152 struct task_security_struct *tsec = tsk->security;
5153 struct key_security_struct *ksec;
5154
5155 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5156 if (!ksec)
5157 return -ENOMEM;
5158
5159 ksec->obj = k;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005160 if (tsec->keycreate_sid)
5161 ksec->sid = tsec->keycreate_sid;
5162 else
5163 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005164 k->security = ksec;
5165
5166 return 0;
5167}
5168
5169static void selinux_key_free(struct key *k)
5170{
5171 struct key_security_struct *ksec = k->security;
5172
5173 k->security = NULL;
5174 kfree(ksec);
5175}
5176
5177static int selinux_key_permission(key_ref_t key_ref,
5178 struct task_struct *ctx,
5179 key_perm_t perm)
5180{
5181 struct key *key;
5182 struct task_security_struct *tsec;
5183 struct key_security_struct *ksec;
5184
5185 key = key_ref_to_ptr(key_ref);
5186
5187 tsec = ctx->security;
5188 ksec = key->security;
5189
5190 /* if no specific permissions are requested, we skip the
5191 permission check. No serious, additional covert channels
5192 appear to be created. */
5193 if (perm == 0)
5194 return 0;
5195
5196 return avc_has_perm(tsec->sid, ksec->sid,
5197 SECCLASS_KEY, perm, NULL);
5198}
5199
5200#endif
5201
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202static struct security_operations selinux_ops = {
5203 .ptrace = selinux_ptrace,
5204 .capget = selinux_capget,
5205 .capset_check = selinux_capset_check,
5206 .capset_set = selinux_capset_set,
5207 .sysctl = selinux_sysctl,
5208 .capable = selinux_capable,
5209 .quotactl = selinux_quotactl,
5210 .quota_on = selinux_quota_on,
5211 .syslog = selinux_syslog,
5212 .vm_enough_memory = selinux_vm_enough_memory,
5213
5214 .netlink_send = selinux_netlink_send,
5215 .netlink_recv = selinux_netlink_recv,
5216
5217 .bprm_alloc_security = selinux_bprm_alloc_security,
5218 .bprm_free_security = selinux_bprm_free_security,
5219 .bprm_apply_creds = selinux_bprm_apply_creds,
5220 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5221 .bprm_set_security = selinux_bprm_set_security,
5222 .bprm_check_security = selinux_bprm_check_security,
5223 .bprm_secureexec = selinux_bprm_secureexec,
5224
5225 .sb_alloc_security = selinux_sb_alloc_security,
5226 .sb_free_security = selinux_sb_free_security,
5227 .sb_copy_data = selinux_sb_copy_data,
5228 .sb_kern_mount = selinux_sb_kern_mount,
5229 .sb_statfs = selinux_sb_statfs,
5230 .sb_mount = selinux_mount,
5231 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005232 .sb_get_mnt_opts = selinux_get_mnt_opts,
5233 .sb_set_mnt_opts = selinux_set_mnt_opts,
5234 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
5236 .inode_alloc_security = selinux_inode_alloc_security,
5237 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005238 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 .inode_unlink = selinux_inode_unlink,
5242 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005243 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 .inode_rmdir = selinux_inode_rmdir,
5245 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247 .inode_readlink = selinux_inode_readlink,
5248 .inode_follow_link = selinux_inode_follow_link,
5249 .inode_permission = selinux_inode_permission,
5250 .inode_setattr = selinux_inode_setattr,
5251 .inode_getattr = selinux_inode_getattr,
5252 .inode_setxattr = selinux_inode_setxattr,
5253 .inode_post_setxattr = selinux_inode_post_setxattr,
5254 .inode_getxattr = selinux_inode_getxattr,
5255 .inode_listxattr = selinux_inode_listxattr,
5256 .inode_removexattr = selinux_inode_removexattr,
5257 .inode_getsecurity = selinux_inode_getsecurity,
5258 .inode_setsecurity = selinux_inode_setsecurity,
5259 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005260 .inode_need_killpriv = selinux_inode_need_killpriv,
5261 .inode_killpriv = selinux_inode_killpriv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262
5263 .file_permission = selinux_file_permission,
5264 .file_alloc_security = selinux_file_alloc_security,
5265 .file_free_security = selinux_file_free_security,
5266 .file_ioctl = selinux_file_ioctl,
5267 .file_mmap = selinux_file_mmap,
5268 .file_mprotect = selinux_file_mprotect,
5269 .file_lock = selinux_file_lock,
5270 .file_fcntl = selinux_file_fcntl,
5271 .file_set_fowner = selinux_file_set_fowner,
5272 .file_send_sigiotask = selinux_file_send_sigiotask,
5273 .file_receive = selinux_file_receive,
5274
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005275 .dentry_open = selinux_dentry_open,
5276
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 .task_create = selinux_task_create,
5278 .task_alloc_security = selinux_task_alloc_security,
5279 .task_free_security = selinux_task_free_security,
5280 .task_setuid = selinux_task_setuid,
5281 .task_post_setuid = selinux_task_post_setuid,
5282 .task_setgid = selinux_task_setgid,
5283 .task_setpgid = selinux_task_setpgid,
5284 .task_getpgid = selinux_task_getpgid,
5285 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005286 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287 .task_setgroups = selinux_task_setgroups,
5288 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005289 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005290 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 .task_setrlimit = selinux_task_setrlimit,
5292 .task_setscheduler = selinux_task_setscheduler,
5293 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005294 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295 .task_kill = selinux_task_kill,
5296 .task_wait = selinux_task_wait,
5297 .task_prctl = selinux_task_prctl,
5298 .task_reparent_to_init = selinux_task_reparent_to_init,
5299 .task_to_inode = selinux_task_to_inode,
5300
5301 .ipc_permission = selinux_ipc_permission,
5302
5303 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5304 .msg_msg_free_security = selinux_msg_msg_free_security,
5305
5306 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5307 .msg_queue_free_security = selinux_msg_queue_free_security,
5308 .msg_queue_associate = selinux_msg_queue_associate,
5309 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5310 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5311 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5312
5313 .shm_alloc_security = selinux_shm_alloc_security,
5314 .shm_free_security = selinux_shm_free_security,
5315 .shm_associate = selinux_shm_associate,
5316 .shm_shmctl = selinux_shm_shmctl,
5317 .shm_shmat = selinux_shm_shmat,
5318
5319 .sem_alloc_security = selinux_sem_alloc_security,
5320 .sem_free_security = selinux_sem_free_security,
5321 .sem_associate = selinux_sem_associate,
5322 .sem_semctl = selinux_sem_semctl,
5323 .sem_semop = selinux_sem_semop,
5324
5325 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326
5327 .d_instantiate = selinux_d_instantiate,
5328
5329 .getprocattr = selinux_getprocattr,
5330 .setprocattr = selinux_setprocattr,
5331
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005332 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005333 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005334 .release_secctx = selinux_release_secctx,
5335
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 .unix_stream_connect = selinux_socket_unix_stream_connect,
5337 .unix_may_send = selinux_socket_unix_may_send,
5338
5339 .socket_create = selinux_socket_create,
5340 .socket_post_create = selinux_socket_post_create,
5341 .socket_bind = selinux_socket_bind,
5342 .socket_connect = selinux_socket_connect,
5343 .socket_listen = selinux_socket_listen,
5344 .socket_accept = selinux_socket_accept,
5345 .socket_sendmsg = selinux_socket_sendmsg,
5346 .socket_recvmsg = selinux_socket_recvmsg,
5347 .socket_getsockname = selinux_socket_getsockname,
5348 .socket_getpeername = selinux_socket_getpeername,
5349 .socket_getsockopt = selinux_socket_getsockopt,
5350 .socket_setsockopt = selinux_socket_setsockopt,
5351 .socket_shutdown = selinux_socket_shutdown,
5352 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005353 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5354 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355 .sk_alloc_security = selinux_sk_alloc_security,
5356 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005357 .sk_clone_security = selinux_sk_clone_security,
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005358 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005359 .sock_graft = selinux_sock_graft,
5360 .inet_conn_request = selinux_inet_conn_request,
5361 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005362 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005363 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005364
5365#ifdef CONFIG_SECURITY_NETWORK_XFRM
5366 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5367 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5368 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005369 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005370 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5371 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005372 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005373 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005374 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005375 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005377
5378#ifdef CONFIG_KEYS
5379 .key_alloc = selinux_key_alloc,
5380 .key_free = selinux_key_free,
5381 .key_permission = selinux_key_permission,
5382#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383};
5384
5385static __init int selinux_init(void)
5386{
5387 struct task_security_struct *tsec;
5388
5389 if (!selinux_enabled) {
5390 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5391 return 0;
5392 }
5393
5394 printk(KERN_INFO "SELinux: Initializing.\n");
5395
5396 /* Set the security state for the initial task. */
5397 if (task_alloc_security(current))
5398 panic("SELinux: Failed to initialize initial task.\n");
5399 tsec = current->security;
5400 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5401
James Morris7cae7e22006-03-22 00:09:22 -08005402 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5403 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005404 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405 avc_init();
5406
5407 original_ops = secondary_ops = security_ops;
5408 if (!secondary_ops)
5409 panic ("SELinux: No initial security operations\n");
5410 if (register_security (&selinux_ops))
5411 panic("SELinux: Unable to register with kernel.\n");
5412
5413 if (selinux_enforcing) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005414 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415 } else {
Eric Parisfadcdb42007-02-22 18:11:31 -05005416 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 }
Michael LeMayd7200242006-06-22 14:47:17 -07005418
5419#ifdef CONFIG_KEYS
5420 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005421 selinux_key_alloc(&root_user_keyring, current,
5422 KEY_ALLOC_NOT_IN_QUOTA);
5423 selinux_key_alloc(&root_session_keyring, current,
5424 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005425#endif
5426
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 return 0;
5428}
5429
5430void selinux_complete_init(void)
5431{
Eric Parisfadcdb42007-02-22 18:11:31 -05005432 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005433
5434 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005435 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005436 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437 spin_lock(&sb_security_lock);
5438next_sb:
5439 if (!list_empty(&superblock_security_head)) {
5440 struct superblock_security_struct *sbsec =
5441 list_entry(superblock_security_head.next,
5442 struct superblock_security_struct,
5443 list);
5444 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005447 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448 down_read(&sb->s_umount);
5449 if (sb->s_root)
5450 superblock_doinit(sb, NULL);
5451 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005452 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005453 spin_lock(&sb_security_lock);
5454 list_del_init(&sbsec->list);
5455 goto next_sb;
5456 }
5457 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005458 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459}
5460
5461/* SELinux requires early initialization in order to label
5462 all processes and objects when they are created. */
5463security_initcall(selinux_init);
5464
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005465#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Paul Mooreeffad8d2008-01-29 08:49:27 -05005467static struct nf_hook_ops selinux_ipv4_ops[] = {
5468 {
5469 .hook = selinux_ipv4_postroute,
5470 .owner = THIS_MODULE,
5471 .pf = PF_INET,
5472 .hooknum = NF_INET_POST_ROUTING,
5473 .priority = NF_IP_PRI_SELINUX_LAST,
5474 },
5475 {
5476 .hook = selinux_ipv4_forward,
5477 .owner = THIS_MODULE,
5478 .pf = PF_INET,
5479 .hooknum = NF_INET_FORWARD,
5480 .priority = NF_IP_PRI_SELINUX_FIRST,
5481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005482};
5483
5484#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5485
Paul Mooreeffad8d2008-01-29 08:49:27 -05005486static struct nf_hook_ops selinux_ipv6_ops[] = {
5487 {
5488 .hook = selinux_ipv6_postroute,
5489 .owner = THIS_MODULE,
5490 .pf = PF_INET6,
5491 .hooknum = NF_INET_POST_ROUTING,
5492 .priority = NF_IP6_PRI_SELINUX_LAST,
5493 },
5494 {
5495 .hook = selinux_ipv6_forward,
5496 .owner = THIS_MODULE,
5497 .pf = PF_INET6,
5498 .hooknum = NF_INET_FORWARD,
5499 .priority = NF_IP6_PRI_SELINUX_FIRST,
5500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501};
5502
5503#endif /* IPV6 */
5504
5505static int __init selinux_nf_ip_init(void)
5506{
5507 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005508 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509
5510 if (!selinux_enabled)
5511 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005512
5513 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5514
Paul Mooreeffad8d2008-01-29 08:49:27 -05005515 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5516 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5517 if (err)
5518 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5519 err);
5520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
5522#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005523 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5524 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5525 if (err)
5526 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5527 err);
5528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005530
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531out:
5532 return err;
5533}
5534
5535__initcall(selinux_nf_ip_init);
5536
5537#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5538static void selinux_nf_ip_exit(void)
5539{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005540 u32 iter;
5541
Eric Parisfadcdb42007-02-22 18:11:31 -05005542 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543
Paul Mooreeffad8d2008-01-29 08:49:27 -05005544 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5545 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005547 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5548 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549#endif /* IPV6 */
5550}
5551#endif
5552
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005553#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554
5555#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5556#define selinux_nf_ip_exit()
5557#endif
5558
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005559#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560
5561#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5562int selinux_disable(void)
5563{
5564 extern void exit_sel_fs(void);
5565 static int selinux_disabled = 0;
5566
5567 if (ss_initialized) {
5568 /* Not permitted after initial policy load. */
5569 return -EINVAL;
5570 }
5571
5572 if (selinux_disabled) {
5573 /* Only do this once. */
5574 return -EINVAL;
5575 }
5576
5577 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5578
5579 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005580 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581
5582 /* Reset security_ops to the secondary module, dummy or capability. */
5583 security_ops = secondary_ops;
5584
5585 /* Unregister netfilter hooks. */
5586 selinux_nf_ip_exit();
5587
5588 /* Unregister selinuxfs. */
5589 exit_sel_fs();
5590
5591 return 0;
5592}
5593#endif
5594
5595