blob: bfe9a05db3a2e67de8d36dee4cb2894e4d212b1d [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>
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070015 * Copyright (C) 2006 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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <asm/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <asm/ioctls.h>
56#include <linux/bitops.h>
57#include <linux/interrupt.h>
58#include <linux/netdevice.h> /* for network interface checks */
59#include <linux/netlink.h>
60#include <linux/tcp.h>
61#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080062#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#include <linux/quota.h>
64#include <linux/un.h> /* for Unix socket types */
65#include <net/af_unix.h> /* for Unix socket types */
66#include <linux/parser.h>
67#include <linux/nfs_mount.h>
68#include <net/ipv6.h>
69#include <linux/hugetlb.h>
70#include <linux/personality.h>
71#include <linux/sysctl.h>
72#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070073#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070074#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070075#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77#include "avc.h"
78#include "objsec.h"
79#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050080#include "netnode.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080081#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050082#include "netlabel.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84#define XATTR_SELINUX_SUFFIX "selinux"
85#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
86
Eric Parisc9180a52007-11-30 13:00:35 -050087#define NUM_SEL_MNT_OPTS 4
88
Linus Torvalds1da177e2005-04-16 15:20:36 -070089extern unsigned int policydb_loaded_version;
90extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
James Morris4e5ab4c2006-06-09 00:33:33 -070091extern int selinux_compat_net;
James Morris20510f22007-10-16 23:31:32 -070092extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
95int selinux_enforcing = 0;
96
97static int __init enforcing_setup(char *str)
98{
99 selinux_enforcing = simple_strtol(str,NULL,0);
100 return 1;
101}
102__setup("enforcing=", enforcing_setup);
103#endif
104
105#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
106int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
107
108static int __init selinux_enabled_setup(char *str)
109{
110 selinux_enabled = simple_strtol(str, NULL, 0);
111 return 1;
112}
113__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400114#else
115int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116#endif
117
118/* Original (dummy) security module. */
119static struct security_operations *original_ops = NULL;
120
121/* Minimal support for a secondary security module,
122 just to allow the use of the dummy or capability modules.
123 The owlsm module can alternatively be used as a secondary
124 module as long as CONFIG_OWLSM_FD is not enabled. */
125static struct security_operations *secondary_ops = NULL;
126
127/* Lists of inode and superblock security structures initialized
128 before the policy was loaded. */
129static LIST_HEAD(superblock_security_head);
130static DEFINE_SPINLOCK(sb_security_lock);
131
Christoph Lametere18b8902006-12-06 20:33:20 -0800132static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800133
Dustin Kirkland8c8570f2005-11-03 17:15:16 +0000134/* Return security context for a given sid or just the context
135 length if the buffer is null or length is 0 */
136static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
137{
138 char *context;
139 unsigned len;
140 int rc;
141
142 rc = security_sid_to_context(sid, &context, &len);
143 if (rc)
144 return rc;
145
146 if (!buffer || !size)
147 goto getsecurity_exit;
148
149 if (size < len) {
150 len = -ERANGE;
151 goto getsecurity_exit;
152 }
153 memcpy(buffer, context, len);
154
155getsecurity_exit:
156 kfree(context);
157 return len;
158}
159
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160/* Allocate and free functions for each kind of security blob. */
161
162static int task_alloc_security(struct task_struct *task)
163{
164 struct task_security_struct *tsec;
165
James Morris89d155e2005-10-30 14:59:21 -0800166 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 if (!tsec)
168 return -ENOMEM;
169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 tsec->task = task;
171 tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
172 task->security = tsec;
173
174 return 0;
175}
176
177static void task_free_security(struct task_struct *task)
178{
179 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 task->security = NULL;
181 kfree(tsec);
182}
183
184static int inode_alloc_security(struct inode *inode)
185{
186 struct task_security_struct *tsec = current->security;
187 struct inode_security_struct *isec;
188
Robert P. J. Dayc3762222007-02-10 01:45:03 -0800189 isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 if (!isec)
191 return -ENOMEM;
192
Eric Paris23970742006-09-25 23:32:01 -0700193 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 isec->inode = inode;
196 isec->sid = SECINITSID_UNLABELED;
197 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800198 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 inode->i_security = isec;
200
201 return 0;
202}
203
204static void inode_free_security(struct inode *inode)
205{
206 struct inode_security_struct *isec = inode->i_security;
207 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 spin_lock(&sbsec->isec_lock);
210 if (!list_empty(&isec->list))
211 list_del_init(&isec->list);
212 spin_unlock(&sbsec->isec_lock);
213
214 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800215 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
218static int file_alloc_security(struct file *file)
219{
220 struct task_security_struct *tsec = current->security;
221 struct file_security_struct *fsec;
222
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800223 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 if (!fsec)
225 return -ENOMEM;
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 fsec->file = file;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800228 fsec->sid = tsec->sid;
229 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 file->f_security = fsec;
231
232 return 0;
233}
234
235static void file_free_security(struct file *file)
236{
237 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 file->f_security = NULL;
239 kfree(fsec);
240}
241
242static int superblock_alloc_security(struct super_block *sb)
243{
244 struct superblock_security_struct *sbsec;
245
James Morris89d155e2005-10-30 14:59:21 -0800246 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 if (!sbsec)
248 return -ENOMEM;
249
Eric Parisbc7e9822006-09-25 23:32:02 -0700250 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 INIT_LIST_HEAD(&sbsec->list);
252 INIT_LIST_HEAD(&sbsec->isec_head);
253 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 sbsec->sb = sb;
255 sbsec->sid = SECINITSID_UNLABELED;
256 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700257 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 sb->s_security = sbsec;
259
260 return 0;
261}
262
263static void superblock_free_security(struct super_block *sb)
264{
265 struct superblock_security_struct *sbsec = sb->s_security;
266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 spin_lock(&sb_security_lock);
268 if (!list_empty(&sbsec->list))
269 list_del_init(&sbsec->list);
270 spin_unlock(&sb_security_lock);
271
272 sb->s_security = NULL;
273 kfree(sbsec);
274}
275
Al Viro7d877f32005-10-21 03:20:43 -0400276static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
278 struct sk_security_struct *ssec;
279
James Morris89d155e2005-10-30 14:59:21 -0800280 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 if (!ssec)
282 return -ENOMEM;
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 ssec->sk = sk;
285 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700286 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 sk->sk_security = ssec;
288
Paul Moore99f59ed2006-08-29 17:53:48 -0700289 selinux_netlbl_sk_security_init(ssec, family);
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 return 0;
292}
293
294static void sk_free_security(struct sock *sk)
295{
296 struct sk_security_struct *ssec = sk->sk_security;
297
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 sk->sk_security = NULL;
299 kfree(ssec);
300}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302/* The security server must be initialized before
303 any labeling or access decisions can be provided. */
304extern int ss_initialized;
305
306/* The file system's label must be initialized prior to use. */
307
308static char *labeling_behaviors[6] = {
309 "uses xattr",
310 "uses transition SIDs",
311 "uses task SIDs",
312 "uses genfs_contexts",
313 "not configured for labeling",
314 "uses mountpoint labeling",
315};
316
317static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
318
319static inline int inode_doinit(struct inode *inode)
320{
321 return inode_doinit_with_dentry(inode, NULL);
322}
323
324enum {
Eric Paris31e87932007-09-19 17:19:12 -0400325 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 Opt_context = 1,
327 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500328 Opt_defcontext = 3,
329 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330};
331
332static match_table_t tokens = {
333 {Opt_context, "context=%s"},
334 {Opt_fscontext, "fscontext=%s"},
335 {Opt_defcontext, "defcontext=%s"},
Eric Paris08089252006-07-10 04:43:55 -0700336 {Opt_rootcontext, "rootcontext=%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400337 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338};
339
340#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
341
Eric Parisc312feb2006-07-10 04:43:53 -0700342static int may_context_mount_sb_relabel(u32 sid,
343 struct superblock_security_struct *sbsec,
344 struct task_security_struct *tsec)
345{
346 int rc;
347
348 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
349 FILESYSTEM__RELABELFROM, NULL);
350 if (rc)
351 return rc;
352
353 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
354 FILESYSTEM__RELABELTO, NULL);
355 return rc;
356}
357
Eric Paris08089252006-07-10 04:43:55 -0700358static int may_context_mount_inode_relabel(u32 sid,
359 struct superblock_security_struct *sbsec,
360 struct task_security_struct *tsec)
361{
362 int rc;
363 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
364 FILESYSTEM__RELABELFROM, NULL);
365 if (rc)
366 return rc;
367
368 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
369 FILESYSTEM__ASSOCIATE, NULL);
370 return rc;
371}
372
Eric Parisc9180a52007-11-30 13:00:35 -0500373static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
375 struct superblock_security_struct *sbsec = sb->s_security;
376 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500377 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 int rc = 0;
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
381 /* Make sure that the xattr handler exists and that no
382 error other than -ENODATA is returned by getxattr on
383 the root directory. -ENODATA is ok, as this may be
384 the first boot of the SELinux kernel before we have
385 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500386 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
388 "xattr support\n", sb->s_id, sb->s_type->name);
389 rc = -EOPNOTSUPP;
390 goto out;
391 }
Eric Parisc9180a52007-11-30 13:00:35 -0500392 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 if (rc < 0 && rc != -ENODATA) {
394 if (rc == -EOPNOTSUPP)
395 printk(KERN_WARNING "SELinux: (dev %s, type "
396 "%s) has no security xattr handler\n",
397 sb->s_id, sb->s_type->name);
398 else
399 printk(KERN_WARNING "SELinux: (dev %s, type "
400 "%s) getxattr errno %d\n", sb->s_id,
401 sb->s_type->name, -rc);
402 goto out;
403 }
404 }
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 sbsec->initialized = 1;
407
Eric Parisc9180a52007-11-30 13:00:35 -0500408 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500409 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500411 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500412 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 sb->s_id, sb->s_type->name,
414 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500417 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419 /* Initialize any other inodes associated with the superblock, e.g.
420 inodes created prior to initial policy load or inodes created
421 during get_sb by a pseudo filesystem that directly
422 populates itself. */
423 spin_lock(&sbsec->isec_lock);
424next_inode:
425 if (!list_empty(&sbsec->isec_head)) {
426 struct inode_security_struct *isec =
427 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500428 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 struct inode *inode = isec->inode;
430 spin_unlock(&sbsec->isec_lock);
431 inode = igrab(inode);
432 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500433 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 inode_doinit(inode);
435 iput(inode);
436 }
437 spin_lock(&sbsec->isec_lock);
438 list_del_init(&isec->list);
439 goto next_inode;
440 }
441 spin_unlock(&sbsec->isec_lock);
442out:
Eric Parisc9180a52007-11-30 13:00:35 -0500443 return rc;
444}
445
446/*
447 * This function should allow an FS to ask what it's mount security
448 * options were so it can use those later for submounts, displaying
449 * mount options, or whatever.
450 */
451static int selinux_get_mnt_opts(const struct super_block *sb,
452 char ***mount_options, int **mnt_opts_flags,
453 int *num_opts)
454{
455 int rc = 0, i;
456 struct superblock_security_struct *sbsec = sb->s_security;
457 char *context = NULL;
458 u32 len;
459 char tmp;
460
461 *num_opts = 0;
462 *mount_options = NULL;
463 *mnt_opts_flags = NULL;
464
465 if (!sbsec->initialized)
466 return -EINVAL;
467
468 if (!ss_initialized)
469 return -EINVAL;
470
471 /*
472 * if we ever use sbsec flags for anything other than tracking mount
473 * settings this is going to need a mask
474 */
475 tmp = sbsec->flags;
476 /* count the number of mount options for this sb */
477 for (i = 0; i < 8; i++) {
478 if (tmp & 0x01)
479 (*num_opts)++;
480 tmp >>= 1;
481 }
482
483 *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
484 if (!*mount_options) {
485 rc = -ENOMEM;
486 goto out_free;
487 }
488
489 *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
490 if (!*mnt_opts_flags) {
491 rc = -ENOMEM;
492 goto out_free;
493 }
494
495 i = 0;
496 if (sbsec->flags & FSCONTEXT_MNT) {
497 rc = security_sid_to_context(sbsec->sid, &context, &len);
498 if (rc)
499 goto out_free;
500 (*mount_options)[i] = context;
501 (*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
502 }
503 if (sbsec->flags & CONTEXT_MNT) {
504 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
505 if (rc)
506 goto out_free;
507 (*mount_options)[i] = context;
508 (*mnt_opts_flags)[i++] = CONTEXT_MNT;
509 }
510 if (sbsec->flags & DEFCONTEXT_MNT) {
511 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
512 if (rc)
513 goto out_free;
514 (*mount_options)[i] = context;
515 (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
516 }
517 if (sbsec->flags & ROOTCONTEXT_MNT) {
518 struct inode *root = sbsec->sb->s_root->d_inode;
519 struct inode_security_struct *isec = root->i_security;
520
521 rc = security_sid_to_context(isec->sid, &context, &len);
522 if (rc)
523 goto out_free;
524 (*mount_options)[i] = context;
525 (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
526 }
527
528 BUG_ON(i != *num_opts);
529
530 return 0;
531
532out_free:
533 /* don't leak context string if security_sid_to_context had an error */
534 if (*mount_options && i)
535 for (; i > 0; i--)
536 kfree((*mount_options)[i-1]);
537 kfree(*mount_options);
538 *mount_options = NULL;
539 kfree(*mnt_opts_flags);
540 *mnt_opts_flags = NULL;
541 *num_opts = 0;
542 return rc;
543}
544
545static int bad_option(struct superblock_security_struct *sbsec, char flag,
546 u32 old_sid, u32 new_sid)
547{
548 /* check if the old mount command had the same options */
549 if (sbsec->initialized)
550 if (!(sbsec->flags & flag) ||
551 (old_sid != new_sid))
552 return 1;
553
554 /* check if we were passed the same options twice,
555 * aka someone passed context=a,context=b
556 */
557 if (!sbsec->initialized)
558 if (sbsec->flags & flag)
559 return 1;
560 return 0;
561}
562/*
563 * Allow filesystems with binary mount data to explicitly set mount point
564 * labeling information.
565 */
566int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
567 int *flags, int num_opts)
568{
569 int rc = 0, i;
570 struct task_security_struct *tsec = current->security;
571 struct superblock_security_struct *sbsec = sb->s_security;
572 const char *name = sb->s_type->name;
573 struct inode *inode = sbsec->sb->s_root->d_inode;
574 struct inode_security_struct *root_isec = inode->i_security;
575 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
576 u32 defcontext_sid = 0;
577
578 mutex_lock(&sbsec->lock);
579
580 if (!ss_initialized) {
581 if (!num_opts) {
582 /* Defer initialization until selinux_complete_init,
583 after the initial policy is loaded and the security
584 server is ready to handle calls. */
585 spin_lock(&sb_security_lock);
586 if (list_empty(&sbsec->list))
587 list_add(&sbsec->list, &superblock_security_head);
588 spin_unlock(&sb_security_lock);
589 goto out;
590 }
591 rc = -EINVAL;
592 printk(KERN_WARNING "Unable to set superblock options before "
593 "the security server is initialized\n");
594 goto out;
595 }
596
597 /*
598 * parse the mount options, check if they are valid sids.
599 * also check if someone is trying to mount the same sb more
600 * than once with different security options.
601 */
602 for (i = 0; i < num_opts; i++) {
603 u32 sid;
604 rc = security_context_to_sid(mount_options[i],
605 strlen(mount_options[i]), &sid);
606 if (rc) {
607 printk(KERN_WARNING "SELinux: security_context_to_sid"
608 "(%s) failed for (dev %s, type %s) errno=%d\n",
609 mount_options[i], sb->s_id, name, rc);
610 goto out;
611 }
612 switch (flags[i]) {
613 case FSCONTEXT_MNT:
614 fscontext_sid = sid;
615
616 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
617 fscontext_sid))
618 goto out_double_mount;
619
620 sbsec->flags |= FSCONTEXT_MNT;
621 break;
622 case CONTEXT_MNT:
623 context_sid = sid;
624
625 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
626 context_sid))
627 goto out_double_mount;
628
629 sbsec->flags |= CONTEXT_MNT;
630 break;
631 case ROOTCONTEXT_MNT:
632 rootcontext_sid = sid;
633
634 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
635 rootcontext_sid))
636 goto out_double_mount;
637
638 sbsec->flags |= ROOTCONTEXT_MNT;
639
640 break;
641 case DEFCONTEXT_MNT:
642 defcontext_sid = sid;
643
644 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
645 defcontext_sid))
646 goto out_double_mount;
647
648 sbsec->flags |= DEFCONTEXT_MNT;
649
650 break;
651 default:
652 rc = -EINVAL;
653 goto out;
654 }
655 }
656
657 if (sbsec->initialized) {
658 /* previously mounted with options, but not on this attempt? */
659 if (sbsec->flags && !num_opts)
660 goto out_double_mount;
661 rc = 0;
662 goto out;
663 }
664
665 if (strcmp(sb->s_type->name, "proc") == 0)
666 sbsec->proc = 1;
667
668 /* Determine the labeling behavior to use for this filesystem type. */
669 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
670 if (rc) {
671 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
672 __FUNCTION__, sb->s_type->name, rc);
673 goto out;
674 }
675
676 /* sets the context of the superblock for the fs being mounted. */
677 if (fscontext_sid) {
678
679 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
680 if (rc)
681 goto out;
682
683 sbsec->sid = fscontext_sid;
684 }
685
686 /*
687 * Switch to using mount point labeling behavior.
688 * sets the label used on all file below the mountpoint, and will set
689 * the superblock context if not already set.
690 */
691 if (context_sid) {
692 if (!fscontext_sid) {
693 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
694 if (rc)
695 goto out;
696 sbsec->sid = context_sid;
697 } else {
698 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
699 if (rc)
700 goto out;
701 }
702 if (!rootcontext_sid)
703 rootcontext_sid = context_sid;
704
705 sbsec->mntpoint_sid = context_sid;
706 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
707 }
708
709 if (rootcontext_sid) {
710 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
711 if (rc)
712 goto out;
713
714 root_isec->sid = rootcontext_sid;
715 root_isec->initialized = 1;
716 }
717
718 if (defcontext_sid) {
719 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
720 rc = -EINVAL;
721 printk(KERN_WARNING "SELinux: defcontext option is "
722 "invalid for this filesystem type\n");
723 goto out;
724 }
725
726 if (defcontext_sid != sbsec->def_sid) {
727 rc = may_context_mount_inode_relabel(defcontext_sid,
728 sbsec, tsec);
729 if (rc)
730 goto out;
731 }
732
733 sbsec->def_sid = defcontext_sid;
734 }
735
736 rc = sb_finish_set_opts(sb);
737out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700738 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500740out_double_mount:
741 rc = -EINVAL;
742 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
743 "security settings for (dev %s, type %s)\n", sb->s_id, name);
744 goto out;
745}
746
747static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
748 struct super_block *newsb)
749{
750 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
751 struct superblock_security_struct *newsbsec = newsb->s_security;
752
753 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
754 int set_context = (oldsbsec->flags & CONTEXT_MNT);
755 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
756
757 /* we can't error, we can't save the info, this shouldn't get called
758 * this early in the boot process. */
759 BUG_ON(!ss_initialized);
760
761 /* this might go away sometime down the line if there is a new user
762 * of clone, but for now, nfs better not get here... */
763 BUG_ON(newsbsec->initialized);
764
765 /* how can we clone if the old one wasn't set up?? */
766 BUG_ON(!oldsbsec->initialized);
767
768 mutex_lock(&newsbsec->lock);
769
770 newsbsec->flags = oldsbsec->flags;
771
772 newsbsec->sid = oldsbsec->sid;
773 newsbsec->def_sid = oldsbsec->def_sid;
774 newsbsec->behavior = oldsbsec->behavior;
775
776 if (set_context) {
777 u32 sid = oldsbsec->mntpoint_sid;
778
779 if (!set_fscontext)
780 newsbsec->sid = sid;
781 if (!set_rootcontext) {
782 struct inode *newinode = newsb->s_root->d_inode;
783 struct inode_security_struct *newisec = newinode->i_security;
784 newisec->sid = sid;
785 }
786 newsbsec->mntpoint_sid = sid;
787 }
788 if (set_rootcontext) {
789 const struct inode *oldinode = oldsb->s_root->d_inode;
790 const struct inode_security_struct *oldisec = oldinode->i_security;
791 struct inode *newinode = newsb->s_root->d_inode;
792 struct inode_security_struct *newisec = newinode->i_security;
793
794 newisec->sid = oldisec->sid;
795 }
796
797 sb_finish_set_opts(newsb);
798 mutex_unlock(&newsbsec->lock);
799}
800
801/*
802 * string mount options parsing and call set the sbsec
803 */
804static int superblock_doinit(struct super_block *sb, void *data)
805{
806 char *context = NULL, *defcontext = NULL;
807 char *fscontext = NULL, *rootcontext = NULL;
808 int rc = 0;
809 char *p, *options = data;
810 /* selinux only know about a fixed number of mount options */
811 char *mnt_opts[NUM_SEL_MNT_OPTS];
812 int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
813
814 if (!data)
815 goto out;
816
817 /* with the nfs patch this will become a goto out; */
818 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
819 const char *name = sb->s_type->name;
820 /* NFS we understand. */
821 if (!strcmp(name, "nfs")) {
822 struct nfs_mount_data *d = data;
823
824 if (d->version != NFS_MOUNT_VERSION)
825 goto out;
826
827 if (d->context[0]) {
828 context = kstrdup(d->context, GFP_KERNEL);
829 if (!context) {
830 rc = -ENOMEM;
831 goto out;
832 }
833 }
834 goto build_flags;
835 } else
836 goto out;
837 }
838
839 /* Standard string-based options. */
840 while ((p = strsep(&options, "|")) != NULL) {
841 int token;
842 substring_t args[MAX_OPT_ARGS];
843
844 if (!*p)
845 continue;
846
847 token = match_token(p, tokens, args);
848
849 switch (token) {
850 case Opt_context:
851 if (context || defcontext) {
852 rc = -EINVAL;
853 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
854 goto out_err;
855 }
856 context = match_strdup(&args[0]);
857 if (!context) {
858 rc = -ENOMEM;
859 goto out_err;
860 }
861 break;
862
863 case Opt_fscontext:
864 if (fscontext) {
865 rc = -EINVAL;
866 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
867 goto out_err;
868 }
869 fscontext = match_strdup(&args[0]);
870 if (!fscontext) {
871 rc = -ENOMEM;
872 goto out_err;
873 }
874 break;
875
876 case Opt_rootcontext:
877 if (rootcontext) {
878 rc = -EINVAL;
879 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
880 goto out_err;
881 }
882 rootcontext = match_strdup(&args[0]);
883 if (!rootcontext) {
884 rc = -ENOMEM;
885 goto out_err;
886 }
887 break;
888
889 case Opt_defcontext:
890 if (context || defcontext) {
891 rc = -EINVAL;
892 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
893 goto out_err;
894 }
895 defcontext = match_strdup(&args[0]);
896 if (!defcontext) {
897 rc = -ENOMEM;
898 goto out_err;
899 }
900 break;
901
902 default:
903 rc = -EINVAL;
904 printk(KERN_WARNING "SELinux: unknown mount option\n");
905 goto out_err;
906
907 }
908 }
909
910build_flags:
911 if (fscontext) {
912 mnt_opts[num_mnt_opts] = fscontext;
913 mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
914 }
915 if (context) {
916 mnt_opts[num_mnt_opts] = context;
917 mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
918 }
919 if (rootcontext) {
920 mnt_opts[num_mnt_opts] = rootcontext;
921 mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
922 }
923 if (defcontext) {
924 mnt_opts[num_mnt_opts] = defcontext;
925 mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
926 }
927
928out:
929 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
930out_err:
931 kfree(context);
932 kfree(defcontext);
933 kfree(fscontext);
934 kfree(rootcontext);
935 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936}
937
938static inline u16 inode_mode_to_security_class(umode_t mode)
939{
940 switch (mode & S_IFMT) {
941 case S_IFSOCK:
942 return SECCLASS_SOCK_FILE;
943 case S_IFLNK:
944 return SECCLASS_LNK_FILE;
945 case S_IFREG:
946 return SECCLASS_FILE;
947 case S_IFBLK:
948 return SECCLASS_BLK_FILE;
949 case S_IFDIR:
950 return SECCLASS_DIR;
951 case S_IFCHR:
952 return SECCLASS_CHR_FILE;
953 case S_IFIFO:
954 return SECCLASS_FIFO_FILE;
955
956 }
957
958 return SECCLASS_FILE;
959}
960
James Morris13402582005-09-30 14:24:34 -0400961static inline int default_protocol_stream(int protocol)
962{
963 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
964}
965
966static inline int default_protocol_dgram(int protocol)
967{
968 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
969}
970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971static inline u16 socket_type_to_security_class(int family, int type, int protocol)
972{
973 switch (family) {
974 case PF_UNIX:
975 switch (type) {
976 case SOCK_STREAM:
977 case SOCK_SEQPACKET:
978 return SECCLASS_UNIX_STREAM_SOCKET;
979 case SOCK_DGRAM:
980 return SECCLASS_UNIX_DGRAM_SOCKET;
981 }
982 break;
983 case PF_INET:
984 case PF_INET6:
985 switch (type) {
986 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -0400987 if (default_protocol_stream(protocol))
988 return SECCLASS_TCP_SOCKET;
989 else
990 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -0400992 if (default_protocol_dgram(protocol))
993 return SECCLASS_UDP_SOCKET;
994 else
995 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -0800996 case SOCK_DCCP:
997 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -0400998 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return SECCLASS_RAWIP_SOCKET;
1000 }
1001 break;
1002 case PF_NETLINK:
1003 switch (protocol) {
1004 case NETLINK_ROUTE:
1005 return SECCLASS_NETLINK_ROUTE_SOCKET;
1006 case NETLINK_FIREWALL:
1007 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001008 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1010 case NETLINK_NFLOG:
1011 return SECCLASS_NETLINK_NFLOG_SOCKET;
1012 case NETLINK_XFRM:
1013 return SECCLASS_NETLINK_XFRM_SOCKET;
1014 case NETLINK_SELINUX:
1015 return SECCLASS_NETLINK_SELINUX_SOCKET;
1016 case NETLINK_AUDIT:
1017 return SECCLASS_NETLINK_AUDIT_SOCKET;
1018 case NETLINK_IP6_FW:
1019 return SECCLASS_NETLINK_IP6FW_SOCKET;
1020 case NETLINK_DNRTMSG:
1021 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001022 case NETLINK_KOBJECT_UEVENT:
1023 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 default:
1025 return SECCLASS_NETLINK_SOCKET;
1026 }
1027 case PF_PACKET:
1028 return SECCLASS_PACKET_SOCKET;
1029 case PF_KEY:
1030 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001031 case PF_APPLETALK:
1032 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034
1035 return SECCLASS_SOCKET;
1036}
1037
1038#ifdef CONFIG_PROC_FS
1039static int selinux_proc_get_sid(struct proc_dir_entry *de,
1040 u16 tclass,
1041 u32 *sid)
1042{
1043 int buflen, rc;
1044 char *buffer, *path, *end;
1045
1046 buffer = (char*)__get_free_page(GFP_KERNEL);
1047 if (!buffer)
1048 return -ENOMEM;
1049
1050 buflen = PAGE_SIZE;
1051 end = buffer+buflen;
1052 *--end = '\0';
1053 buflen--;
1054 path = end-1;
1055 *path = '/';
1056 while (de && de != de->parent) {
1057 buflen -= de->namelen + 1;
1058 if (buflen < 0)
1059 break;
1060 end -= de->namelen;
1061 memcpy(end, de->name, de->namelen);
1062 *--end = '/';
1063 path = end;
1064 de = de->parent;
1065 }
1066 rc = security_genfs_sid("proc", path, tclass, sid);
1067 free_page((unsigned long)buffer);
1068 return rc;
1069}
1070#else
1071static int selinux_proc_get_sid(struct proc_dir_entry *de,
1072 u16 tclass,
1073 u32 *sid)
1074{
1075 return -EINVAL;
1076}
1077#endif
1078
1079/* The inode's security attributes must be initialized before first use. */
1080static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1081{
1082 struct superblock_security_struct *sbsec = NULL;
1083 struct inode_security_struct *isec = inode->i_security;
1084 u32 sid;
1085 struct dentry *dentry;
1086#define INITCONTEXTLEN 255
1087 char *context = NULL;
1088 unsigned len = 0;
1089 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 if (isec->initialized)
1092 goto out;
1093
Eric Paris23970742006-09-25 23:32:01 -07001094 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001096 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098 sbsec = inode->i_sb->s_security;
1099 if (!sbsec->initialized) {
1100 /* Defer initialization until selinux_complete_init,
1101 after the initial policy is loaded and the security
1102 server is ready to handle calls. */
1103 spin_lock(&sbsec->isec_lock);
1104 if (list_empty(&isec->list))
1105 list_add(&isec->list, &sbsec->isec_head);
1106 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001107 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 }
1109
1110 switch (sbsec->behavior) {
1111 case SECURITY_FS_USE_XATTR:
1112 if (!inode->i_op->getxattr) {
1113 isec->sid = sbsec->def_sid;
1114 break;
1115 }
1116
1117 /* Need a dentry, since the xattr API requires one.
1118 Life would be simpler if we could just pass the inode. */
1119 if (opt_dentry) {
1120 /* Called from d_instantiate or d_splice_alias. */
1121 dentry = dget(opt_dentry);
1122 } else {
1123 /* Called from selinux_complete_init, try to find a dentry. */
1124 dentry = d_find_alias(inode);
1125 }
1126 if (!dentry) {
1127 printk(KERN_WARNING "%s: no dentry for dev=%s "
1128 "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
1129 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001130 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 }
1132
1133 len = INITCONTEXTLEN;
1134 context = kmalloc(len, GFP_KERNEL);
1135 if (!context) {
1136 rc = -ENOMEM;
1137 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001138 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 }
1140 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1141 context, len);
1142 if (rc == -ERANGE) {
1143 /* Need a larger buffer. Query for the right size. */
1144 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1145 NULL, 0);
1146 if (rc < 0) {
1147 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001148 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
1150 kfree(context);
1151 len = rc;
1152 context = kmalloc(len, GFP_KERNEL);
1153 if (!context) {
1154 rc = -ENOMEM;
1155 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001156 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 }
1158 rc = inode->i_op->getxattr(dentry,
1159 XATTR_NAME_SELINUX,
1160 context, len);
1161 }
1162 dput(dentry);
1163 if (rc < 0) {
1164 if (rc != -ENODATA) {
1165 printk(KERN_WARNING "%s: getxattr returned "
1166 "%d for dev=%s ino=%ld\n", __FUNCTION__,
1167 -rc, inode->i_sb->s_id, inode->i_ino);
1168 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001169 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
1171 /* Map ENODATA to the default file SID */
1172 sid = sbsec->def_sid;
1173 rc = 0;
1174 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001175 rc = security_context_to_sid_default(context, rc, &sid,
1176 sbsec->def_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 if (rc) {
1178 printk(KERN_WARNING "%s: context_to_sid(%s) "
1179 "returned %d for dev=%s ino=%ld\n",
1180 __FUNCTION__, context, -rc,
1181 inode->i_sb->s_id, inode->i_ino);
1182 kfree(context);
1183 /* Leave with the unlabeled SID */
1184 rc = 0;
1185 break;
1186 }
1187 }
1188 kfree(context);
1189 isec->sid = sid;
1190 break;
1191 case SECURITY_FS_USE_TASK:
1192 isec->sid = isec->task_sid;
1193 break;
1194 case SECURITY_FS_USE_TRANS:
1195 /* Default to the fs SID. */
1196 isec->sid = sbsec->sid;
1197
1198 /* Try to obtain a transition SID. */
1199 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1200 rc = security_transition_sid(isec->task_sid,
1201 sbsec->sid,
1202 isec->sclass,
1203 &sid);
1204 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001205 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 isec->sid = sid;
1207 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001208 case SECURITY_FS_USE_MNTPOINT:
1209 isec->sid = sbsec->mntpoint_sid;
1210 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001212 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 isec->sid = sbsec->sid;
1214
1215 if (sbsec->proc) {
1216 struct proc_inode *proci = PROC_I(inode);
1217 if (proci->pde) {
1218 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1219 rc = selinux_proc_get_sid(proci->pde,
1220 isec->sclass,
1221 &sid);
1222 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001223 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 isec->sid = sid;
1225 }
1226 }
1227 break;
1228 }
1229
1230 isec->initialized = 1;
1231
Eric Paris23970742006-09-25 23:32:01 -07001232out_unlock:
1233 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234out:
1235 if (isec->sclass == SECCLASS_FILE)
1236 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 return rc;
1238}
1239
1240/* Convert a Linux signal to an access vector. */
1241static inline u32 signal_to_av(int sig)
1242{
1243 u32 perm = 0;
1244
1245 switch (sig) {
1246 case SIGCHLD:
1247 /* Commonly granted from child to parent. */
1248 perm = PROCESS__SIGCHLD;
1249 break;
1250 case SIGKILL:
1251 /* Cannot be caught or ignored */
1252 perm = PROCESS__SIGKILL;
1253 break;
1254 case SIGSTOP:
1255 /* Cannot be caught or ignored */
1256 perm = PROCESS__SIGSTOP;
1257 break;
1258 default:
1259 /* All other signals. */
1260 perm = PROCESS__SIGNAL;
1261 break;
1262 }
1263
1264 return perm;
1265}
1266
1267/* Check permission betweeen a pair of tasks, e.g. signal checks,
1268 fork check, ptrace check, etc. */
1269static int task_has_perm(struct task_struct *tsk1,
1270 struct task_struct *tsk2,
1271 u32 perms)
1272{
1273 struct task_security_struct *tsec1, *tsec2;
1274
1275 tsec1 = tsk1->security;
1276 tsec2 = tsk2->security;
1277 return avc_has_perm(tsec1->sid, tsec2->sid,
1278 SECCLASS_PROCESS, perms, NULL);
1279}
1280
1281/* Check whether a task is allowed to use a capability. */
1282static int task_has_capability(struct task_struct *tsk,
1283 int cap)
1284{
1285 struct task_security_struct *tsec;
1286 struct avc_audit_data ad;
1287
1288 tsec = tsk->security;
1289
1290 AVC_AUDIT_DATA_INIT(&ad,CAP);
1291 ad.tsk = tsk;
1292 ad.u.cap = cap;
1293
1294 return avc_has_perm(tsec->sid, tsec->sid,
1295 SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
1296}
1297
1298/* Check whether a task is allowed to use a system operation. */
1299static int task_has_system(struct task_struct *tsk,
1300 u32 perms)
1301{
1302 struct task_security_struct *tsec;
1303
1304 tsec = tsk->security;
1305
1306 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1307 SECCLASS_SYSTEM, perms, NULL);
1308}
1309
1310/* Check whether a task has a particular permission to an inode.
1311 The 'adp' parameter is optional and allows other audit
1312 data to be passed (e.g. the dentry). */
1313static int inode_has_perm(struct task_struct *tsk,
1314 struct inode *inode,
1315 u32 perms,
1316 struct avc_audit_data *adp)
1317{
1318 struct task_security_struct *tsec;
1319 struct inode_security_struct *isec;
1320 struct avc_audit_data ad;
1321
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001322 if (unlikely (IS_PRIVATE (inode)))
1323 return 0;
1324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 tsec = tsk->security;
1326 isec = inode->i_security;
1327
1328 if (!adp) {
1329 adp = &ad;
1330 AVC_AUDIT_DATA_INIT(&ad, FS);
1331 ad.u.fs.inode = inode;
1332 }
1333
1334 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1335}
1336
1337/* Same as inode_has_perm, but pass explicit audit data containing
1338 the dentry to help the auditing code to more easily generate the
1339 pathname if needed. */
1340static inline int dentry_has_perm(struct task_struct *tsk,
1341 struct vfsmount *mnt,
1342 struct dentry *dentry,
1343 u32 av)
1344{
1345 struct inode *inode = dentry->d_inode;
1346 struct avc_audit_data ad;
1347 AVC_AUDIT_DATA_INIT(&ad,FS);
1348 ad.u.fs.mnt = mnt;
1349 ad.u.fs.dentry = dentry;
1350 return inode_has_perm(tsk, inode, av, &ad);
1351}
1352
1353/* Check whether a task can use an open file descriptor to
1354 access an inode in a given way. Check access to the
1355 descriptor itself, and then use dentry_has_perm to
1356 check a particular permission to the file.
1357 Access to the descriptor is implicitly granted if it
1358 has the same SID as the process. If av is zero, then
1359 access to the file is not checked, e.g. for cases
1360 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001361static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 struct file *file,
1363 u32 av)
1364{
1365 struct task_security_struct *tsec = tsk->security;
1366 struct file_security_struct *fsec = file->f_security;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001367 struct vfsmount *mnt = file->f_path.mnt;
1368 struct dentry *dentry = file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 struct inode *inode = dentry->d_inode;
1370 struct avc_audit_data ad;
1371 int rc;
1372
1373 AVC_AUDIT_DATA_INIT(&ad, FS);
1374 ad.u.fs.mnt = mnt;
1375 ad.u.fs.dentry = dentry;
1376
1377 if (tsec->sid != fsec->sid) {
1378 rc = avc_has_perm(tsec->sid, fsec->sid,
1379 SECCLASS_FD,
1380 FD__USE,
1381 &ad);
1382 if (rc)
1383 return rc;
1384 }
1385
1386 /* av is zero if only checking access to the descriptor. */
1387 if (av)
1388 return inode_has_perm(tsk, inode, av, &ad);
1389
1390 return 0;
1391}
1392
1393/* Check whether a task can create a file. */
1394static int may_create(struct inode *dir,
1395 struct dentry *dentry,
1396 u16 tclass)
1397{
1398 struct task_security_struct *tsec;
1399 struct inode_security_struct *dsec;
1400 struct superblock_security_struct *sbsec;
1401 u32 newsid;
1402 struct avc_audit_data ad;
1403 int rc;
1404
1405 tsec = current->security;
1406 dsec = dir->i_security;
1407 sbsec = dir->i_sb->s_security;
1408
1409 AVC_AUDIT_DATA_INIT(&ad, FS);
1410 ad.u.fs.dentry = dentry;
1411
1412 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1413 DIR__ADD_NAME | DIR__SEARCH,
1414 &ad);
1415 if (rc)
1416 return rc;
1417
1418 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1419 newsid = tsec->create_sid;
1420 } else {
1421 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1422 &newsid);
1423 if (rc)
1424 return rc;
1425 }
1426
1427 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1428 if (rc)
1429 return rc;
1430
1431 return avc_has_perm(newsid, sbsec->sid,
1432 SECCLASS_FILESYSTEM,
1433 FILESYSTEM__ASSOCIATE, &ad);
1434}
1435
Michael LeMay4eb582c2006-06-26 00:24:57 -07001436/* Check whether a task can create a key. */
1437static int may_create_key(u32 ksid,
1438 struct task_struct *ctx)
1439{
1440 struct task_security_struct *tsec;
1441
1442 tsec = ctx->security;
1443
1444 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1445}
1446
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447#define MAY_LINK 0
1448#define MAY_UNLINK 1
1449#define MAY_RMDIR 2
1450
1451/* Check whether a task can link, unlink, or rmdir a file/directory. */
1452static int may_link(struct inode *dir,
1453 struct dentry *dentry,
1454 int kind)
1455
1456{
1457 struct task_security_struct *tsec;
1458 struct inode_security_struct *dsec, *isec;
1459 struct avc_audit_data ad;
1460 u32 av;
1461 int rc;
1462
1463 tsec = current->security;
1464 dsec = dir->i_security;
1465 isec = dentry->d_inode->i_security;
1466
1467 AVC_AUDIT_DATA_INIT(&ad, FS);
1468 ad.u.fs.dentry = dentry;
1469
1470 av = DIR__SEARCH;
1471 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1472 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1473 if (rc)
1474 return rc;
1475
1476 switch (kind) {
1477 case MAY_LINK:
1478 av = FILE__LINK;
1479 break;
1480 case MAY_UNLINK:
1481 av = FILE__UNLINK;
1482 break;
1483 case MAY_RMDIR:
1484 av = DIR__RMDIR;
1485 break;
1486 default:
1487 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1488 return 0;
1489 }
1490
1491 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1492 return rc;
1493}
1494
1495static inline int may_rename(struct inode *old_dir,
1496 struct dentry *old_dentry,
1497 struct inode *new_dir,
1498 struct dentry *new_dentry)
1499{
1500 struct task_security_struct *tsec;
1501 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1502 struct avc_audit_data ad;
1503 u32 av;
1504 int old_is_dir, new_is_dir;
1505 int rc;
1506
1507 tsec = current->security;
1508 old_dsec = old_dir->i_security;
1509 old_isec = old_dentry->d_inode->i_security;
1510 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1511 new_dsec = new_dir->i_security;
1512
1513 AVC_AUDIT_DATA_INIT(&ad, FS);
1514
1515 ad.u.fs.dentry = old_dentry;
1516 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1517 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1518 if (rc)
1519 return rc;
1520 rc = avc_has_perm(tsec->sid, old_isec->sid,
1521 old_isec->sclass, FILE__RENAME, &ad);
1522 if (rc)
1523 return rc;
1524 if (old_is_dir && new_dir != old_dir) {
1525 rc = avc_has_perm(tsec->sid, old_isec->sid,
1526 old_isec->sclass, DIR__REPARENT, &ad);
1527 if (rc)
1528 return rc;
1529 }
1530
1531 ad.u.fs.dentry = new_dentry;
1532 av = DIR__ADD_NAME | DIR__SEARCH;
1533 if (new_dentry->d_inode)
1534 av |= DIR__REMOVE_NAME;
1535 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1536 if (rc)
1537 return rc;
1538 if (new_dentry->d_inode) {
1539 new_isec = new_dentry->d_inode->i_security;
1540 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1541 rc = avc_has_perm(tsec->sid, new_isec->sid,
1542 new_isec->sclass,
1543 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1544 if (rc)
1545 return rc;
1546 }
1547
1548 return 0;
1549}
1550
1551/* Check whether a task can perform a filesystem operation. */
1552static int superblock_has_perm(struct task_struct *tsk,
1553 struct super_block *sb,
1554 u32 perms,
1555 struct avc_audit_data *ad)
1556{
1557 struct task_security_struct *tsec;
1558 struct superblock_security_struct *sbsec;
1559
1560 tsec = tsk->security;
1561 sbsec = sb->s_security;
1562 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1563 perms, ad);
1564}
1565
1566/* Convert a Linux mode and permission mask to an access vector. */
1567static inline u32 file_mask_to_av(int mode, int mask)
1568{
1569 u32 av = 0;
1570
1571 if ((mode & S_IFMT) != S_IFDIR) {
1572 if (mask & MAY_EXEC)
1573 av |= FILE__EXECUTE;
1574 if (mask & MAY_READ)
1575 av |= FILE__READ;
1576
1577 if (mask & MAY_APPEND)
1578 av |= FILE__APPEND;
1579 else if (mask & MAY_WRITE)
1580 av |= FILE__WRITE;
1581
1582 } else {
1583 if (mask & MAY_EXEC)
1584 av |= DIR__SEARCH;
1585 if (mask & MAY_WRITE)
1586 av |= DIR__WRITE;
1587 if (mask & MAY_READ)
1588 av |= DIR__READ;
1589 }
1590
1591 return av;
1592}
1593
1594/* Convert a Linux file to an access vector. */
1595static inline u32 file_to_av(struct file *file)
1596{
1597 u32 av = 0;
1598
1599 if (file->f_mode & FMODE_READ)
1600 av |= FILE__READ;
1601 if (file->f_mode & FMODE_WRITE) {
1602 if (file->f_flags & O_APPEND)
1603 av |= FILE__APPEND;
1604 else
1605 av |= FILE__WRITE;
1606 }
1607
1608 return av;
1609}
1610
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611/* Hook functions begin here. */
1612
1613static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1614{
1615 struct task_security_struct *psec = parent->security;
1616 struct task_security_struct *csec = child->security;
1617 int rc;
1618
1619 rc = secondary_ops->ptrace(parent,child);
1620 if (rc)
1621 return rc;
1622
1623 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1624 /* Save the SID of the tracing process for later use in apply_creds. */
Stephen Smalley341c2d82006-03-11 03:27:16 -08001625 if (!(child->ptrace & PT_PTRACED) && !rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 csec->ptrace_sid = psec->sid;
1627 return rc;
1628}
1629
1630static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1631 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1632{
1633 int error;
1634
1635 error = task_has_perm(current, target, PROCESS__GETCAP);
1636 if (error)
1637 return error;
1638
1639 return secondary_ops->capget(target, effective, inheritable, permitted);
1640}
1641
1642static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1643 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1644{
1645 int error;
1646
1647 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1648 if (error)
1649 return error;
1650
1651 return task_has_perm(current, target, PROCESS__SETCAP);
1652}
1653
1654static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1655 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1656{
1657 secondary_ops->capset_set(target, effective, inheritable, permitted);
1658}
1659
1660static int selinux_capable(struct task_struct *tsk, int cap)
1661{
1662 int rc;
1663
1664 rc = secondary_ops->capable(tsk, cap);
1665 if (rc)
1666 return rc;
1667
1668 return task_has_capability(tsk,cap);
1669}
1670
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001671static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1672{
1673 int buflen, rc;
1674 char *buffer, *path, *end;
1675
1676 rc = -ENOMEM;
1677 buffer = (char*)__get_free_page(GFP_KERNEL);
1678 if (!buffer)
1679 goto out;
1680
1681 buflen = PAGE_SIZE;
1682 end = buffer+buflen;
1683 *--end = '\0';
1684 buflen--;
1685 path = end-1;
1686 *path = '/';
1687 while (table) {
1688 const char *name = table->procname;
1689 size_t namelen = strlen(name);
1690 buflen -= namelen + 1;
1691 if (buflen < 0)
1692 goto out_free;
1693 end -= namelen;
1694 memcpy(end, name, namelen);
1695 *--end = '/';
1696 path = end;
1697 table = table->parent;
1698 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001699 buflen -= 4;
1700 if (buflen < 0)
1701 goto out_free;
1702 end -= 4;
1703 memcpy(end, "/sys", 4);
1704 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001705 rc = security_genfs_sid("proc", path, tclass, sid);
1706out_free:
1707 free_page((unsigned long)buffer);
1708out:
1709 return rc;
1710}
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712static int selinux_sysctl(ctl_table *table, int op)
1713{
1714 int error = 0;
1715 u32 av;
1716 struct task_security_struct *tsec;
1717 u32 tsid;
1718 int rc;
1719
1720 rc = secondary_ops->sysctl(table, op);
1721 if (rc)
1722 return rc;
1723
1724 tsec = current->security;
1725
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001726 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1727 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 if (rc) {
1729 /* Default to the well-defined sysctl SID. */
1730 tsid = SECINITSID_SYSCTL;
1731 }
1732
1733 /* The op values are "defined" in sysctl.c, thereby creating
1734 * a bad coupling between this module and sysctl.c */
1735 if(op == 001) {
1736 error = avc_has_perm(tsec->sid, tsid,
1737 SECCLASS_DIR, DIR__SEARCH, NULL);
1738 } else {
1739 av = 0;
1740 if (op & 004)
1741 av |= FILE__READ;
1742 if (op & 002)
1743 av |= FILE__WRITE;
1744 if (av)
1745 error = avc_has_perm(tsec->sid, tsid,
1746 SECCLASS_FILE, av, NULL);
1747 }
1748
1749 return error;
1750}
1751
1752static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1753{
1754 int rc = 0;
1755
1756 if (!sb)
1757 return 0;
1758
1759 switch (cmds) {
1760 case Q_SYNC:
1761 case Q_QUOTAON:
1762 case Q_QUOTAOFF:
1763 case Q_SETINFO:
1764 case Q_SETQUOTA:
1765 rc = superblock_has_perm(current,
1766 sb,
1767 FILESYSTEM__QUOTAMOD, NULL);
1768 break;
1769 case Q_GETFMT:
1770 case Q_GETINFO:
1771 case Q_GETQUOTA:
1772 rc = superblock_has_perm(current,
1773 sb,
1774 FILESYSTEM__QUOTAGET, NULL);
1775 break;
1776 default:
1777 rc = 0; /* let the kernel handle invalid cmds */
1778 break;
1779 }
1780 return rc;
1781}
1782
1783static int selinux_quota_on(struct dentry *dentry)
1784{
1785 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1786}
1787
1788static int selinux_syslog(int type)
1789{
1790 int rc;
1791
1792 rc = secondary_ops->syslog(type);
1793 if (rc)
1794 return rc;
1795
1796 switch (type) {
1797 case 3: /* Read last kernel messages */
1798 case 10: /* Return size of the log buffer */
1799 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1800 break;
1801 case 6: /* Disable logging to console */
1802 case 7: /* Enable logging to console */
1803 case 8: /* Set level of messages printed to console */
1804 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1805 break;
1806 case 0: /* Close log */
1807 case 1: /* Open log */
1808 case 2: /* Read from log */
1809 case 4: /* Read/clear last kernel messages */
1810 case 5: /* Clear ring buffer */
1811 default:
1812 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1813 break;
1814 }
1815 return rc;
1816}
1817
1818/*
1819 * Check that a process has enough memory to allocate a new virtual
1820 * mapping. 0 means there is enough memory for the allocation to
1821 * succeed and -ENOMEM implies there is not.
1822 *
1823 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1824 * if the capability is granted, but __vm_enough_memory requires 1 if
1825 * the capability is granted.
1826 *
1827 * Do not audit the selinux permission check, as this is applied to all
1828 * processes that allocate mappings.
1829 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001830static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
1832 int rc, cap_sys_admin = 0;
1833 struct task_security_struct *tsec = current->security;
1834
1835 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1836 if (rc == 0)
1837 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001838 SECCLASS_CAPABILITY,
1839 CAP_TO_MASK(CAP_SYS_ADMIN),
1840 0,
1841 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
1843 if (rc == 0)
1844 cap_sys_admin = 1;
1845
Alan Cox34b4e4a2007-08-22 14:01:28 -07001846 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847}
1848
1849/* binprm security operations */
1850
1851static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1852{
1853 struct bprm_security_struct *bsec;
1854
James Morris89d155e2005-10-30 14:59:21 -08001855 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 if (!bsec)
1857 return -ENOMEM;
1858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 bsec->bprm = bprm;
1860 bsec->sid = SECINITSID_UNLABELED;
1861 bsec->set = 0;
1862
1863 bprm->security = bsec;
1864 return 0;
1865}
1866
1867static int selinux_bprm_set_security(struct linux_binprm *bprm)
1868{
1869 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001870 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 struct inode_security_struct *isec;
1872 struct bprm_security_struct *bsec;
1873 u32 newsid;
1874 struct avc_audit_data ad;
1875 int rc;
1876
1877 rc = secondary_ops->bprm_set_security(bprm);
1878 if (rc)
1879 return rc;
1880
1881 bsec = bprm->security;
1882
1883 if (bsec->set)
1884 return 0;
1885
1886 tsec = current->security;
1887 isec = inode->i_security;
1888
1889 /* Default to the current task SID. */
1890 bsec->sid = tsec->sid;
1891
Michael LeMay28eba5b2006-06-27 02:53:42 -07001892 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001894 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001895 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
1897 if (tsec->exec_sid) {
1898 newsid = tsec->exec_sid;
1899 /* Reset exec SID on execve. */
1900 tsec->exec_sid = 0;
1901 } else {
1902 /* Check for a default transition on this program. */
1903 rc = security_transition_sid(tsec->sid, isec->sid,
1904 SECCLASS_PROCESS, &newsid);
1905 if (rc)
1906 return rc;
1907 }
1908
1909 AVC_AUDIT_DATA_INIT(&ad, FS);
Josef Sipek3d5ff522006-12-08 02:37:38 -08001910 ad.u.fs.mnt = bprm->file->f_path.mnt;
1911 ad.u.fs.dentry = bprm->file->f_path.dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Josef Sipek3d5ff522006-12-08 02:37:38 -08001913 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 newsid = tsec->sid;
1915
1916 if (tsec->sid == newsid) {
1917 rc = avc_has_perm(tsec->sid, isec->sid,
1918 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1919 if (rc)
1920 return rc;
1921 } else {
1922 /* Check permissions for the transition. */
1923 rc = avc_has_perm(tsec->sid, newsid,
1924 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1925 if (rc)
1926 return rc;
1927
1928 rc = avc_has_perm(newsid, isec->sid,
1929 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1930 if (rc)
1931 return rc;
1932
1933 /* Clear any possibly unsafe personality bits on exec: */
1934 current->personality &= ~PER_CLEAR_ON_SETID;
1935
1936 /* Set the security field to the new SID. */
1937 bsec->sid = newsid;
1938 }
1939
1940 bsec->set = 1;
1941 return 0;
1942}
1943
1944static int selinux_bprm_check_security (struct linux_binprm *bprm)
1945{
1946 return secondary_ops->bprm_check_security(bprm);
1947}
1948
1949
1950static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1951{
1952 struct task_security_struct *tsec = current->security;
1953 int atsecure = 0;
1954
1955 if (tsec->osid != tsec->sid) {
1956 /* Enable secure mode for SIDs transitions unless
1957 the noatsecure permission is granted between
1958 the two SIDs, i.e. ahp returns 0. */
1959 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1960 SECCLASS_PROCESS,
1961 PROCESS__NOATSECURE, NULL);
1962 }
1963
1964 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1965}
1966
1967static void selinux_bprm_free_security(struct linux_binprm *bprm)
1968{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07001969 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
1973extern struct vfsmount *selinuxfs_mount;
1974extern struct dentry *selinux_null;
1975
1976/* Derived from fs/exec.c:flush_old_files. */
1977static inline void flush_unauthorized_files(struct files_struct * files)
1978{
1979 struct avc_audit_data ad;
1980 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001981 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07001982 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001984 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
Stephen Smalleyb20c8122006-09-25 23:32:03 -07001986 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08001987 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 if (tty) {
1989 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08001990 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 if (file) {
1992 /* Revalidate access to controlling tty.
1993 Use inode_has_perm on the tty inode directly rather
1994 than using file_has_perm, as this particular open
1995 file may belong to another process and we are only
1996 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08001997 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 if (inode_has_perm(current, inode,
1999 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002000 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 }
2002 }
2003 file_list_unlock();
2004 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002005 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002006 /* Reset controlling tty. */
2007 if (drop_tty)
2008 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 /* Revalidate access to inherited open files. */
2011
2012 AVC_AUDIT_DATA_INIT(&ad,FS);
2013
2014 spin_lock(&files->file_lock);
2015 for (;;) {
2016 unsigned long set, i;
2017 int fd;
2018
2019 j++;
2020 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002021 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002022 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002024 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 if (!set)
2026 continue;
2027 spin_unlock(&files->file_lock);
2028 for ( ; set ; i++,set >>= 1) {
2029 if (set & 1) {
2030 file = fget(i);
2031 if (!file)
2032 continue;
2033 if (file_has_perm(current,
2034 file,
2035 file_to_av(file))) {
2036 sys_close(i);
2037 fd = get_unused_fd();
2038 if (fd != i) {
2039 if (fd >= 0)
2040 put_unused_fd(fd);
2041 fput(file);
2042 continue;
2043 }
2044 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002045 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 } else {
2047 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002048 if (IS_ERR(devnull)) {
2049 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 put_unused_fd(fd);
2051 fput(file);
2052 continue;
2053 }
2054 }
2055 fd_install(fd, devnull);
2056 }
2057 fput(file);
2058 }
2059 }
2060 spin_lock(&files->file_lock);
2061
2062 }
2063 spin_unlock(&files->file_lock);
2064}
2065
2066static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2067{
2068 struct task_security_struct *tsec;
2069 struct bprm_security_struct *bsec;
2070 u32 sid;
2071 int rc;
2072
2073 secondary_ops->bprm_apply_creds(bprm, unsafe);
2074
2075 tsec = current->security;
2076
2077 bsec = bprm->security;
2078 sid = bsec->sid;
2079
2080 tsec->osid = tsec->sid;
2081 bsec->unsafe = 0;
2082 if (tsec->sid != sid) {
2083 /* Check for shared state. If not ok, leave SID
2084 unchanged and kill. */
2085 if (unsafe & LSM_UNSAFE_SHARE) {
2086 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2087 PROCESS__SHARE, NULL);
2088 if (rc) {
2089 bsec->unsafe = 1;
2090 return;
2091 }
2092 }
2093
2094 /* Check for ptracing, and update the task SID if ok.
2095 Otherwise, leave SID unchanged and kill. */
2096 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2097 rc = avc_has_perm(tsec->ptrace_sid, sid,
2098 SECCLASS_PROCESS, PROCESS__PTRACE,
2099 NULL);
2100 if (rc) {
2101 bsec->unsafe = 1;
2102 return;
2103 }
2104 }
2105 tsec->sid = sid;
2106 }
2107}
2108
2109/*
2110 * called after apply_creds without the task lock held
2111 */
2112static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2113{
2114 struct task_security_struct *tsec;
2115 struct rlimit *rlim, *initrlim;
2116 struct itimerval itimer;
2117 struct bprm_security_struct *bsec;
2118 int rc, i;
2119
2120 tsec = current->security;
2121 bsec = bprm->security;
2122
2123 if (bsec->unsafe) {
2124 force_sig_specific(SIGKILL, current);
2125 return;
2126 }
2127 if (tsec->osid == tsec->sid)
2128 return;
2129
2130 /* Close files for which the new task SID is not authorized. */
2131 flush_unauthorized_files(current->files);
2132
2133 /* Check whether the new SID can inherit signal state
2134 from the old SID. If not, clear itimers to avoid
2135 subsequent signal generation and flush and unblock
2136 signals. This must occur _after_ the task SID has
2137 been updated so that any kill done after the flush
2138 will be checked against the new SID. */
2139 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2140 PROCESS__SIGINH, NULL);
2141 if (rc) {
2142 memset(&itimer, 0, sizeof itimer);
2143 for (i = 0; i < 3; i++)
2144 do_setitimer(i, &itimer, NULL);
2145 flush_signals(current);
2146 spin_lock_irq(&current->sighand->siglock);
2147 flush_signal_handlers(current, 1);
2148 sigemptyset(&current->blocked);
2149 recalc_sigpending();
2150 spin_unlock_irq(&current->sighand->siglock);
2151 }
2152
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002153 /* Always clear parent death signal on SID transitions. */
2154 current->pdeath_signal = 0;
2155
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 /* Check whether the new SID can inherit resource limits
2157 from the old SID. If not, reset all soft limits to
2158 the lower of the current task's hard limit and the init
2159 task's soft limit. Note that the setting of hard limits
2160 (even to lower them) can be controlled by the setrlimit
2161 check. The inclusion of the init task's soft limit into
2162 the computation is to avoid resetting soft limits higher
2163 than the default soft limit for cases where the default
2164 is lower than the hard limit, e.g. RLIMIT_CORE or
2165 RLIMIT_STACK.*/
2166 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2167 PROCESS__RLIMITINH, NULL);
2168 if (rc) {
2169 for (i = 0; i < RLIM_NLIMITS; i++) {
2170 rlim = current->signal->rlim + i;
2171 initrlim = init_task.signal->rlim+i;
2172 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
2173 }
2174 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2175 /*
2176 * This will cause RLIMIT_CPU calculations
2177 * to be refigured.
2178 */
2179 current->it_prof_expires = jiffies_to_cputime(1);
2180 }
2181 }
2182
2183 /* Wake up the parent if it is waiting so that it can
2184 recheck wait permission to the new task SID. */
2185 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2186}
2187
2188/* superblock security operations */
2189
2190static int selinux_sb_alloc_security(struct super_block *sb)
2191{
2192 return superblock_alloc_security(sb);
2193}
2194
2195static void selinux_sb_free_security(struct super_block *sb)
2196{
2197 superblock_free_security(sb);
2198}
2199
2200static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2201{
2202 if (plen > olen)
2203 return 0;
2204
2205 return !memcmp(prefix, option, plen);
2206}
2207
2208static inline int selinux_option(char *option, int len)
2209{
2210 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
2211 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
Eric Paris08089252006-07-10 04:43:55 -07002212 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
2213 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214}
2215
2216static inline void take_option(char **to, char *from, int *first, int len)
2217{
2218 if (!*first) {
2219 **to = ',';
2220 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002221 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 *first = 0;
2223 memcpy(*to, from, len);
2224 *to += len;
2225}
2226
Cory Olmo3528a952006-09-29 01:58:44 -07002227static inline void take_selinux_option(char **to, char *from, int *first,
2228 int len)
2229{
2230 int current_size = 0;
2231
2232 if (!*first) {
2233 **to = '|';
2234 *to += 1;
2235 }
2236 else
2237 *first = 0;
2238
2239 while (current_size < len) {
2240 if (*from != '"') {
2241 **to = *from;
2242 *to += 1;
2243 }
2244 from += 1;
2245 current_size += 1;
2246 }
2247}
2248
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
2250{
2251 int fnosec, fsec, rc = 0;
2252 char *in_save, *in_curr, *in_end;
2253 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002254 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
2256 in_curr = orig;
2257 sec_curr = copy;
2258
2259 /* Binary mount data: just copy */
2260 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2261 copy_page(sec_curr, in_curr);
2262 goto out;
2263 }
2264
2265 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2266 if (!nosec) {
2267 rc = -ENOMEM;
2268 goto out;
2269 }
2270
2271 nosec_save = nosec;
2272 fnosec = fsec = 1;
2273 in_save = in_end = orig;
2274
2275 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002276 if (*in_end == '"')
2277 open_quote = !open_quote;
2278 if ((*in_end == ',' && open_quote == 0) ||
2279 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 int len = in_end - in_curr;
2281
2282 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002283 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 else
2285 take_option(&nosec, in_curr, &fnosec, len);
2286
2287 in_curr = in_end + 1;
2288 }
2289 } while (*in_end++);
2290
Eric Paris6931dfc2005-06-30 02:58:51 -07002291 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002292 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293out:
2294 return rc;
2295}
2296
2297static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2298{
2299 struct avc_audit_data ad;
2300 int rc;
2301
2302 rc = superblock_doinit(sb, data);
2303 if (rc)
2304 return rc;
2305
2306 AVC_AUDIT_DATA_INIT(&ad,FS);
2307 ad.u.fs.dentry = sb->s_root;
2308 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2309}
2310
David Howells726c3342006-06-23 02:02:58 -07002311static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312{
2313 struct avc_audit_data ad;
2314
2315 AVC_AUDIT_DATA_INIT(&ad,FS);
David Howells726c3342006-06-23 02:02:58 -07002316 ad.u.fs.dentry = dentry->d_sb->s_root;
2317 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318}
2319
2320static int selinux_mount(char * dev_name,
2321 struct nameidata *nd,
2322 char * type,
2323 unsigned long flags,
2324 void * data)
2325{
2326 int rc;
2327
2328 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2329 if (rc)
2330 return rc;
2331
2332 if (flags & MS_REMOUNT)
2333 return superblock_has_perm(current, nd->mnt->mnt_sb,
2334 FILESYSTEM__REMOUNT, NULL);
2335 else
2336 return dentry_has_perm(current, nd->mnt, nd->dentry,
2337 FILE__MOUNTON);
2338}
2339
2340static int selinux_umount(struct vfsmount *mnt, int flags)
2341{
2342 int rc;
2343
2344 rc = secondary_ops->sb_umount(mnt, flags);
2345 if (rc)
2346 return rc;
2347
2348 return superblock_has_perm(current,mnt->mnt_sb,
2349 FILESYSTEM__UNMOUNT,NULL);
2350}
2351
2352/* inode security operations */
2353
2354static int selinux_inode_alloc_security(struct inode *inode)
2355{
2356 return inode_alloc_security(inode);
2357}
2358
2359static void selinux_inode_free_security(struct inode *inode)
2360{
2361 inode_free_security(inode);
2362}
2363
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002364static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2365 char **name, void **value,
2366 size_t *len)
2367{
2368 struct task_security_struct *tsec;
2369 struct inode_security_struct *dsec;
2370 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002371 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002372 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002373 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002374
2375 tsec = current->security;
2376 dsec = dir->i_security;
2377 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002378
2379 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2380 newsid = tsec->create_sid;
2381 } else {
2382 rc = security_transition_sid(tsec->sid, dsec->sid,
2383 inode_mode_to_security_class(inode->i_mode),
2384 &newsid);
2385 if (rc) {
2386 printk(KERN_WARNING "%s: "
2387 "security_transition_sid failed, rc=%d (dev=%s "
2388 "ino=%ld)\n",
2389 __FUNCTION__,
2390 -rc, inode->i_sb->s_id, inode->i_ino);
2391 return rc;
2392 }
2393 }
2394
Eric Paris296fddf2006-09-25 23:32:00 -07002395 /* Possibly defer initialization to selinux_complete_init. */
2396 if (sbsec->initialized) {
2397 struct inode_security_struct *isec = inode->i_security;
2398 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2399 isec->sid = newsid;
2400 isec->initialized = 1;
2401 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002402
Stephen Smalley8aad3872006-03-22 00:09:13 -08002403 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002404 return -EOPNOTSUPP;
2405
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002406 if (name) {
2407 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
2408 if (!namep)
2409 return -ENOMEM;
2410 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002411 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002412
2413 if (value && len) {
2414 rc = security_sid_to_context(newsid, &context, &clen);
2415 if (rc) {
2416 kfree(namep);
2417 return rc;
2418 }
2419 *value = context;
2420 *len = clen;
2421 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002422
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002423 return 0;
2424}
2425
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2427{
2428 return may_create(dir, dentry, SECCLASS_FILE);
2429}
2430
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2432{
2433 int rc;
2434
2435 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2436 if (rc)
2437 return rc;
2438 return may_link(dir, old_dentry, MAY_LINK);
2439}
2440
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2442{
2443 int rc;
2444
2445 rc = secondary_ops->inode_unlink(dir, dentry);
2446 if (rc)
2447 return rc;
2448 return may_link(dir, dentry, MAY_UNLINK);
2449}
2450
2451static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2452{
2453 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2454}
2455
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2457{
2458 return may_create(dir, dentry, SECCLASS_DIR);
2459}
2460
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2462{
2463 return may_link(dir, dentry, MAY_RMDIR);
2464}
2465
2466static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2467{
2468 int rc;
2469
2470 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2471 if (rc)
2472 return rc;
2473
2474 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2475}
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2478 struct inode *new_inode, struct dentry *new_dentry)
2479{
2480 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2481}
2482
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483static int selinux_inode_readlink(struct dentry *dentry)
2484{
2485 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2486}
2487
2488static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2489{
2490 int rc;
2491
2492 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2493 if (rc)
2494 return rc;
2495 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2496}
2497
2498static int selinux_inode_permission(struct inode *inode, int mask,
2499 struct nameidata *nd)
2500{
2501 int rc;
2502
2503 rc = secondary_ops->inode_permission(inode, mask, nd);
2504 if (rc)
2505 return rc;
2506
2507 if (!mask) {
2508 /* No permission to check. Existence test. */
2509 return 0;
2510 }
2511
2512 return inode_has_perm(current, inode,
2513 file_mask_to_av(inode->i_mode, mask), NULL);
2514}
2515
2516static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2517{
2518 int rc;
2519
2520 rc = secondary_ops->inode_setattr(dentry, iattr);
2521 if (rc)
2522 return rc;
2523
2524 if (iattr->ia_valid & ATTR_FORCE)
2525 return 0;
2526
2527 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2528 ATTR_ATIME_SET | ATTR_MTIME_SET))
2529 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2530
2531 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2532}
2533
2534static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2535{
2536 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2537}
2538
Serge E. Hallynb5376772007-10-16 23:31:36 -07002539static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2540{
2541 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2542 sizeof XATTR_SECURITY_PREFIX - 1)) {
2543 if (!strcmp(name, XATTR_NAME_CAPS)) {
2544 if (!capable(CAP_SETFCAP))
2545 return -EPERM;
2546 } else if (!capable(CAP_SYS_ADMIN)) {
2547 /* A different attribute in the security namespace.
2548 Restrict to administrator. */
2549 return -EPERM;
2550 }
2551 }
2552
2553 /* Not an attribute we recognize, so just check the
2554 ordinary setattr permission. */
2555 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2556}
2557
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2559{
2560 struct task_security_struct *tsec = current->security;
2561 struct inode *inode = dentry->d_inode;
2562 struct inode_security_struct *isec = inode->i_security;
2563 struct superblock_security_struct *sbsec;
2564 struct avc_audit_data ad;
2565 u32 newsid;
2566 int rc = 0;
2567
Serge E. Hallynb5376772007-10-16 23:31:36 -07002568 if (strcmp(name, XATTR_NAME_SELINUX))
2569 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
2571 sbsec = inode->i_sb->s_security;
2572 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2573 return -EOPNOTSUPP;
2574
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302575 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 return -EPERM;
2577
2578 AVC_AUDIT_DATA_INIT(&ad,FS);
2579 ad.u.fs.dentry = dentry;
2580
2581 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2582 FILE__RELABELFROM, &ad);
2583 if (rc)
2584 return rc;
2585
2586 rc = security_context_to_sid(value, size, &newsid);
2587 if (rc)
2588 return rc;
2589
2590 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2591 FILE__RELABELTO, &ad);
2592 if (rc)
2593 return rc;
2594
2595 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2596 isec->sclass);
2597 if (rc)
2598 return rc;
2599
2600 return avc_has_perm(newsid,
2601 sbsec->sid,
2602 SECCLASS_FILESYSTEM,
2603 FILESYSTEM__ASSOCIATE,
2604 &ad);
2605}
2606
2607static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2608 void *value, size_t size, int flags)
2609{
2610 struct inode *inode = dentry->d_inode;
2611 struct inode_security_struct *isec = inode->i_security;
2612 u32 newsid;
2613 int rc;
2614
2615 if (strcmp(name, XATTR_NAME_SELINUX)) {
2616 /* Not an attribute we recognize, so nothing to do. */
2617 return;
2618 }
2619
2620 rc = security_context_to_sid(value, size, &newsid);
2621 if (rc) {
2622 printk(KERN_WARNING "%s: unable to obtain SID for context "
2623 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2624 return;
2625 }
2626
2627 isec->sid = newsid;
2628 return;
2629}
2630
2631static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2632{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2634}
2635
2636static int selinux_inode_listxattr (struct dentry *dentry)
2637{
2638 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2639}
2640
2641static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2642{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002643 if (strcmp(name, XATTR_NAME_SELINUX))
2644 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
2646 /* No one is allowed to remove a SELinux security label.
2647 You can change the label, but all data must be labeled. */
2648 return -EACCES;
2649}
2650
James Morrisd381d8a2005-10-30 14:59:22 -08002651/*
2652 * Copy the in-core inode security context value to the user. If the
2653 * getxattr() prior to this succeeded, check to see if we need to
2654 * canonicalize the value to be finally returned to the user.
2655 *
2656 * Permission check is handled by selinux_inode_getxattr hook.
2657 */
Dustin Kirkland7306a0b2005-11-16 15:53:13 +00002658static 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 -07002659{
2660 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002662 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2663 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002665 return selinux_getsecurity(isec->sid, buffer, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666}
2667
2668static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2669 const void *value, size_t size, int flags)
2670{
2671 struct inode_security_struct *isec = inode->i_security;
2672 u32 newsid;
2673 int rc;
2674
2675 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2676 return -EOPNOTSUPP;
2677
2678 if (!value || !size)
2679 return -EACCES;
2680
2681 rc = security_context_to_sid((void*)value, size, &newsid);
2682 if (rc)
2683 return rc;
2684
2685 isec->sid = newsid;
2686 return 0;
2687}
2688
2689static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2690{
2691 const int len = sizeof(XATTR_NAME_SELINUX);
2692 if (buffer && len <= buffer_size)
2693 memcpy(buffer, XATTR_NAME_SELINUX, len);
2694 return len;
2695}
2696
Serge E. Hallynb5376772007-10-16 23:31:36 -07002697static int selinux_inode_need_killpriv(struct dentry *dentry)
2698{
2699 return secondary_ops->inode_need_killpriv(dentry);
2700}
2701
2702static int selinux_inode_killpriv(struct dentry *dentry)
2703{
2704 return secondary_ops->inode_killpriv(dentry);
2705}
2706
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707/* file security operations */
2708
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002709static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002711 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002712 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
2714 if (!mask) {
2715 /* No permission to check. Existence test. */
2716 return 0;
2717 }
2718
2719 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2720 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2721 mask |= MAY_APPEND;
2722
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002723 rc = file_has_perm(current, file,
2724 file_mask_to_av(inode->i_mode, mask));
2725 if (rc)
2726 return rc;
2727
2728 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002731static int selinux_file_permission(struct file *file, int mask)
2732{
2733 struct inode *inode = file->f_path.dentry->d_inode;
2734 struct task_security_struct *tsec = current->security;
2735 struct file_security_struct *fsec = file->f_security;
2736 struct inode_security_struct *isec = inode->i_security;
2737
2738 if (!mask) {
2739 /* No permission to check. Existence test. */
2740 return 0;
2741 }
2742
2743 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2744 && fsec->pseqno == avc_policy_seqno())
2745 return selinux_netlbl_inode_permission(inode, mask);
2746
2747 return selinux_revalidate_file_permission(file, mask);
2748}
2749
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750static int selinux_file_alloc_security(struct file *file)
2751{
2752 return file_alloc_security(file);
2753}
2754
2755static void selinux_file_free_security(struct file *file)
2756{
2757 file_free_security(file);
2758}
2759
2760static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2761 unsigned long arg)
2762{
2763 int error = 0;
2764
2765 switch (cmd) {
2766 case FIONREAD:
2767 /* fall through */
2768 case FIBMAP:
2769 /* fall through */
2770 case FIGETBSZ:
2771 /* fall through */
2772 case EXT2_IOC_GETFLAGS:
2773 /* fall through */
2774 case EXT2_IOC_GETVERSION:
2775 error = file_has_perm(current, file, FILE__GETATTR);
2776 break;
2777
2778 case EXT2_IOC_SETFLAGS:
2779 /* fall through */
2780 case EXT2_IOC_SETVERSION:
2781 error = file_has_perm(current, file, FILE__SETATTR);
2782 break;
2783
2784 /* sys_ioctl() checks */
2785 case FIONBIO:
2786 /* fall through */
2787 case FIOASYNC:
2788 error = file_has_perm(current, file, 0);
2789 break;
2790
2791 case KDSKBENT:
2792 case KDSKBSENT:
2793 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2794 break;
2795
2796 /* default case assumes that the command will go
2797 * to the file's ioctl() function.
2798 */
2799 default:
2800 error = file_has_perm(current, file, FILE__IOCTL);
2801
2802 }
2803 return error;
2804}
2805
2806static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2807{
2808#ifndef CONFIG_PPC32
2809 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2810 /*
2811 * We are making executable an anonymous mapping or a
2812 * private file mapping that will also be writable.
2813 * This has an additional check.
2814 */
2815 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2816 if (rc)
2817 return rc;
2818 }
2819#endif
2820
2821 if (file) {
2822 /* read access is always possible with a mapping */
2823 u32 av = FILE__READ;
2824
2825 /* write access only matters if the mapping is shared */
2826 if (shared && (prot & PROT_WRITE))
2827 av |= FILE__WRITE;
2828
2829 if (prot & PROT_EXEC)
2830 av |= FILE__EXECUTE;
2831
2832 return file_has_perm(current, file, av);
2833 }
2834 return 0;
2835}
2836
2837static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002838 unsigned long prot, unsigned long flags,
2839 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
Eric Parised032182007-06-28 15:55:21 -04002841 int rc = 0;
2842 u32 sid = ((struct task_security_struct*)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
Eric Parised032182007-06-28 15:55:21 -04002844 if (addr < mmap_min_addr)
2845 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2846 MEMPROTECT__MMAP_ZERO, NULL);
2847 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 return rc;
2849
2850 if (selinux_checkreqprot)
2851 prot = reqprot;
2852
2853 return file_map_prot_check(file, prot,
2854 (flags & MAP_TYPE) == MAP_SHARED);
2855}
2856
2857static int selinux_file_mprotect(struct vm_area_struct *vma,
2858 unsigned long reqprot,
2859 unsigned long prot)
2860{
2861 int rc;
2862
2863 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2864 if (rc)
2865 return rc;
2866
2867 if (selinux_checkreqprot)
2868 prot = reqprot;
2869
2870#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002871 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2872 rc = 0;
2873 if (vma->vm_start >= vma->vm_mm->start_brk &&
2874 vma->vm_end <= vma->vm_mm->brk) {
2875 rc = task_has_perm(current, current,
2876 PROCESS__EXECHEAP);
2877 } else if (!vma->vm_file &&
2878 vma->vm_start <= vma->vm_mm->start_stack &&
2879 vma->vm_end >= vma->vm_mm->start_stack) {
2880 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2881 } else if (vma->vm_file && vma->anon_vma) {
2882 /*
2883 * We are making executable a file mapping that has
2884 * had some COW done. Since pages might have been
2885 * written, check ability to execute the possibly
2886 * modified content. This typically should only
2887 * occur for text relocations.
2888 */
2889 rc = file_has_perm(current, vma->vm_file,
2890 FILE__EXECMOD);
2891 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002892 if (rc)
2893 return rc;
2894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895#endif
2896
2897 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2898}
2899
2900static int selinux_file_lock(struct file *file, unsigned int cmd)
2901{
2902 return file_has_perm(current, file, FILE__LOCK);
2903}
2904
2905static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2906 unsigned long arg)
2907{
2908 int err = 0;
2909
2910 switch (cmd) {
2911 case F_SETFL:
Josef Sipek3d5ff522006-12-08 02:37:38 -08002912 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 err = -EINVAL;
2914 break;
2915 }
2916
2917 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2918 err = file_has_perm(current, file,FILE__WRITE);
2919 break;
2920 }
2921 /* fall through */
2922 case F_SETOWN:
2923 case F_SETSIG:
2924 case F_GETFL:
2925 case F_GETOWN:
2926 case F_GETSIG:
2927 /* Just check FD__USE permission */
2928 err = file_has_perm(current, file, 0);
2929 break;
2930 case F_GETLK:
2931 case F_SETLK:
2932 case F_SETLKW:
2933#if BITS_PER_LONG == 32
2934 case F_GETLK64:
2935 case F_SETLK64:
2936 case F_SETLKW64:
2937#endif
Josef Sipek3d5ff522006-12-08 02:37:38 -08002938 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 err = -EINVAL;
2940 break;
2941 }
2942 err = file_has_perm(current, file, FILE__LOCK);
2943 break;
2944 }
2945
2946 return err;
2947}
2948
2949static int selinux_file_set_fowner(struct file *file)
2950{
2951 struct task_security_struct *tsec;
2952 struct file_security_struct *fsec;
2953
2954 tsec = current->security;
2955 fsec = file->f_security;
2956 fsec->fown_sid = tsec->sid;
2957
2958 return 0;
2959}
2960
2961static int selinux_file_send_sigiotask(struct task_struct *tsk,
2962 struct fown_struct *fown, int signum)
2963{
2964 struct file *file;
2965 u32 perm;
2966 struct task_security_struct *tsec;
2967 struct file_security_struct *fsec;
2968
2969 /* struct fown_struct is never outside the context of a struct file */
Robert P. J. Dayb385a142007-02-10 01:46:25 -08002970 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
2972 tsec = tsk->security;
2973 fsec = file->f_security;
2974
2975 if (!signum)
2976 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
2977 else
2978 perm = signal_to_av(signum);
2979
2980 return avc_has_perm(fsec->fown_sid, tsec->sid,
2981 SECCLASS_PROCESS, perm, NULL);
2982}
2983
2984static int selinux_file_receive(struct file *file)
2985{
2986 return file_has_perm(current, file, file_to_av(file));
2987}
2988
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002989static int selinux_dentry_open(struct file *file)
2990{
2991 struct file_security_struct *fsec;
2992 struct inode *inode;
2993 struct inode_security_struct *isec;
2994 inode = file->f_path.dentry->d_inode;
2995 fsec = file->f_security;
2996 isec = inode->i_security;
2997 /*
2998 * Save inode label and policy sequence number
2999 * at open-time so that selinux_file_permission
3000 * can determine whether revalidation is necessary.
3001 * Task label is already saved in the file security
3002 * struct as its SID.
3003 */
3004 fsec->isid = isec->sid;
3005 fsec->pseqno = avc_policy_seqno();
3006 /*
3007 * Since the inode label or policy seqno may have changed
3008 * between the selinux_inode_permission check and the saving
3009 * of state above, recheck that access is still permitted.
3010 * Otherwise, access might never be revalidated against the
3011 * new inode label or new policy.
3012 * This check is not redundant - do not remove.
3013 */
3014 return inode_has_perm(current, inode, file_to_av(file), NULL);
3015}
3016
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017/* task security operations */
3018
3019static int selinux_task_create(unsigned long clone_flags)
3020{
3021 int rc;
3022
3023 rc = secondary_ops->task_create(clone_flags);
3024 if (rc)
3025 return rc;
3026
3027 return task_has_perm(current, current, PROCESS__FORK);
3028}
3029
3030static int selinux_task_alloc_security(struct task_struct *tsk)
3031{
3032 struct task_security_struct *tsec1, *tsec2;
3033 int rc;
3034
3035 tsec1 = current->security;
3036
3037 rc = task_alloc_security(tsk);
3038 if (rc)
3039 return rc;
3040 tsec2 = tsk->security;
3041
3042 tsec2->osid = tsec1->osid;
3043 tsec2->sid = tsec1->sid;
3044
Michael LeMay28eba5b2006-06-27 02:53:42 -07003045 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 tsec2->exec_sid = tsec1->exec_sid;
3047 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003048 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003049 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
3051 /* Retain ptracer SID across fork, if any.
3052 This will be reset by the ptrace hook upon any
3053 subsequent ptrace_attach operations. */
3054 tsec2->ptrace_sid = tsec1->ptrace_sid;
3055
3056 return 0;
3057}
3058
3059static void selinux_task_free_security(struct task_struct *tsk)
3060{
3061 task_free_security(tsk);
3062}
3063
3064static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3065{
3066 /* Since setuid only affects the current process, and
3067 since the SELinux controls are not based on the Linux
3068 identity attributes, SELinux does not need to control
3069 this operation. However, SELinux does control the use
3070 of the CAP_SETUID and CAP_SETGID capabilities using the
3071 capable hook. */
3072 return 0;
3073}
3074
3075static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3076{
3077 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
3078}
3079
3080static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3081{
3082 /* See the comment for setuid above. */
3083 return 0;
3084}
3085
3086static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3087{
3088 return task_has_perm(current, p, PROCESS__SETPGID);
3089}
3090
3091static int selinux_task_getpgid(struct task_struct *p)
3092{
3093 return task_has_perm(current, p, PROCESS__GETPGID);
3094}
3095
3096static int selinux_task_getsid(struct task_struct *p)
3097{
3098 return task_has_perm(current, p, PROCESS__GETSESSION);
3099}
3100
David Quigleyf9008e42006-06-30 01:55:46 -07003101static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3102{
3103 selinux_get_task_sid(p, secid);
3104}
3105
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106static int selinux_task_setgroups(struct group_info *group_info)
3107{
3108 /* See the comment for setuid above. */
3109 return 0;
3110}
3111
3112static int selinux_task_setnice(struct task_struct *p, int nice)
3113{
3114 int rc;
3115
3116 rc = secondary_ops->task_setnice(p, nice);
3117 if (rc)
3118 return rc;
3119
3120 return task_has_perm(current,p, PROCESS__SETSCHED);
3121}
3122
James Morris03e68062006-06-23 02:03:58 -07003123static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3124{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003125 int rc;
3126
3127 rc = secondary_ops->task_setioprio(p, ioprio);
3128 if (rc)
3129 return rc;
3130
James Morris03e68062006-06-23 02:03:58 -07003131 return task_has_perm(current, p, PROCESS__SETSCHED);
3132}
3133
David Quigleya1836a42006-06-30 01:55:49 -07003134static int selinux_task_getioprio(struct task_struct *p)
3135{
3136 return task_has_perm(current, p, PROCESS__GETSCHED);
3137}
3138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3140{
3141 struct rlimit *old_rlim = current->signal->rlim + resource;
3142 int rc;
3143
3144 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3145 if (rc)
3146 return rc;
3147
3148 /* Control the ability to change the hard limit (whether
3149 lowering or raising it), so that the hard limit can
3150 later be used as a safe reset point for the soft limit
3151 upon context transitions. See selinux_bprm_apply_creds. */
3152 if (old_rlim->rlim_max != new_rlim->rlim_max)
3153 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3154
3155 return 0;
3156}
3157
3158static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3159{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003160 int rc;
3161
3162 rc = secondary_ops->task_setscheduler(p, policy, lp);
3163 if (rc)
3164 return rc;
3165
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 return task_has_perm(current, p, PROCESS__SETSCHED);
3167}
3168
3169static int selinux_task_getscheduler(struct task_struct *p)
3170{
3171 return task_has_perm(current, p, PROCESS__GETSCHED);
3172}
3173
David Quigley35601542006-06-23 02:04:01 -07003174static int selinux_task_movememory(struct task_struct *p)
3175{
3176 return task_has_perm(current, p, PROCESS__SETSCHED);
3177}
3178
David Quigleyf9008e42006-06-30 01:55:46 -07003179static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3180 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181{
3182 u32 perm;
3183 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003184 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
David Quigleyf9008e42006-06-30 01:55:46 -07003186 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 if (rc)
3188 return rc;
3189
Oleg Nesterov621d3122005-10-30 15:03:45 -08003190 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 return 0;
3192
3193 if (!sig)
3194 perm = PROCESS__SIGNULL; /* null signal; existence test */
3195 else
3196 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003197 tsec = p->security;
3198 if (secid)
3199 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3200 else
3201 rc = task_has_perm(current, p, perm);
3202 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203}
3204
3205static int selinux_task_prctl(int option,
3206 unsigned long arg2,
3207 unsigned long arg3,
3208 unsigned long arg4,
3209 unsigned long arg5)
3210{
3211 /* The current prctl operations do not appear to require
3212 any SELinux controls since they merely observe or modify
3213 the state of the current process. */
3214 return 0;
3215}
3216
3217static int selinux_task_wait(struct task_struct *p)
3218{
Eric Paris8a535142007-10-22 16:10:31 -04003219 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220}
3221
3222static void selinux_task_reparent_to_init(struct task_struct *p)
3223{
3224 struct task_security_struct *tsec;
3225
3226 secondary_ops->task_reparent_to_init(p);
3227
3228 tsec = p->security;
3229 tsec->osid = tsec->sid;
3230 tsec->sid = SECINITSID_KERNEL;
3231 return;
3232}
3233
3234static void selinux_task_to_inode(struct task_struct *p,
3235 struct inode *inode)
3236{
3237 struct task_security_struct *tsec = p->security;
3238 struct inode_security_struct *isec = inode->i_security;
3239
3240 isec->sid = tsec->sid;
3241 isec->initialized = 1;
3242 return;
3243}
3244
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003246static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3247 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248{
3249 int offset, ihlen, ret = -EINVAL;
3250 struct iphdr _iph, *ih;
3251
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003252 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3254 if (ih == NULL)
3255 goto out;
3256
3257 ihlen = ih->ihl * 4;
3258 if (ihlen < sizeof(_iph))
3259 goto out;
3260
3261 ad->u.net.v4info.saddr = ih->saddr;
3262 ad->u.net.v4info.daddr = ih->daddr;
3263 ret = 0;
3264
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003265 if (proto)
3266 *proto = ih->protocol;
3267
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 switch (ih->protocol) {
3269 case IPPROTO_TCP: {
3270 struct tcphdr _tcph, *th;
3271
3272 if (ntohs(ih->frag_off) & IP_OFFSET)
3273 break;
3274
3275 offset += ihlen;
3276 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3277 if (th == NULL)
3278 break;
3279
3280 ad->u.net.sport = th->source;
3281 ad->u.net.dport = th->dest;
3282 break;
3283 }
3284
3285 case IPPROTO_UDP: {
3286 struct udphdr _udph, *uh;
3287
3288 if (ntohs(ih->frag_off) & IP_OFFSET)
3289 break;
3290
3291 offset += ihlen;
3292 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3293 if (uh == NULL)
3294 break;
3295
3296 ad->u.net.sport = uh->source;
3297 ad->u.net.dport = uh->dest;
3298 break;
3299 }
3300
James Morris2ee92d42006-11-13 16:09:01 -08003301 case IPPROTO_DCCP: {
3302 struct dccp_hdr _dccph, *dh;
3303
3304 if (ntohs(ih->frag_off) & IP_OFFSET)
3305 break;
3306
3307 offset += ihlen;
3308 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3309 if (dh == NULL)
3310 break;
3311
3312 ad->u.net.sport = dh->dccph_sport;
3313 ad->u.net.dport = dh->dccph_dport;
3314 break;
3315 }
3316
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 default:
3318 break;
3319 }
3320out:
3321 return ret;
3322}
3323
3324#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3325
3326/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003327static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3328 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329{
3330 u8 nexthdr;
3331 int ret = -EINVAL, offset;
3332 struct ipv6hdr _ipv6h, *ip6;
3333
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003334 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3336 if (ip6 == NULL)
3337 goto out;
3338
3339 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3340 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3341 ret = 0;
3342
3343 nexthdr = ip6->nexthdr;
3344 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003345 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 if (offset < 0)
3347 goto out;
3348
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003349 if (proto)
3350 *proto = nexthdr;
3351
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 switch (nexthdr) {
3353 case IPPROTO_TCP: {
3354 struct tcphdr _tcph, *th;
3355
3356 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3357 if (th == NULL)
3358 break;
3359
3360 ad->u.net.sport = th->source;
3361 ad->u.net.dport = th->dest;
3362 break;
3363 }
3364
3365 case IPPROTO_UDP: {
3366 struct udphdr _udph, *uh;
3367
3368 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3369 if (uh == NULL)
3370 break;
3371
3372 ad->u.net.sport = uh->source;
3373 ad->u.net.dport = uh->dest;
3374 break;
3375 }
3376
James Morris2ee92d42006-11-13 16:09:01 -08003377 case IPPROTO_DCCP: {
3378 struct dccp_hdr _dccph, *dh;
3379
3380 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3381 if (dh == NULL)
3382 break;
3383
3384 ad->u.net.sport = dh->dccph_sport;
3385 ad->u.net.dport = dh->dccph_dport;
3386 break;
3387 }
3388
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 /* includes fragments */
3390 default:
3391 break;
3392 }
3393out:
3394 return ret;
3395}
3396
3397#endif /* IPV6 */
3398
3399static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003400 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
3402 int ret = 0;
3403
3404 switch (ad->u.net.family) {
3405 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003406 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 if (ret || !addrp)
3408 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3410 &ad->u.net.v4info.daddr);
3411 break;
3412
3413#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3414 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003415 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 if (ret || !addrp)
3417 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3419 &ad->u.net.v6info.daddr);
3420 break;
3421#endif /* IPV6 */
3422 default:
3423 break;
3424 }
3425
3426 return ret;
3427}
3428
Paul Moore4f6a9932007-03-01 14:35:22 -05003429/**
Paul Moore220deb92008-01-29 08:38:23 -05003430 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003431 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003432 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003433 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003434 *
3435 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003436 * Check the various different forms of network peer labeling and determine
3437 * the peer label/SID for the packet; most of the magic actually occurs in
3438 * the security server function security_net_peersid_cmp(). The function
3439 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3440 * or -EACCES if @sid is invalid due to inconsistencies with the different
3441 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003442 *
3443 */
Paul Moore220deb92008-01-29 08:38:23 -05003444static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003445{
3446 u32 xfrm_sid;
3447 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003448 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003449
3450 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003451 selinux_netlbl_skbuff_getsid(skb,
3452 family,
3453 SECINITSID_NETMSG,
3454 &nlbl_type,
3455 &nlbl_sid);
3456
3457 if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
3458 xfrm_sid,
3459 sid) != 0)
3460 return -EACCES;
3461
3462 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003463}
3464
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465/* socket security operations */
3466static int socket_has_perm(struct task_struct *task, struct socket *sock,
3467 u32 perms)
3468{
3469 struct inode_security_struct *isec;
3470 struct task_security_struct *tsec;
3471 struct avc_audit_data ad;
3472 int err = 0;
3473
3474 tsec = task->security;
3475 isec = SOCK_INODE(sock)->i_security;
3476
3477 if (isec->sid == SECINITSID_KERNEL)
3478 goto out;
3479
3480 AVC_AUDIT_DATA_INIT(&ad,NET);
3481 ad.u.net.sk = sock->sk;
3482 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3483
3484out:
3485 return err;
3486}
3487
3488static int selinux_socket_create(int family, int type,
3489 int protocol, int kern)
3490{
3491 int err = 0;
3492 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003493 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
3495 if (kern)
3496 goto out;
3497
3498 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003499 newsid = tsec->sockcreate_sid ? : tsec->sid;
3500 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 socket_type_to_security_class(family, type,
3502 protocol), SOCKET__CREATE, NULL);
3503
3504out:
3505 return err;
3506}
3507
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003508static int selinux_socket_post_create(struct socket *sock, int family,
3509 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003511 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 struct inode_security_struct *isec;
3513 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003514 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003515 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
3517 isec = SOCK_INODE(sock)->i_security;
3518
3519 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003520 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003522 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 isec->initialized = 1;
3524
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003525 if (sock->sk) {
3526 sksec = sock->sk->sk_security;
3527 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003528 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003529 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003530 }
3531
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003532 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533}
3534
3535/* Range of port numbers used to automatically bind.
3536 Need to determine whether we should perform a name_bind
3537 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
3539static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3540{
3541 u16 family;
3542 int err;
3543
3544 err = socket_has_perm(current, sock, SOCKET__BIND);
3545 if (err)
3546 goto out;
3547
3548 /*
3549 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003550 * Multiple address binding for SCTP is not supported yet: we just
3551 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 */
3553 family = sock->sk->sk_family;
3554 if (family == PF_INET || family == PF_INET6) {
3555 char *addrp;
3556 struct inode_security_struct *isec;
3557 struct task_security_struct *tsec;
3558 struct avc_audit_data ad;
3559 struct sockaddr_in *addr4 = NULL;
3560 struct sockaddr_in6 *addr6 = NULL;
3561 unsigned short snum;
3562 struct sock *sk = sock->sk;
3563 u32 sid, node_perm, addrlen;
3564
3565 tsec = current->security;
3566 isec = SOCK_INODE(sock)->i_security;
3567
3568 if (family == PF_INET) {
3569 addr4 = (struct sockaddr_in *)address;
3570 snum = ntohs(addr4->sin_port);
3571 addrlen = sizeof(addr4->sin_addr.s_addr);
3572 addrp = (char *)&addr4->sin_addr.s_addr;
3573 } else {
3574 addr6 = (struct sockaddr_in6 *)address;
3575 snum = ntohs(addr6->sin6_port);
3576 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3577 addrp = (char *)&addr6->sin6_addr.s6_addr;
3578 }
3579
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003580 if (snum) {
3581 int low, high;
3582
3583 inet_get_local_port_range(&low, &high);
3584
3585 if (snum < max(PROT_SOCK, low) || snum > high) {
3586 err = security_port_sid(sk->sk_family,
3587 sk->sk_type,
3588 sk->sk_protocol, snum,
3589 &sid);
3590 if (err)
3591 goto out;
3592 AVC_AUDIT_DATA_INIT(&ad,NET);
3593 ad.u.net.sport = htons(snum);
3594 ad.u.net.family = family;
3595 err = avc_has_perm(isec->sid, sid,
3596 isec->sclass,
3597 SOCKET__NAME_BIND, &ad);
3598 if (err)
3599 goto out;
3600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 }
3602
James Morris13402582005-09-30 14:24:34 -04003603 switch(isec->sclass) {
3604 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 node_perm = TCP_SOCKET__NODE_BIND;
3606 break;
3607
James Morris13402582005-09-30 14:24:34 -04003608 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 node_perm = UDP_SOCKET__NODE_BIND;
3610 break;
James Morris2ee92d42006-11-13 16:09:01 -08003611
3612 case SECCLASS_DCCP_SOCKET:
3613 node_perm = DCCP_SOCKET__NODE_BIND;
3614 break;
3615
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 default:
3617 node_perm = RAWIP_SOCKET__NODE_BIND;
3618 break;
3619 }
3620
Paul Moore224dfbd2008-01-29 08:38:13 -05003621 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 if (err)
3623 goto out;
3624
3625 AVC_AUDIT_DATA_INIT(&ad,NET);
3626 ad.u.net.sport = htons(snum);
3627 ad.u.net.family = family;
3628
3629 if (family == PF_INET)
3630 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3631 else
3632 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3633
3634 err = avc_has_perm(isec->sid, sid,
3635 isec->sclass, node_perm, &ad);
3636 if (err)
3637 goto out;
3638 }
3639out:
3640 return err;
3641}
3642
3643static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3644{
3645 struct inode_security_struct *isec;
3646 int err;
3647
3648 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3649 if (err)
3650 return err;
3651
3652 /*
James Morris2ee92d42006-11-13 16:09:01 -08003653 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 */
3655 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003656 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3657 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 struct sock *sk = sock->sk;
3659 struct avc_audit_data ad;
3660 struct sockaddr_in *addr4 = NULL;
3661 struct sockaddr_in6 *addr6 = NULL;
3662 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003663 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664
3665 if (sk->sk_family == PF_INET) {
3666 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003667 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668 return -EINVAL;
3669 snum = ntohs(addr4->sin_port);
3670 } else {
3671 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003672 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 return -EINVAL;
3674 snum = ntohs(addr6->sin6_port);
3675 }
3676
3677 err = security_port_sid(sk->sk_family, sk->sk_type,
3678 sk->sk_protocol, snum, &sid);
3679 if (err)
3680 goto out;
3681
James Morris2ee92d42006-11-13 16:09:01 -08003682 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3683 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3684
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 AVC_AUDIT_DATA_INIT(&ad,NET);
3686 ad.u.net.dport = htons(snum);
3687 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003688 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 if (err)
3690 goto out;
3691 }
3692
3693out:
3694 return err;
3695}
3696
3697static int selinux_socket_listen(struct socket *sock, int backlog)
3698{
3699 return socket_has_perm(current, sock, SOCKET__LISTEN);
3700}
3701
3702static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3703{
3704 int err;
3705 struct inode_security_struct *isec;
3706 struct inode_security_struct *newisec;
3707
3708 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3709 if (err)
3710 return err;
3711
3712 newisec = SOCK_INODE(newsock)->i_security;
3713
3714 isec = SOCK_INODE(sock)->i_security;
3715 newisec->sclass = isec->sclass;
3716 newisec->sid = isec->sid;
3717 newisec->initialized = 1;
3718
3719 return 0;
3720}
3721
3722static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3723 int size)
3724{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003725 int rc;
3726
3727 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3728 if (rc)
3729 return rc;
3730
3731 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732}
3733
3734static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3735 int size, int flags)
3736{
3737 return socket_has_perm(current, sock, SOCKET__READ);
3738}
3739
3740static int selinux_socket_getsockname(struct socket *sock)
3741{
3742 return socket_has_perm(current, sock, SOCKET__GETATTR);
3743}
3744
3745static int selinux_socket_getpeername(struct socket *sock)
3746{
3747 return socket_has_perm(current, sock, SOCKET__GETATTR);
3748}
3749
3750static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3751{
Paul Mooref8687af2006-10-30 15:22:15 -08003752 int err;
3753
3754 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3755 if (err)
3756 return err;
3757
3758 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759}
3760
3761static int selinux_socket_getsockopt(struct socket *sock, int level,
3762 int optname)
3763{
3764 return socket_has_perm(current, sock, SOCKET__GETOPT);
3765}
3766
3767static int selinux_socket_shutdown(struct socket *sock, int how)
3768{
3769 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3770}
3771
3772static int selinux_socket_unix_stream_connect(struct socket *sock,
3773 struct socket *other,
3774 struct sock *newsk)
3775{
3776 struct sk_security_struct *ssec;
3777 struct inode_security_struct *isec;
3778 struct inode_security_struct *other_isec;
3779 struct avc_audit_data ad;
3780 int err;
3781
3782 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3783 if (err)
3784 return err;
3785
3786 isec = SOCK_INODE(sock)->i_security;
3787 other_isec = SOCK_INODE(other)->i_security;
3788
3789 AVC_AUDIT_DATA_INIT(&ad,NET);
3790 ad.u.net.sk = other->sk;
3791
3792 err = avc_has_perm(isec->sid, other_isec->sid,
3793 isec->sclass,
3794 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3795 if (err)
3796 return err;
3797
3798 /* connecting socket */
3799 ssec = sock->sk->sk_security;
3800 ssec->peer_sid = other_isec->sid;
3801
3802 /* server child socket */
3803 ssec = newsk->sk_security;
3804 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003805 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3806
3807 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808}
3809
3810static int selinux_socket_unix_may_send(struct socket *sock,
3811 struct socket *other)
3812{
3813 struct inode_security_struct *isec;
3814 struct inode_security_struct *other_isec;
3815 struct avc_audit_data ad;
3816 int err;
3817
3818 isec = SOCK_INODE(sock)->i_security;
3819 other_isec = SOCK_INODE(other)->i_security;
3820
3821 AVC_AUDIT_DATA_INIT(&ad,NET);
3822 ad.u.net.sk = other->sk;
3823
3824 err = avc_has_perm(isec->sid, other_isec->sid,
3825 isec->sclass, SOCKET__SENDTO, &ad);
3826 if (err)
3827 return err;
3828
3829 return 0;
3830}
3831
Paul Moore220deb92008-01-29 08:38:23 -05003832static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3833 struct sk_buff *skb,
3834 struct avc_audit_data *ad,
3835 u16 family,
3836 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
Paul Moore220deb92008-01-29 08:38:23 -05003838 int err;
3839 struct sk_security_struct *sksec = sk->sk_security;
3840 u16 sk_class;
3841 u32 netif_perm, node_perm, recv_perm;
3842 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003843
Paul Moore220deb92008-01-29 08:38:23 -05003844 sk_sid = sksec->sid;
3845 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Paul Moore220deb92008-01-29 08:38:23 -05003847 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 case SECCLASS_UDP_SOCKET:
3849 netif_perm = NETIF__UDP_RECV;
3850 node_perm = NODE__UDP_RECV;
3851 recv_perm = UDP_SOCKET__RECV_MSG;
3852 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 case SECCLASS_TCP_SOCKET:
3854 netif_perm = NETIF__TCP_RECV;
3855 node_perm = NODE__TCP_RECV;
3856 recv_perm = TCP_SOCKET__RECV_MSG;
3857 break;
James Morris2ee92d42006-11-13 16:09:01 -08003858 case SECCLASS_DCCP_SOCKET:
3859 netif_perm = NETIF__DCCP_RECV;
3860 node_perm = NODE__DCCP_RECV;
3861 recv_perm = DCCP_SOCKET__RECV_MSG;
3862 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 default:
3864 netif_perm = NETIF__RAWIP_RECV;
3865 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003866 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 break;
3868 }
3869
Paul Moore220deb92008-01-29 08:38:23 -05003870 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003872 return err;
3873 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3874 if (err)
3875 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
Paul Moore224dfbd2008-01-29 08:38:13 -05003877 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003879 return err;
3880 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003882 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Paul Moore220deb92008-01-29 08:38:23 -05003884 if (!recv_perm)
3885 return 0;
3886 err = security_port_sid(sk->sk_family, sk->sk_type,
3887 sk->sk_protocol, ntohs(ad->u.net.sport),
3888 &port_sid);
3889 if (err)
3890 return err;
3891 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3892}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893
Paul Moore220deb92008-01-29 08:38:23 -05003894static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3895 struct avc_audit_data *ad,
3896 u16 family, char *addrp)
3897{
3898 int err;
3899 struct sk_security_struct *sksec = sk->sk_security;
3900 u32 peer_sid;
3901 u32 sk_sid = sksec->sid;
3902
3903 if (selinux_compat_net)
3904 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3905 family, addrp);
3906 else
3907 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3908 PACKET__RECV, ad);
3909 if (err)
3910 return err;
3911
3912 if (selinux_policycap_netpeer) {
3913 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003915 return err;
3916 err = avc_has_perm(sk_sid, peer_sid,
3917 SECCLASS_PEER, PEER__RECV, ad);
3918 } else {
3919 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3920 if (err)
3921 return err;
3922 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003924
James Morris4e5ab4c2006-06-09 00:33:33 -07003925 return err;
3926}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08003927
James Morris4e5ab4c2006-06-09 00:33:33 -07003928static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3929{
Paul Moore220deb92008-01-29 08:38:23 -05003930 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003931 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05003932 u16 family = sk->sk_family;
3933 u32 sk_sid = sksec->sid;
3934 u32 peer_sid;
3935 struct avc_audit_data ad;
3936 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07003937
James Morris4e5ab4c2006-06-09 00:33:33 -07003938 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05003939 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07003940
3941 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00003942 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07003943 family = PF_INET;
3944
James Morris4e5ab4c2006-06-09 00:33:33 -07003945 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05003946 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07003947 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05003948 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07003949 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003950 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07003951
Paul Moore220deb92008-01-29 08:38:23 -05003952 /* If any sort of compatibility mode is enabled then handoff processing
3953 * to the selinux_sock_rcv_skb_compat() function to deal with the
3954 * special handling. We do this in an attempt to keep this function
3955 * as fast and as clean as possible. */
3956 if (selinux_compat_net || !selinux_policycap_netpeer)
3957 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3958 family, addrp);
3959
3960 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3961 PACKET__RECV, &ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07003962 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003963 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07003964
Paul Moore220deb92008-01-29 08:38:23 -05003965 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003966 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003967 return err;
3968 return avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969}
3970
Catherine Zhang2c7946a2006-03-20 22:41:23 -08003971static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
3972 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973{
3974 int err = 0;
3975 char *scontext;
3976 u32 scontext_len;
3977 struct sk_security_struct *ssec;
3978 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05003979 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980
3981 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08003982
Paul Moore3de4bab2006-11-17 17:38:54 -05003983 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
3984 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08003985 ssec = sock->sk->sk_security;
3986 peer_sid = ssec->peer_sid;
3987 }
Paul Moore3de4bab2006-11-17 17:38:54 -05003988 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 err = -ENOPROTOOPT;
3990 goto out;
3991 }
3992
Catherine Zhang2c7946a2006-03-20 22:41:23 -08003993 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
3994
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 if (err)
3996 goto out;
3997
3998 if (scontext_len > len) {
3999 err = -ERANGE;
4000 goto out_len;
4001 }
4002
4003 if (copy_to_user(optval, scontext, scontext_len))
4004 err = -EFAULT;
4005
4006out_len:
4007 if (put_user(scontext_len, optlen))
4008 err = -EFAULT;
4009
4010 kfree(scontext);
4011out:
4012 return err;
4013}
4014
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004015static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004016{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004017 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004018 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004019
Paul Moore75e22912008-01-29 08:38:04 -05004020 if (sock)
4021 family = sock->sk->sk_family;
4022 else if (skb && skb->sk)
4023 family = skb->sk->sk_family;
4024 else
4025 goto out;
4026
4027 if (sock && family == PF_UNIX)
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004028 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004029 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004030 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004031
Paul Moore75e22912008-01-29 08:38:04 -05004032out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004033 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004034 if (peer_secid == SECSID_NULL)
4035 return -EINVAL;
4036 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004037}
4038
Al Viro7d877f32005-10-21 03:20:43 -04004039static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040{
4041 return sk_alloc_security(sk, family, priority);
4042}
4043
4044static void selinux_sk_free_security(struct sock *sk)
4045{
4046 sk_free_security(sk);
4047}
4048
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004049static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4050{
4051 struct sk_security_struct *ssec = sk->sk_security;
4052 struct sk_security_struct *newssec = newsk->sk_security;
4053
4054 newssec->sid = ssec->sid;
4055 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004056 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004057
Paul Moore9f2ad662006-11-17 17:38:53 -05004058 selinux_netlbl_sk_security_clone(ssec, newssec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004059}
4060
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004061static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004062{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004063 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004064 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004065 else {
4066 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004067
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004068 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004069 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004070}
4071
Adrian Bunk9a673e52006-08-15 00:03:53 -07004072static void selinux_sock_graft(struct sock* sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004073{
4074 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4075 struct sk_security_struct *sksec = sk->sk_security;
4076
David Woodhouse2148ccc2006-09-29 15:50:25 -07004077 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4078 sk->sk_family == PF_UNIX)
4079 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004080 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004081
4082 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004083}
4084
Adrian Bunk9a673e52006-08-15 00:03:53 -07004085static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4086 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004087{
4088 struct sk_security_struct *sksec = sk->sk_security;
4089 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004090 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004091 u32 peersid;
4092
Paul Moore220deb92008-01-29 08:38:23 -05004093 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4094 if (err)
4095 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004096 if (peersid == SECSID_NULL) {
4097 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004098 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004099 return 0;
4100 }
4101
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004102 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4103 if (err)
4104 return err;
4105
4106 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004107 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004108 return 0;
4109}
4110
Adrian Bunk9a673e52006-08-15 00:03:53 -07004111static void selinux_inet_csk_clone(struct sock *newsk,
4112 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004113{
4114 struct sk_security_struct *newsksec = newsk->sk_security;
4115
4116 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004117 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004118 /* NOTE: Ideally, we should also get the isec->sid for the
4119 new socket in sync, but we don't have the isec available yet.
4120 So we will wait until sock_graft to do it, by which
4121 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004122
Paul Moore9f2ad662006-11-17 17:38:53 -05004123 /* We don't need to take any sort of lock here as we are the only
4124 * thread with access to newsksec */
4125 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004126}
4127
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004128static void selinux_inet_conn_established(struct sock *sk,
4129 struct sk_buff *skb)
4130{
4131 struct sk_security_struct *sksec = sk->sk_security;
4132
Paul Moore220deb92008-01-29 08:38:23 -05004133 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004134}
4135
Adrian Bunk9a673e52006-08-15 00:03:53 -07004136static void selinux_req_classify_flow(const struct request_sock *req,
4137 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004138{
4139 fl->secid = req->secid;
4140}
4141
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4143{
4144 int err = 0;
4145 u32 perm;
4146 struct nlmsghdr *nlh;
4147 struct socket *sock = sk->sk_socket;
4148 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4149
4150 if (skb->len < NLMSG_SPACE(0)) {
4151 err = -EINVAL;
4152 goto out;
4153 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004154 nlh = nlmsg_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
4156 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4157 if (err) {
4158 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004159 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 "SELinux: unrecognized netlink message"
4161 " type=%hu for sclass=%hu\n",
4162 nlh->nlmsg_type, isec->sclass);
4163 if (!selinux_enforcing)
4164 err = 0;
4165 }
4166
4167 /* Ignore */
4168 if (err == -ENOENT)
4169 err = 0;
4170 goto out;
4171 }
4172
4173 err = socket_has_perm(current, sock, perm);
4174out:
4175 return err;
4176}
4177
4178#ifdef CONFIG_NETFILTER
4179
Paul Moore224dfbd2008-01-29 08:38:13 -05004180static int selinux_ip_postroute_last_compat(struct sock *sk,
4181 struct net_device *dev,
James Morris4e5ab4c2006-06-09 00:33:33 -07004182 struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05004183 u16 family,
4184 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185{
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004186 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004188 struct socket *sock;
4189 struct inode *inode;
4190 struct inode_security_struct *isec;
4191
4192 sock = sk->sk_socket;
4193 if (!sock)
4194 goto out;
4195
4196 inode = SOCK_INODE(sock);
4197 if (!inode)
4198 goto out;
4199
4200 isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
Paul Mooree8bfdb92008-01-29 08:38:08 -05004202 err = sel_netif_sid(dev->ifindex, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 if (err)
4204 goto out;
4205
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 switch (isec->sclass) {
4207 case SECCLASS_UDP_SOCKET:
4208 netif_perm = NETIF__UDP_SEND;
4209 node_perm = NODE__UDP_SEND;
4210 send_perm = UDP_SOCKET__SEND_MSG;
4211 break;
4212
4213 case SECCLASS_TCP_SOCKET:
4214 netif_perm = NETIF__TCP_SEND;
4215 node_perm = NODE__TCP_SEND;
4216 send_perm = TCP_SOCKET__SEND_MSG;
4217 break;
James Morris2ee92d42006-11-13 16:09:01 -08004218
4219 case SECCLASS_DCCP_SOCKET:
4220 netif_perm = NETIF__DCCP_SEND;
4221 node_perm = NODE__DCCP_SEND;
4222 send_perm = DCCP_SOCKET__SEND_MSG;
4223 break;
4224
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 default:
4226 netif_perm = NETIF__RAWIP_SEND;
4227 node_perm = NODE__RAWIP_SEND;
4228 break;
4229 }
4230
James Morris4e5ab4c2006-06-09 00:33:33 -07004231 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4232 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 goto out;
4234
Paul Moore224dfbd2008-01-29 08:38:13 -05004235 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004236 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 goto out;
4238
James Morris4e5ab4c2006-06-09 00:33:33 -07004239 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
4240 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241 goto out;
4242
4243 if (send_perm) {
4244 u32 port_sid;
4245
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 err = security_port_sid(sk->sk_family,
4247 sk->sk_type,
4248 sk->sk_protocol,
James Morris4e5ab4c2006-06-09 00:33:33 -07004249 ntohs(ad->u.net.dport),
4250 &port_sid);
4251 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 goto out;
4253
4254 err = avc_has_perm(isec->sid, port_sid, isec->sclass,
James Morris4e5ab4c2006-06-09 00:33:33 -07004255 send_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004257out:
4258 return err;
4259}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
James Morris4e5ab4c2006-06-09 00:33:33 -07004261static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
David S. Millera224be72007-10-15 02:58:25 -07004262 struct sk_buff *skb,
James Morris4e5ab4c2006-06-09 00:33:33 -07004263 const struct net_device *in,
4264 const struct net_device *out,
4265 int (*okfn)(struct sk_buff *),
4266 u16 family)
4267{
4268 char *addrp;
Paul Moore224dfbd2008-01-29 08:38:13 -05004269 int err = 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004270 struct sock *sk;
James Morris4e5ab4c2006-06-09 00:33:33 -07004271 struct avc_audit_data ad;
4272 struct net_device *dev = (struct net_device *)out;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004273 struct sk_security_struct *sksec;
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004274 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004275
4276 sk = skb->sk;
4277 if (!sk)
4278 goto out;
4279
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004280 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004281
4282 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004283 ad.u.net.netif = dev->ifindex;
James Morris4e5ab4c2006-06-09 00:33:33 -07004284 ad.u.net.family = family;
4285
Paul Moore224dfbd2008-01-29 08:38:13 -05004286 err = selinux_parse_skb(skb, &ad, &addrp, 0, &proto);
James Morris4e5ab4c2006-06-09 00:33:33 -07004287 if (err)
4288 goto out;
4289
4290 if (selinux_compat_net)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004291 err = selinux_ip_postroute_last_compat(sk, dev, &ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05004292 family, addrp);
James Morris4e5ab4c2006-06-09 00:33:33 -07004293 else
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004294 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
James Morris4e5ab4c2006-06-09 00:33:33 -07004295 PACKET__SEND, &ad);
4296
4297 if (err)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004298 goto out;
4299
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004300 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301out:
James Morris4e5ab4c2006-06-09 00:33:33 -07004302 return err ? NF_DROP : NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303}
4304
4305static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
David S. Millera224be72007-10-15 02:58:25 -07004306 struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 const struct net_device *in,
4308 const struct net_device *out,
4309 int (*okfn)(struct sk_buff *))
4310{
David S. Millera224be72007-10-15 02:58:25 -07004311 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312}
4313
4314#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4315
4316static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum,
David S. Millera224be72007-10-15 02:58:25 -07004317 struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 const struct net_device *in,
4319 const struct net_device *out,
4320 int (*okfn)(struct sk_buff *))
4321{
David S. Millera224be72007-10-15 02:58:25 -07004322 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325#endif /* IPV6 */
4326
4327#endif /* CONFIG_NETFILTER */
4328
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4330{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 int err;
4332
4333 err = secondary_ops->netlink_send(sk, skb);
4334 if (err)
4335 return err;
4336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4338 err = selinux_nlmsg_perm(sk, skb);
4339
4340 return err;
4341}
4342
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004343static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004345 int err;
4346 struct avc_audit_data ad;
4347
4348 err = secondary_ops->netlink_recv(skb, capability);
4349 if (err)
4350 return err;
4351
4352 AVC_AUDIT_DATA_INIT(&ad, CAP);
4353 ad.u.cap = capability;
4354
4355 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
4356 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357}
4358
4359static int ipc_alloc_security(struct task_struct *task,
4360 struct kern_ipc_perm *perm,
4361 u16 sclass)
4362{
4363 struct task_security_struct *tsec = task->security;
4364 struct ipc_security_struct *isec;
4365
James Morris89d155e2005-10-30 14:59:21 -08004366 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 if (!isec)
4368 return -ENOMEM;
4369
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 isec->sclass = sclass;
4371 isec->ipc_perm = perm;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004372 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 perm->security = isec;
4374
4375 return 0;
4376}
4377
4378static void ipc_free_security(struct kern_ipc_perm *perm)
4379{
4380 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 perm->security = NULL;
4382 kfree(isec);
4383}
4384
4385static int msg_msg_alloc_security(struct msg_msg *msg)
4386{
4387 struct msg_security_struct *msec;
4388
James Morris89d155e2005-10-30 14:59:21 -08004389 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 if (!msec)
4391 return -ENOMEM;
4392
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 msec->msg = msg;
4394 msec->sid = SECINITSID_UNLABELED;
4395 msg->security = msec;
4396
4397 return 0;
4398}
4399
4400static void msg_msg_free_security(struct msg_msg *msg)
4401{
4402 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
4404 msg->security = NULL;
4405 kfree(msec);
4406}
4407
4408static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004409 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410{
4411 struct task_security_struct *tsec;
4412 struct ipc_security_struct *isec;
4413 struct avc_audit_data ad;
4414
4415 tsec = current->security;
4416 isec = ipc_perms->security;
4417
4418 AVC_AUDIT_DATA_INIT(&ad, IPC);
4419 ad.u.ipc_id = ipc_perms->key;
4420
Stephen Smalley6af963f2005-05-01 08:58:39 -07004421 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422}
4423
4424static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4425{
4426 return msg_msg_alloc_security(msg);
4427}
4428
4429static void selinux_msg_msg_free_security(struct msg_msg *msg)
4430{
4431 msg_msg_free_security(msg);
4432}
4433
4434/* message queue security operations */
4435static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4436{
4437 struct task_security_struct *tsec;
4438 struct ipc_security_struct *isec;
4439 struct avc_audit_data ad;
4440 int rc;
4441
4442 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4443 if (rc)
4444 return rc;
4445
4446 tsec = current->security;
4447 isec = msq->q_perm.security;
4448
4449 AVC_AUDIT_DATA_INIT(&ad, IPC);
4450 ad.u.ipc_id = msq->q_perm.key;
4451
4452 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4453 MSGQ__CREATE, &ad);
4454 if (rc) {
4455 ipc_free_security(&msq->q_perm);
4456 return rc;
4457 }
4458 return 0;
4459}
4460
4461static void selinux_msg_queue_free_security(struct msg_queue *msq)
4462{
4463 ipc_free_security(&msq->q_perm);
4464}
4465
4466static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4467{
4468 struct task_security_struct *tsec;
4469 struct ipc_security_struct *isec;
4470 struct avc_audit_data ad;
4471
4472 tsec = current->security;
4473 isec = msq->q_perm.security;
4474
4475 AVC_AUDIT_DATA_INIT(&ad, IPC);
4476 ad.u.ipc_id = msq->q_perm.key;
4477
4478 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4479 MSGQ__ASSOCIATE, &ad);
4480}
4481
4482static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4483{
4484 int err;
4485 int perms;
4486
4487 switch(cmd) {
4488 case IPC_INFO:
4489 case MSG_INFO:
4490 /* No specific object, just general system-wide information. */
4491 return task_has_system(current, SYSTEM__IPC_INFO);
4492 case IPC_STAT:
4493 case MSG_STAT:
4494 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4495 break;
4496 case IPC_SET:
4497 perms = MSGQ__SETATTR;
4498 break;
4499 case IPC_RMID:
4500 perms = MSGQ__DESTROY;
4501 break;
4502 default:
4503 return 0;
4504 }
4505
Stephen Smalley6af963f2005-05-01 08:58:39 -07004506 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 return err;
4508}
4509
4510static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4511{
4512 struct task_security_struct *tsec;
4513 struct ipc_security_struct *isec;
4514 struct msg_security_struct *msec;
4515 struct avc_audit_data ad;
4516 int rc;
4517
4518 tsec = current->security;
4519 isec = msq->q_perm.security;
4520 msec = msg->security;
4521
4522 /*
4523 * First time through, need to assign label to the message
4524 */
4525 if (msec->sid == SECINITSID_UNLABELED) {
4526 /*
4527 * Compute new sid based on current process and
4528 * message queue this message will be stored in
4529 */
4530 rc = security_transition_sid(tsec->sid,
4531 isec->sid,
4532 SECCLASS_MSG,
4533 &msec->sid);
4534 if (rc)
4535 return rc;
4536 }
4537
4538 AVC_AUDIT_DATA_INIT(&ad, IPC);
4539 ad.u.ipc_id = msq->q_perm.key;
4540
4541 /* Can this process write to the queue? */
4542 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4543 MSGQ__WRITE, &ad);
4544 if (!rc)
4545 /* Can this process send the message */
4546 rc = avc_has_perm(tsec->sid, msec->sid,
4547 SECCLASS_MSG, MSG__SEND, &ad);
4548 if (!rc)
4549 /* Can the message be put in the queue? */
4550 rc = avc_has_perm(msec->sid, isec->sid,
4551 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4552
4553 return rc;
4554}
4555
4556static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4557 struct task_struct *target,
4558 long type, int mode)
4559{
4560 struct task_security_struct *tsec;
4561 struct ipc_security_struct *isec;
4562 struct msg_security_struct *msec;
4563 struct avc_audit_data ad;
4564 int rc;
4565
4566 tsec = target->security;
4567 isec = msq->q_perm.security;
4568 msec = msg->security;
4569
4570 AVC_AUDIT_DATA_INIT(&ad, IPC);
4571 ad.u.ipc_id = msq->q_perm.key;
4572
4573 rc = avc_has_perm(tsec->sid, isec->sid,
4574 SECCLASS_MSGQ, MSGQ__READ, &ad);
4575 if (!rc)
4576 rc = avc_has_perm(tsec->sid, msec->sid,
4577 SECCLASS_MSG, MSG__RECEIVE, &ad);
4578 return rc;
4579}
4580
4581/* Shared Memory security operations */
4582static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4583{
4584 struct task_security_struct *tsec;
4585 struct ipc_security_struct *isec;
4586 struct avc_audit_data ad;
4587 int rc;
4588
4589 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4590 if (rc)
4591 return rc;
4592
4593 tsec = current->security;
4594 isec = shp->shm_perm.security;
4595
4596 AVC_AUDIT_DATA_INIT(&ad, IPC);
4597 ad.u.ipc_id = shp->shm_perm.key;
4598
4599 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4600 SHM__CREATE, &ad);
4601 if (rc) {
4602 ipc_free_security(&shp->shm_perm);
4603 return rc;
4604 }
4605 return 0;
4606}
4607
4608static void selinux_shm_free_security(struct shmid_kernel *shp)
4609{
4610 ipc_free_security(&shp->shm_perm);
4611}
4612
4613static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4614{
4615 struct task_security_struct *tsec;
4616 struct ipc_security_struct *isec;
4617 struct avc_audit_data ad;
4618
4619 tsec = current->security;
4620 isec = shp->shm_perm.security;
4621
4622 AVC_AUDIT_DATA_INIT(&ad, IPC);
4623 ad.u.ipc_id = shp->shm_perm.key;
4624
4625 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4626 SHM__ASSOCIATE, &ad);
4627}
4628
4629/* Note, at this point, shp is locked down */
4630static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4631{
4632 int perms;
4633 int err;
4634
4635 switch(cmd) {
4636 case IPC_INFO:
4637 case SHM_INFO:
4638 /* No specific object, just general system-wide information. */
4639 return task_has_system(current, SYSTEM__IPC_INFO);
4640 case IPC_STAT:
4641 case SHM_STAT:
4642 perms = SHM__GETATTR | SHM__ASSOCIATE;
4643 break;
4644 case IPC_SET:
4645 perms = SHM__SETATTR;
4646 break;
4647 case SHM_LOCK:
4648 case SHM_UNLOCK:
4649 perms = SHM__LOCK;
4650 break;
4651 case IPC_RMID:
4652 perms = SHM__DESTROY;
4653 break;
4654 default:
4655 return 0;
4656 }
4657
Stephen Smalley6af963f2005-05-01 08:58:39 -07004658 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 return err;
4660}
4661
4662static int selinux_shm_shmat(struct shmid_kernel *shp,
4663 char __user *shmaddr, int shmflg)
4664{
4665 u32 perms;
4666 int rc;
4667
4668 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4669 if (rc)
4670 return rc;
4671
4672 if (shmflg & SHM_RDONLY)
4673 perms = SHM__READ;
4674 else
4675 perms = SHM__READ | SHM__WRITE;
4676
Stephen Smalley6af963f2005-05-01 08:58:39 -07004677 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678}
4679
4680/* Semaphore security operations */
4681static int selinux_sem_alloc_security(struct sem_array *sma)
4682{
4683 struct task_security_struct *tsec;
4684 struct ipc_security_struct *isec;
4685 struct avc_audit_data ad;
4686 int rc;
4687
4688 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4689 if (rc)
4690 return rc;
4691
4692 tsec = current->security;
4693 isec = sma->sem_perm.security;
4694
4695 AVC_AUDIT_DATA_INIT(&ad, IPC);
4696 ad.u.ipc_id = sma->sem_perm.key;
4697
4698 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4699 SEM__CREATE, &ad);
4700 if (rc) {
4701 ipc_free_security(&sma->sem_perm);
4702 return rc;
4703 }
4704 return 0;
4705}
4706
4707static void selinux_sem_free_security(struct sem_array *sma)
4708{
4709 ipc_free_security(&sma->sem_perm);
4710}
4711
4712static int selinux_sem_associate(struct sem_array *sma, int semflg)
4713{
4714 struct task_security_struct *tsec;
4715 struct ipc_security_struct *isec;
4716 struct avc_audit_data ad;
4717
4718 tsec = current->security;
4719 isec = sma->sem_perm.security;
4720
4721 AVC_AUDIT_DATA_INIT(&ad, IPC);
4722 ad.u.ipc_id = sma->sem_perm.key;
4723
4724 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4725 SEM__ASSOCIATE, &ad);
4726}
4727
4728/* Note, at this point, sma is locked down */
4729static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4730{
4731 int err;
4732 u32 perms;
4733
4734 switch(cmd) {
4735 case IPC_INFO:
4736 case SEM_INFO:
4737 /* No specific object, just general system-wide information. */
4738 return task_has_system(current, SYSTEM__IPC_INFO);
4739 case GETPID:
4740 case GETNCNT:
4741 case GETZCNT:
4742 perms = SEM__GETATTR;
4743 break;
4744 case GETVAL:
4745 case GETALL:
4746 perms = SEM__READ;
4747 break;
4748 case SETVAL:
4749 case SETALL:
4750 perms = SEM__WRITE;
4751 break;
4752 case IPC_RMID:
4753 perms = SEM__DESTROY;
4754 break;
4755 case IPC_SET:
4756 perms = SEM__SETATTR;
4757 break;
4758 case IPC_STAT:
4759 case SEM_STAT:
4760 perms = SEM__GETATTR | SEM__ASSOCIATE;
4761 break;
4762 default:
4763 return 0;
4764 }
4765
Stephen Smalley6af963f2005-05-01 08:58:39 -07004766 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 return err;
4768}
4769
4770static int selinux_sem_semop(struct sem_array *sma,
4771 struct sembuf *sops, unsigned nsops, int alter)
4772{
4773 u32 perms;
4774
4775 if (alter)
4776 perms = SEM__READ | SEM__WRITE;
4777 else
4778 perms = SEM__READ;
4779
Stephen Smalley6af963f2005-05-01 08:58:39 -07004780 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781}
4782
4783static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4784{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785 u32 av = 0;
4786
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787 av = 0;
4788 if (flag & S_IRUGO)
4789 av |= IPC__UNIX_READ;
4790 if (flag & S_IWUGO)
4791 av |= IPC__UNIX_WRITE;
4792
4793 if (av == 0)
4794 return 0;
4795
Stephen Smalley6af963f2005-05-01 08:58:39 -07004796 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797}
4798
4799/* module stacking operations */
4800static int selinux_register_security (const char *name, struct security_operations *ops)
4801{
4802 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05004803 printk(KERN_ERR "%s: There is already a secondary security "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 "module registered.\n", __FUNCTION__);
4805 return -EINVAL;
4806 }
4807
4808 secondary_ops = ops;
4809
4810 printk(KERN_INFO "%s: Registering secondary module %s\n",
4811 __FUNCTION__,
4812 name);
4813
4814 return 0;
4815}
4816
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
4818{
4819 if (inode)
4820 inode_doinit_with_dentry(inode, dentry);
4821}
4822
4823static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00004824 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825{
4826 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00004827 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 int error;
Al Viro04ff9702007-03-12 16:17:58 +00004829 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830
4831 if (current != p) {
4832 error = task_has_perm(current, p, PROCESS__GETATTR);
4833 if (error)
4834 return error;
4835 }
4836
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837 tsec = p->security;
4838
4839 if (!strcmp(name, "current"))
4840 sid = tsec->sid;
4841 else if (!strcmp(name, "prev"))
4842 sid = tsec->osid;
4843 else if (!strcmp(name, "exec"))
4844 sid = tsec->exec_sid;
4845 else if (!strcmp(name, "fscreate"))
4846 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07004847 else if (!strcmp(name, "keycreate"))
4848 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07004849 else if (!strcmp(name, "sockcreate"))
4850 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851 else
4852 return -EINVAL;
4853
4854 if (!sid)
4855 return 0;
4856
Al Viro04ff9702007-03-12 16:17:58 +00004857 error = security_sid_to_context(sid, value, &len);
4858 if (error)
4859 return error;
4860 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861}
4862
4863static int selinux_setprocattr(struct task_struct *p,
4864 char *name, void *value, size_t size)
4865{
4866 struct task_security_struct *tsec;
4867 u32 sid = 0;
4868 int error;
4869 char *str = value;
4870
4871 if (current != p) {
4872 /* SELinux only allows a process to change its own
4873 security attributes. */
4874 return -EACCES;
4875 }
4876
4877 /*
4878 * Basic control over ability to set these attributes at all.
4879 * current == p, but we'll pass them separately in case the
4880 * above restriction is ever removed.
4881 */
4882 if (!strcmp(name, "exec"))
4883 error = task_has_perm(current, p, PROCESS__SETEXEC);
4884 else if (!strcmp(name, "fscreate"))
4885 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07004886 else if (!strcmp(name, "keycreate"))
4887 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07004888 else if (!strcmp(name, "sockcreate"))
4889 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890 else if (!strcmp(name, "current"))
4891 error = task_has_perm(current, p, PROCESS__SETCURRENT);
4892 else
4893 error = -EINVAL;
4894 if (error)
4895 return error;
4896
4897 /* Obtain a SID for the context, if one was specified. */
4898 if (size && str[1] && str[1] != '\n') {
4899 if (str[size-1] == '\n') {
4900 str[size-1] = 0;
4901 size--;
4902 }
4903 error = security_context_to_sid(value, size, &sid);
4904 if (error)
4905 return error;
4906 }
4907
4908 /* Permission checking based on the specified context is
4909 performed during the actual operation (execve,
4910 open/mkdir/...), when we know the full context of the
4911 operation. See selinux_bprm_set_security for the execve
4912 checks and may_create for the file creation checks. The
4913 operation will then fail if the context is not permitted. */
4914 tsec = p->security;
4915 if (!strcmp(name, "exec"))
4916 tsec->exec_sid = sid;
4917 else if (!strcmp(name, "fscreate"))
4918 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07004919 else if (!strcmp(name, "keycreate")) {
4920 error = may_create_key(sid, p);
4921 if (error)
4922 return error;
4923 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07004924 } else if (!strcmp(name, "sockcreate"))
4925 tsec->sockcreate_sid = sid;
4926 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 struct av_decision avd;
4928
4929 if (sid == 0)
4930 return -EINVAL;
4931
4932 /* Only allow single threaded processes to change context */
4933 if (atomic_read(&p->mm->mm_users) != 1) {
4934 struct task_struct *g, *t;
4935 struct mm_struct *mm = p->mm;
4936 read_lock(&tasklist_lock);
4937 do_each_thread(g, t)
4938 if (t->mm == mm && t != p) {
4939 read_unlock(&tasklist_lock);
4940 return -EPERM;
4941 }
4942 while_each_thread(g, t);
4943 read_unlock(&tasklist_lock);
4944 }
4945
4946 /* Check permissions for the transition. */
4947 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
4948 PROCESS__DYNTRANSITION, NULL);
4949 if (error)
4950 return error;
4951
4952 /* Check for ptracing, and update the task SID if ok.
4953 Otherwise, leave SID unchanged and fail. */
4954 task_lock(p);
4955 if (p->ptrace & PT_PTRACED) {
4956 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
4957 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04004958 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 if (!error)
4960 tsec->sid = sid;
4961 task_unlock(p);
4962 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
4963 PROCESS__PTRACE, &avd, error, NULL);
4964 if (error)
4965 return error;
4966 } else {
4967 tsec->sid = sid;
4968 task_unlock(p);
4969 }
4970 }
4971 else
4972 return -EINVAL;
4973
4974 return size;
4975}
4976
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004977static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
4978{
4979 return security_sid_to_context(secid, secdata, seclen);
4980}
4981
David Howells63cb3442008-01-15 23:47:35 +00004982static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
4983{
4984 return security_context_to_sid(secdata, seclen, secid);
4985}
4986
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004987static void selinux_release_secctx(char *secdata, u32 seclen)
4988{
Paul Moore088999e2007-08-01 11:12:58 -04004989 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004990}
4991
Michael LeMayd7200242006-06-22 14:47:17 -07004992#ifdef CONFIG_KEYS
4993
David Howells7e047ef2006-06-26 00:24:50 -07004994static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
4995 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07004996{
4997 struct task_security_struct *tsec = tsk->security;
4998 struct key_security_struct *ksec;
4999
5000 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5001 if (!ksec)
5002 return -ENOMEM;
5003
5004 ksec->obj = k;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005005 if (tsec->keycreate_sid)
5006 ksec->sid = tsec->keycreate_sid;
5007 else
5008 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005009 k->security = ksec;
5010
5011 return 0;
5012}
5013
5014static void selinux_key_free(struct key *k)
5015{
5016 struct key_security_struct *ksec = k->security;
5017
5018 k->security = NULL;
5019 kfree(ksec);
5020}
5021
5022static int selinux_key_permission(key_ref_t key_ref,
5023 struct task_struct *ctx,
5024 key_perm_t perm)
5025{
5026 struct key *key;
5027 struct task_security_struct *tsec;
5028 struct key_security_struct *ksec;
5029
5030 key = key_ref_to_ptr(key_ref);
5031
5032 tsec = ctx->security;
5033 ksec = key->security;
5034
5035 /* if no specific permissions are requested, we skip the
5036 permission check. No serious, additional covert channels
5037 appear to be created. */
5038 if (perm == 0)
5039 return 0;
5040
5041 return avc_has_perm(tsec->sid, ksec->sid,
5042 SECCLASS_KEY, perm, NULL);
5043}
5044
5045#endif
5046
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047static struct security_operations selinux_ops = {
5048 .ptrace = selinux_ptrace,
5049 .capget = selinux_capget,
5050 .capset_check = selinux_capset_check,
5051 .capset_set = selinux_capset_set,
5052 .sysctl = selinux_sysctl,
5053 .capable = selinux_capable,
5054 .quotactl = selinux_quotactl,
5055 .quota_on = selinux_quota_on,
5056 .syslog = selinux_syslog,
5057 .vm_enough_memory = selinux_vm_enough_memory,
5058
5059 .netlink_send = selinux_netlink_send,
5060 .netlink_recv = selinux_netlink_recv,
5061
5062 .bprm_alloc_security = selinux_bprm_alloc_security,
5063 .bprm_free_security = selinux_bprm_free_security,
5064 .bprm_apply_creds = selinux_bprm_apply_creds,
5065 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5066 .bprm_set_security = selinux_bprm_set_security,
5067 .bprm_check_security = selinux_bprm_check_security,
5068 .bprm_secureexec = selinux_bprm_secureexec,
5069
5070 .sb_alloc_security = selinux_sb_alloc_security,
5071 .sb_free_security = selinux_sb_free_security,
5072 .sb_copy_data = selinux_sb_copy_data,
5073 .sb_kern_mount = selinux_sb_kern_mount,
5074 .sb_statfs = selinux_sb_statfs,
5075 .sb_mount = selinux_mount,
5076 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005077 .sb_get_mnt_opts = selinux_get_mnt_opts,
5078 .sb_set_mnt_opts = selinux_set_mnt_opts,
5079 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
5081 .inode_alloc_security = selinux_inode_alloc_security,
5082 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005083 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086 .inode_unlink = selinux_inode_unlink,
5087 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089 .inode_rmdir = selinux_inode_rmdir,
5090 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092 .inode_readlink = selinux_inode_readlink,
5093 .inode_follow_link = selinux_inode_follow_link,
5094 .inode_permission = selinux_inode_permission,
5095 .inode_setattr = selinux_inode_setattr,
5096 .inode_getattr = selinux_inode_getattr,
5097 .inode_setxattr = selinux_inode_setxattr,
5098 .inode_post_setxattr = selinux_inode_post_setxattr,
5099 .inode_getxattr = selinux_inode_getxattr,
5100 .inode_listxattr = selinux_inode_listxattr,
5101 .inode_removexattr = selinux_inode_removexattr,
5102 .inode_getsecurity = selinux_inode_getsecurity,
5103 .inode_setsecurity = selinux_inode_setsecurity,
5104 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005105 .inode_need_killpriv = selinux_inode_need_killpriv,
5106 .inode_killpriv = selinux_inode_killpriv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
5108 .file_permission = selinux_file_permission,
5109 .file_alloc_security = selinux_file_alloc_security,
5110 .file_free_security = selinux_file_free_security,
5111 .file_ioctl = selinux_file_ioctl,
5112 .file_mmap = selinux_file_mmap,
5113 .file_mprotect = selinux_file_mprotect,
5114 .file_lock = selinux_file_lock,
5115 .file_fcntl = selinux_file_fcntl,
5116 .file_set_fowner = selinux_file_set_fowner,
5117 .file_send_sigiotask = selinux_file_send_sigiotask,
5118 .file_receive = selinux_file_receive,
5119
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005120 .dentry_open = selinux_dentry_open,
5121
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122 .task_create = selinux_task_create,
5123 .task_alloc_security = selinux_task_alloc_security,
5124 .task_free_security = selinux_task_free_security,
5125 .task_setuid = selinux_task_setuid,
5126 .task_post_setuid = selinux_task_post_setuid,
5127 .task_setgid = selinux_task_setgid,
5128 .task_setpgid = selinux_task_setpgid,
5129 .task_getpgid = selinux_task_getpgid,
5130 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005131 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132 .task_setgroups = selinux_task_setgroups,
5133 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005134 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005135 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136 .task_setrlimit = selinux_task_setrlimit,
5137 .task_setscheduler = selinux_task_setscheduler,
5138 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005139 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140 .task_kill = selinux_task_kill,
5141 .task_wait = selinux_task_wait,
5142 .task_prctl = selinux_task_prctl,
5143 .task_reparent_to_init = selinux_task_reparent_to_init,
5144 .task_to_inode = selinux_task_to_inode,
5145
5146 .ipc_permission = selinux_ipc_permission,
5147
5148 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5149 .msg_msg_free_security = selinux_msg_msg_free_security,
5150
5151 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5152 .msg_queue_free_security = selinux_msg_queue_free_security,
5153 .msg_queue_associate = selinux_msg_queue_associate,
5154 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5155 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5156 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5157
5158 .shm_alloc_security = selinux_shm_alloc_security,
5159 .shm_free_security = selinux_shm_free_security,
5160 .shm_associate = selinux_shm_associate,
5161 .shm_shmctl = selinux_shm_shmctl,
5162 .shm_shmat = selinux_shm_shmat,
5163
5164 .sem_alloc_security = selinux_sem_alloc_security,
5165 .sem_free_security = selinux_sem_free_security,
5166 .sem_associate = selinux_sem_associate,
5167 .sem_semctl = selinux_sem_semctl,
5168 .sem_semop = selinux_sem_semop,
5169
5170 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171
5172 .d_instantiate = selinux_d_instantiate,
5173
5174 .getprocattr = selinux_getprocattr,
5175 .setprocattr = selinux_setprocattr,
5176
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005177 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005178 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005179 .release_secctx = selinux_release_secctx,
5180
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181 .unix_stream_connect = selinux_socket_unix_stream_connect,
5182 .unix_may_send = selinux_socket_unix_may_send,
5183
5184 .socket_create = selinux_socket_create,
5185 .socket_post_create = selinux_socket_post_create,
5186 .socket_bind = selinux_socket_bind,
5187 .socket_connect = selinux_socket_connect,
5188 .socket_listen = selinux_socket_listen,
5189 .socket_accept = selinux_socket_accept,
5190 .socket_sendmsg = selinux_socket_sendmsg,
5191 .socket_recvmsg = selinux_socket_recvmsg,
5192 .socket_getsockname = selinux_socket_getsockname,
5193 .socket_getpeername = selinux_socket_getpeername,
5194 .socket_getsockopt = selinux_socket_getsockopt,
5195 .socket_setsockopt = selinux_socket_setsockopt,
5196 .socket_shutdown = selinux_socket_shutdown,
5197 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005198 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5199 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 .sk_alloc_security = selinux_sk_alloc_security,
5201 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005202 .sk_clone_security = selinux_sk_clone_security,
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005203 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005204 .sock_graft = selinux_sock_graft,
5205 .inet_conn_request = selinux_inet_conn_request,
5206 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005207 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005208 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005209
5210#ifdef CONFIG_SECURITY_NETWORK_XFRM
5211 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5212 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5213 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005214 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005215 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5216 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005217 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005218 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005219 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005220 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005222
5223#ifdef CONFIG_KEYS
5224 .key_alloc = selinux_key_alloc,
5225 .key_free = selinux_key_free,
5226 .key_permission = selinux_key_permission,
5227#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228};
5229
5230static __init int selinux_init(void)
5231{
5232 struct task_security_struct *tsec;
5233
5234 if (!selinux_enabled) {
5235 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5236 return 0;
5237 }
5238
5239 printk(KERN_INFO "SELinux: Initializing.\n");
5240
5241 /* Set the security state for the initial task. */
5242 if (task_alloc_security(current))
5243 panic("SELinux: Failed to initialize initial task.\n");
5244 tsec = current->security;
5245 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5246
James Morris7cae7e22006-03-22 00:09:22 -08005247 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5248 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005249 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250 avc_init();
5251
5252 original_ops = secondary_ops = security_ops;
5253 if (!secondary_ops)
5254 panic ("SELinux: No initial security operations\n");
5255 if (register_security (&selinux_ops))
5256 panic("SELinux: Unable to register with kernel.\n");
5257
5258 if (selinux_enforcing) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005259 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 } else {
Eric Parisfadcdb42007-02-22 18:11:31 -05005261 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 }
Michael LeMayd7200242006-06-22 14:47:17 -07005263
5264#ifdef CONFIG_KEYS
5265 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005266 selinux_key_alloc(&root_user_keyring, current,
5267 KEY_ALLOC_NOT_IN_QUOTA);
5268 selinux_key_alloc(&root_session_keyring, current,
5269 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005270#endif
5271
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 return 0;
5273}
5274
5275void selinux_complete_init(void)
5276{
Eric Parisfadcdb42007-02-22 18:11:31 -05005277 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278
5279 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005280 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005281 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 spin_lock(&sb_security_lock);
5283next_sb:
5284 if (!list_empty(&superblock_security_head)) {
5285 struct superblock_security_struct *sbsec =
5286 list_entry(superblock_security_head.next,
5287 struct superblock_security_struct,
5288 list);
5289 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005292 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293 down_read(&sb->s_umount);
5294 if (sb->s_root)
5295 superblock_doinit(sb, NULL);
5296 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005297 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 spin_lock(&sb_security_lock);
5299 list_del_init(&sbsec->list);
5300 goto next_sb;
5301 }
5302 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005303 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304}
5305
5306/* SELinux requires early initialization in order to label
5307 all processes and objects when they are created. */
5308security_initcall(selinux_init);
5309
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005310#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311
5312static struct nf_hook_ops selinux_ipv4_op = {
5313 .hook = selinux_ipv4_postroute_last,
5314 .owner = THIS_MODULE,
5315 .pf = PF_INET,
Patrick McHardy6e23ae22007-11-19 18:53:30 -08005316 .hooknum = NF_INET_POST_ROUTING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317 .priority = NF_IP_PRI_SELINUX_LAST,
5318};
5319
5320#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5321
5322static struct nf_hook_ops selinux_ipv6_op = {
5323 .hook = selinux_ipv6_postroute_last,
5324 .owner = THIS_MODULE,
5325 .pf = PF_INET6,
Patrick McHardy6e23ae22007-11-19 18:53:30 -08005326 .hooknum = NF_INET_POST_ROUTING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327 .priority = NF_IP6_PRI_SELINUX_LAST,
5328};
5329
5330#endif /* IPV6 */
5331
5332static int __init selinux_nf_ip_init(void)
5333{
5334 int err = 0;
5335
5336 if (!selinux_enabled)
5337 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005338
5339 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5340
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 err = nf_register_hook(&selinux_ipv4_op);
5342 if (err)
5343 panic("SELinux: nf_register_hook for IPv4: error %d\n", err);
5344
5345#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5346
5347 err = nf_register_hook(&selinux_ipv6_op);
5348 if (err)
5349 panic("SELinux: nf_register_hook for IPv6: error %d\n", err);
5350
5351#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005352
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353out:
5354 return err;
5355}
5356
5357__initcall(selinux_nf_ip_init);
5358
5359#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5360static void selinux_nf_ip_exit(void)
5361{
Eric Parisfadcdb42007-02-22 18:11:31 -05005362 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363
5364 nf_unregister_hook(&selinux_ipv4_op);
5365#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5366 nf_unregister_hook(&selinux_ipv6_op);
5367#endif /* IPV6 */
5368}
5369#endif
5370
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005371#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372
5373#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5374#define selinux_nf_ip_exit()
5375#endif
5376
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005377#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
5379#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5380int selinux_disable(void)
5381{
5382 extern void exit_sel_fs(void);
5383 static int selinux_disabled = 0;
5384
5385 if (ss_initialized) {
5386 /* Not permitted after initial policy load. */
5387 return -EINVAL;
5388 }
5389
5390 if (selinux_disabled) {
5391 /* Only do this once. */
5392 return -EINVAL;
5393 }
5394
5395 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5396
5397 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005398 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399
5400 /* Reset security_ops to the secondary module, dummy or capability. */
5401 security_ops = secondary_ops;
5402
5403 /* Unregister netfilter hooks. */
5404 selinux_nf_ip_exit();
5405
5406 /* Unregister selinuxfs. */
5407 exit_sel_fs();
5408
5409 return 0;
5410}
5411#endif
5412
5413