blob: 1bf2543ea94224c8733abfe084baf8266ec00a85 [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>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
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.
Eric Paris828dfe12008-04-17 13:17:49 -040014 * <dgoeddel@trustedcs.com>
Paul Mooreeffad8d2008-01-29 08:49:27 -050015 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
Eric Paris828dfe12008-04-17 13:17:49 -040016 * Paul Moore <paul.moore@hp.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090017 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040018 * 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,
Eric Paris828dfe12008-04-17 13:17:49 -040022 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/init.h>
26#include <linux/kernel.h>
27#include <linux/ptrace.h>
28#include <linux/errno.h>
29#include <linux/sched.h>
30#include <linux/security.h>
31#include <linux/xattr.h>
32#include <linux/capability.h>
33#include <linux/unistd.h>
34#include <linux/mm.h>
35#include <linux/mman.h>
36#include <linux/slab.h>
37#include <linux/pagemap.h>
38#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/spinlock.h>
40#include <linux/syscalls.h>
41#include <linux/file.h>
42#include <linux/namei.h>
43#include <linux/mount.h>
44#include <linux/ext2_fs.h>
45#include <linux/proc_fs.h>
46#include <linux/kd.h>
47#include <linux/netfilter_ipv4.h>
48#include <linux/netfilter_ipv6.h>
49#include <linux/tty.h>
50#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070051#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050053#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050054#include <net/netlabel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <asm/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <asm/ioctls.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <asm/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#include <linux/bitops.h>
59#include <linux/interrupt.h>
60#include <linux/netdevice.h> /* for network interface checks */
61#include <linux/netlink.h>
62#include <linux/tcp.h>
63#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080064#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/quota.h>
66#include <linux/un.h> /* for Unix socket types */
67#include <net/af_unix.h> /* for Unix socket types */
68#include <linux/parser.h>
69#include <linux/nfs_mount.h>
70#include <net/ipv6.h>
71#include <linux/hugetlb.h>
72#include <linux/personality.h>
73#include <linux/sysctl.h>
74#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070075#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070076#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070077#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79#include "avc.h"
80#include "objsec.h"
81#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050082#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040083#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080084#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050085#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020086#include "audit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88#define XATTR_SELINUX_SUFFIX "selinux"
89#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
90
Eric Parisc9180a52007-11-30 13:00:35 -050091#define NUM_SEL_MNT_OPTS 4
92
Linus Torvalds1da177e2005-04-16 15:20:36 -070093extern unsigned int policydb_loaded_version;
94extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
James Morris4e5ab4c2006-06-09 00:33:33 -070095extern int selinux_compat_net;
James Morris20510f22007-10-16 23:31:32 -070096extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Paul Moored621d352008-01-29 08:43:36 -050098/* SECMARK reference count */
99atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400102int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104static int __init enforcing_setup(char *str)
105{
Eric Paris828dfe12008-04-17 13:17:49 -0400106 selinux_enforcing = simple_strtol(str, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 return 1;
108}
109__setup("enforcing=", enforcing_setup);
110#endif
111
112#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
113int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
114
115static int __init selinux_enabled_setup(char *str)
116{
117 selinux_enabled = simple_strtol(str, NULL, 0);
118 return 1;
119}
120__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400121#else
122int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#endif
124
125/* Original (dummy) security module. */
Eric Paris828dfe12008-04-17 13:17:49 -0400126static struct security_operations *original_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128/* Minimal support for a secondary security module,
129 just to allow the use of the dummy or capability modules.
130 The owlsm module can alternatively be used as a secondary
131 module as long as CONFIG_OWLSM_FD is not enabled. */
Eric Paris828dfe12008-04-17 13:17:49 -0400132static struct security_operations *secondary_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
134/* Lists of inode and superblock security structures initialized
135 before the policy was loaded. */
136static LIST_HEAD(superblock_security_head);
137static DEFINE_SPINLOCK(sb_security_lock);
138
Christoph Lametere18b8902006-12-06 20:33:20 -0800139static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800140
Paul Moored621d352008-01-29 08:43:36 -0500141/**
142 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
143 *
144 * Description:
145 * This function checks the SECMARK reference counter to see if any SECMARK
146 * targets are currently configured, if the reference counter is greater than
147 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
148 * enabled, false (0) if SECMARK is disabled.
149 *
150 */
151static int selinux_secmark_enabled(void)
152{
153 return (atomic_read(&selinux_secmark_refcount) > 0);
154}
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156/* Allocate and free functions for each kind of security blob. */
157
158static int task_alloc_security(struct task_struct *task)
159{
160 struct task_security_struct *tsec;
161
James Morris89d155e2005-10-30 14:59:21 -0800162 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 if (!tsec)
164 return -ENOMEM;
165
Roland McGrath03563572008-03-26 15:46:39 -0700166 tsec->osid = tsec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 task->security = tsec;
168
169 return 0;
170}
171
172static void task_free_security(struct task_struct *task)
173{
174 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 task->security = NULL;
176 kfree(tsec);
177}
178
179static int inode_alloc_security(struct inode *inode)
180{
181 struct task_security_struct *tsec = current->security;
182 struct inode_security_struct *isec;
183
Josef Bacika02fe132008-04-04 09:35:05 +1100184 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 if (!isec)
186 return -ENOMEM;
187
Eric Paris23970742006-09-25 23:32:01 -0700188 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 isec->inode = inode;
191 isec->sid = SECINITSID_UNLABELED;
192 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800193 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 inode->i_security = isec;
195
196 return 0;
197}
198
199static void inode_free_security(struct inode *inode)
200{
201 struct inode_security_struct *isec = inode->i_security;
202 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 spin_lock(&sbsec->isec_lock);
205 if (!list_empty(&isec->list))
206 list_del_init(&isec->list);
207 spin_unlock(&sbsec->isec_lock);
208
209 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800210 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211}
212
213static int file_alloc_security(struct file *file)
214{
215 struct task_security_struct *tsec = current->security;
216 struct file_security_struct *fsec;
217
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800218 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 if (!fsec)
220 return -ENOMEM;
221
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800222 fsec->sid = tsec->sid;
223 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 file->f_security = fsec;
225
226 return 0;
227}
228
229static void file_free_security(struct file *file)
230{
231 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 file->f_security = NULL;
233 kfree(fsec);
234}
235
236static int superblock_alloc_security(struct super_block *sb)
237{
238 struct superblock_security_struct *sbsec;
239
James Morris89d155e2005-10-30 14:59:21 -0800240 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (!sbsec)
242 return -ENOMEM;
243
Eric Parisbc7e9822006-09-25 23:32:02 -0700244 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 INIT_LIST_HEAD(&sbsec->list);
246 INIT_LIST_HEAD(&sbsec->isec_head);
247 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 sbsec->sb = sb;
249 sbsec->sid = SECINITSID_UNLABELED;
250 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700251 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 sb->s_security = sbsec;
253
254 return 0;
255}
256
257static void superblock_free_security(struct super_block *sb)
258{
259 struct superblock_security_struct *sbsec = sb->s_security;
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 spin_lock(&sb_security_lock);
262 if (!list_empty(&sbsec->list))
263 list_del_init(&sbsec->list);
264 spin_unlock(&sb_security_lock);
265
266 sb->s_security = NULL;
267 kfree(sbsec);
268}
269
Al Viro7d877f32005-10-21 03:20:43 -0400270static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 struct sk_security_struct *ssec;
273
James Morris89d155e2005-10-30 14:59:21 -0800274 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 if (!ssec)
276 return -ENOMEM;
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700279 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 sk->sk_security = ssec;
281
Paul Mooref74af6e2008-02-25 11:40:33 -0500282 selinux_netlbl_sk_security_reset(ssec, family);
Paul Moore99f59ed2006-08-29 17:53:48 -0700283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 return 0;
285}
286
287static void sk_free_security(struct sock *sk)
288{
289 struct sk_security_struct *ssec = sk->sk_security;
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 sk->sk_security = NULL;
292 kfree(ssec);
293}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
295/* The security server must be initialized before
296 any labeling or access decisions can be provided. */
297extern int ss_initialized;
298
299/* The file system's label must be initialized prior to use. */
300
301static char *labeling_behaviors[6] = {
302 "uses xattr",
303 "uses transition SIDs",
304 "uses task SIDs",
305 "uses genfs_contexts",
306 "not configured for labeling",
307 "uses mountpoint labeling",
308};
309
310static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
311
312static inline int inode_doinit(struct inode *inode)
313{
314 return inode_doinit_with_dentry(inode, NULL);
315}
316
317enum {
Eric Paris31e87932007-09-19 17:19:12 -0400318 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 Opt_context = 1,
320 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500321 Opt_defcontext = 3,
322 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323};
324
325static match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400326 {Opt_context, CONTEXT_STR "%s"},
327 {Opt_fscontext, FSCONTEXT_STR "%s"},
328 {Opt_defcontext, DEFCONTEXT_STR "%s"},
329 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400330 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331};
332
333#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
334
Eric Parisc312feb2006-07-10 04:43:53 -0700335static int may_context_mount_sb_relabel(u32 sid,
336 struct superblock_security_struct *sbsec,
337 struct task_security_struct *tsec)
338{
339 int rc;
340
341 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
342 FILESYSTEM__RELABELFROM, NULL);
343 if (rc)
344 return rc;
345
346 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
347 FILESYSTEM__RELABELTO, NULL);
348 return rc;
349}
350
Eric Paris08089252006-07-10 04:43:55 -0700351static int may_context_mount_inode_relabel(u32 sid,
352 struct superblock_security_struct *sbsec,
353 struct task_security_struct *tsec)
354{
355 int rc;
356 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
357 FILESYSTEM__RELABELFROM, NULL);
358 if (rc)
359 return rc;
360
361 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
362 FILESYSTEM__ASSOCIATE, NULL);
363 return rc;
364}
365
Eric Parisc9180a52007-11-30 13:00:35 -0500366static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367{
368 struct superblock_security_struct *sbsec = sb->s_security;
369 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500370 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 int rc = 0;
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
374 /* Make sure that the xattr handler exists and that no
375 error other than -ENODATA is returned by getxattr on
376 the root directory. -ENODATA is ok, as this may be
377 the first boot of the SELinux kernel before we have
378 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500379 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
381 "xattr support\n", sb->s_id, sb->s_type->name);
382 rc = -EOPNOTSUPP;
383 goto out;
384 }
Eric Parisc9180a52007-11-30 13:00:35 -0500385 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (rc < 0 && rc != -ENODATA) {
387 if (rc == -EOPNOTSUPP)
388 printk(KERN_WARNING "SELinux: (dev %s, type "
389 "%s) has no security xattr handler\n",
390 sb->s_id, sb->s_type->name);
391 else
392 printk(KERN_WARNING "SELinux: (dev %s, type "
393 "%s) getxattr errno %d\n", sb->s_id,
394 sb->s_type->name, -rc);
395 goto out;
396 }
397 }
398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 sbsec->initialized = 1;
400
Eric Parisc9180a52007-11-30 13:00:35 -0500401 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500402 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500404 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500405 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 sb->s_id, sb->s_type->name,
407 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
409 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500410 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
412 /* Initialize any other inodes associated with the superblock, e.g.
413 inodes created prior to initial policy load or inodes created
414 during get_sb by a pseudo filesystem that directly
415 populates itself. */
416 spin_lock(&sbsec->isec_lock);
417next_inode:
418 if (!list_empty(&sbsec->isec_head)) {
419 struct inode_security_struct *isec =
420 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500421 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 struct inode *inode = isec->inode;
423 spin_unlock(&sbsec->isec_lock);
424 inode = igrab(inode);
425 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500426 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 inode_doinit(inode);
428 iput(inode);
429 }
430 spin_lock(&sbsec->isec_lock);
431 list_del_init(&isec->list);
432 goto next_inode;
433 }
434 spin_unlock(&sbsec->isec_lock);
435out:
Eric Parisc9180a52007-11-30 13:00:35 -0500436 return rc;
437}
438
439/*
440 * This function should allow an FS to ask what it's mount security
441 * options were so it can use those later for submounts, displaying
442 * mount options, or whatever.
443 */
444static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500445 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500446{
447 int rc = 0, i;
448 struct superblock_security_struct *sbsec = sb->s_security;
449 char *context = NULL;
450 u32 len;
451 char tmp;
452
Eric Parise0007522008-03-05 10:31:54 -0500453 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500454
455 if (!sbsec->initialized)
456 return -EINVAL;
457
458 if (!ss_initialized)
459 return -EINVAL;
460
461 /*
462 * if we ever use sbsec flags for anything other than tracking mount
463 * settings this is going to need a mask
464 */
465 tmp = sbsec->flags;
466 /* count the number of mount options for this sb */
467 for (i = 0; i < 8; i++) {
468 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500469 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500470 tmp >>= 1;
471 }
472
Eric Parise0007522008-03-05 10:31:54 -0500473 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
474 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500475 rc = -ENOMEM;
476 goto out_free;
477 }
478
Eric Parise0007522008-03-05 10:31:54 -0500479 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
480 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500481 rc = -ENOMEM;
482 goto out_free;
483 }
484
485 i = 0;
486 if (sbsec->flags & FSCONTEXT_MNT) {
487 rc = security_sid_to_context(sbsec->sid, &context, &len);
488 if (rc)
489 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500490 opts->mnt_opts[i] = context;
491 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500492 }
493 if (sbsec->flags & CONTEXT_MNT) {
494 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
495 if (rc)
496 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500497 opts->mnt_opts[i] = context;
498 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500499 }
500 if (sbsec->flags & DEFCONTEXT_MNT) {
501 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
502 if (rc)
503 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500504 opts->mnt_opts[i] = context;
505 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500506 }
507 if (sbsec->flags & ROOTCONTEXT_MNT) {
508 struct inode *root = sbsec->sb->s_root->d_inode;
509 struct inode_security_struct *isec = root->i_security;
510
511 rc = security_sid_to_context(isec->sid, &context, &len);
512 if (rc)
513 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500514 opts->mnt_opts[i] = context;
515 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500516 }
517
Eric Parise0007522008-03-05 10:31:54 -0500518 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500519
520 return 0;
521
522out_free:
Eric Parise0007522008-03-05 10:31:54 -0500523 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500524 return rc;
525}
526
527static int bad_option(struct superblock_security_struct *sbsec, char flag,
528 u32 old_sid, u32 new_sid)
529{
530 /* check if the old mount command had the same options */
531 if (sbsec->initialized)
532 if (!(sbsec->flags & flag) ||
533 (old_sid != new_sid))
534 return 1;
535
536 /* check if we were passed the same options twice,
537 * aka someone passed context=a,context=b
538 */
539 if (!sbsec->initialized)
540 if (sbsec->flags & flag)
541 return 1;
542 return 0;
543}
Eric Parise0007522008-03-05 10:31:54 -0500544
Eric Parisc9180a52007-11-30 13:00:35 -0500545/*
546 * Allow filesystems with binary mount data to explicitly set mount point
547 * labeling information.
548 */
Eric Parise0007522008-03-05 10:31:54 -0500549static int selinux_set_mnt_opts(struct super_block *sb,
550 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500551{
552 int rc = 0, i;
553 struct task_security_struct *tsec = current->security;
554 struct superblock_security_struct *sbsec = sb->s_security;
555 const char *name = sb->s_type->name;
556 struct inode *inode = sbsec->sb->s_root->d_inode;
557 struct inode_security_struct *root_isec = inode->i_security;
558 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
559 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500560 char **mount_options = opts->mnt_opts;
561 int *flags = opts->mnt_opts_flags;
562 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500563
564 mutex_lock(&sbsec->lock);
565
566 if (!ss_initialized) {
567 if (!num_opts) {
568 /* Defer initialization until selinux_complete_init,
569 after the initial policy is loaded and the security
570 server is ready to handle calls. */
571 spin_lock(&sb_security_lock);
572 if (list_empty(&sbsec->list))
573 list_add(&sbsec->list, &superblock_security_head);
574 spin_unlock(&sb_security_lock);
575 goto out;
576 }
577 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400578 printk(KERN_WARNING "SELinux: Unable to set superblock options "
579 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500580 goto out;
581 }
582
583 /*
Eric Parise0007522008-03-05 10:31:54 -0500584 * Binary mount data FS will come through this function twice. Once
585 * from an explicit call and once from the generic calls from the vfs.
586 * Since the generic VFS calls will not contain any security mount data
587 * we need to skip the double mount verification.
588 *
589 * This does open a hole in which we will not notice if the first
590 * mount using this sb set explict options and a second mount using
591 * this sb does not set any security options. (The first options
592 * will be used for both mounts)
593 */
594 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
595 && (num_opts == 0))
596 goto out;
597
598 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500599 * parse the mount options, check if they are valid sids.
600 * also check if someone is trying to mount the same sb more
601 * than once with different security options.
602 */
603 for (i = 0; i < num_opts; i++) {
604 u32 sid;
605 rc = security_context_to_sid(mount_options[i],
606 strlen(mount_options[i]), &sid);
607 if (rc) {
608 printk(KERN_WARNING "SELinux: security_context_to_sid"
609 "(%s) failed for (dev %s, type %s) errno=%d\n",
610 mount_options[i], sb->s_id, name, rc);
611 goto out;
612 }
613 switch (flags[i]) {
614 case FSCONTEXT_MNT:
615 fscontext_sid = sid;
616
617 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
618 fscontext_sid))
619 goto out_double_mount;
620
621 sbsec->flags |= FSCONTEXT_MNT;
622 break;
623 case CONTEXT_MNT:
624 context_sid = sid;
625
626 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
627 context_sid))
628 goto out_double_mount;
629
630 sbsec->flags |= CONTEXT_MNT;
631 break;
632 case ROOTCONTEXT_MNT:
633 rootcontext_sid = sid;
634
635 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
636 rootcontext_sid))
637 goto out_double_mount;
638
639 sbsec->flags |= ROOTCONTEXT_MNT;
640
641 break;
642 case DEFCONTEXT_MNT:
643 defcontext_sid = sid;
644
645 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
646 defcontext_sid))
647 goto out_double_mount;
648
649 sbsec->flags |= DEFCONTEXT_MNT;
650
651 break;
652 default:
653 rc = -EINVAL;
654 goto out;
655 }
656 }
657
658 if (sbsec->initialized) {
659 /* previously mounted with options, but not on this attempt? */
660 if (sbsec->flags && !num_opts)
661 goto out_double_mount;
662 rc = 0;
663 goto out;
664 }
665
666 if (strcmp(sb->s_type->name, "proc") == 0)
667 sbsec->proc = 1;
668
669 /* Determine the labeling behavior to use for this filesystem type. */
670 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
671 if (rc) {
672 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +1100673 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500674 goto out;
675 }
676
677 /* sets the context of the superblock for the fs being mounted. */
678 if (fscontext_sid) {
679
680 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
681 if (rc)
682 goto out;
683
684 sbsec->sid = fscontext_sid;
685 }
686
687 /*
688 * Switch to using mount point labeling behavior.
689 * sets the label used on all file below the mountpoint, and will set
690 * the superblock context if not already set.
691 */
692 if (context_sid) {
693 if (!fscontext_sid) {
694 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
695 if (rc)
696 goto out;
697 sbsec->sid = context_sid;
698 } else {
699 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
700 if (rc)
701 goto out;
702 }
703 if (!rootcontext_sid)
704 rootcontext_sid = context_sid;
705
706 sbsec->mntpoint_sid = context_sid;
707 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
708 }
709
710 if (rootcontext_sid) {
711 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
712 if (rc)
713 goto out;
714
715 root_isec->sid = rootcontext_sid;
716 root_isec->initialized = 1;
717 }
718
719 if (defcontext_sid) {
720 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
721 rc = -EINVAL;
722 printk(KERN_WARNING "SELinux: defcontext option is "
723 "invalid for this filesystem type\n");
724 goto out;
725 }
726
727 if (defcontext_sid != sbsec->def_sid) {
728 rc = may_context_mount_inode_relabel(defcontext_sid,
729 sbsec, tsec);
730 if (rc)
731 goto out;
732 }
733
734 sbsec->def_sid = defcontext_sid;
735 }
736
737 rc = sb_finish_set_opts(sb);
738out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700739 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500741out_double_mount:
742 rc = -EINVAL;
743 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
744 "security settings for (dev %s, type %s)\n", sb->s_id, name);
745 goto out;
746}
747
748static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
749 struct super_block *newsb)
750{
751 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
752 struct superblock_security_struct *newsbsec = newsb->s_security;
753
754 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
755 int set_context = (oldsbsec->flags & CONTEXT_MNT);
756 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
757
758 /* we can't error, we can't save the info, this shouldn't get called
759 * this early in the boot process. */
760 BUG_ON(!ss_initialized);
761
Eric Parisc9180a52007-11-30 13:00:35 -0500762 /* how can we clone if the old one wasn't set up?? */
763 BUG_ON(!oldsbsec->initialized);
764
Eric Paris5a552612008-04-09 14:08:35 -0400765 /* if fs is reusing a sb, just let its options stand... */
766 if (newsbsec->initialized)
767 return;
768
Eric Parisc9180a52007-11-30 13:00:35 -0500769 mutex_lock(&newsbsec->lock);
770
771 newsbsec->flags = oldsbsec->flags;
772
773 newsbsec->sid = oldsbsec->sid;
774 newsbsec->def_sid = oldsbsec->def_sid;
775 newsbsec->behavior = oldsbsec->behavior;
776
777 if (set_context) {
778 u32 sid = oldsbsec->mntpoint_sid;
779
780 if (!set_fscontext)
781 newsbsec->sid = sid;
782 if (!set_rootcontext) {
783 struct inode *newinode = newsb->s_root->d_inode;
784 struct inode_security_struct *newisec = newinode->i_security;
785 newisec->sid = sid;
786 }
787 newsbsec->mntpoint_sid = sid;
788 }
789 if (set_rootcontext) {
790 const struct inode *oldinode = oldsb->s_root->d_inode;
791 const struct inode_security_struct *oldisec = oldinode->i_security;
792 struct inode *newinode = newsb->s_root->d_inode;
793 struct inode_security_struct *newisec = newinode->i_security;
794
795 newisec->sid = oldisec->sid;
796 }
797
798 sb_finish_set_opts(newsb);
799 mutex_unlock(&newsbsec->lock);
800}
801
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200802static int selinux_parse_opts_str(char *options,
803 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500804{
Eric Parise0007522008-03-05 10:31:54 -0500805 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500806 char *context = NULL, *defcontext = NULL;
807 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500808 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500809
Eric Parise0007522008-03-05 10:31:54 -0500810 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500811
812 /* Standard string-based options. */
813 while ((p = strsep(&options, "|")) != NULL) {
814 int token;
815 substring_t args[MAX_OPT_ARGS];
816
817 if (!*p)
818 continue;
819
820 token = match_token(p, tokens, args);
821
822 switch (token) {
823 case Opt_context:
824 if (context || defcontext) {
825 rc = -EINVAL;
826 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
827 goto out_err;
828 }
829 context = match_strdup(&args[0]);
830 if (!context) {
831 rc = -ENOMEM;
832 goto out_err;
833 }
834 break;
835
836 case Opt_fscontext:
837 if (fscontext) {
838 rc = -EINVAL;
839 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
840 goto out_err;
841 }
842 fscontext = match_strdup(&args[0]);
843 if (!fscontext) {
844 rc = -ENOMEM;
845 goto out_err;
846 }
847 break;
848
849 case Opt_rootcontext:
850 if (rootcontext) {
851 rc = -EINVAL;
852 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
853 goto out_err;
854 }
855 rootcontext = match_strdup(&args[0]);
856 if (!rootcontext) {
857 rc = -ENOMEM;
858 goto out_err;
859 }
860 break;
861
862 case Opt_defcontext:
863 if (context || defcontext) {
864 rc = -EINVAL;
865 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
866 goto out_err;
867 }
868 defcontext = match_strdup(&args[0]);
869 if (!defcontext) {
870 rc = -ENOMEM;
871 goto out_err;
872 }
873 break;
874
875 default:
876 rc = -EINVAL;
877 printk(KERN_WARNING "SELinux: unknown mount option\n");
878 goto out_err;
879
880 }
881 }
882
Eric Parise0007522008-03-05 10:31:54 -0500883 rc = -ENOMEM;
884 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
885 if (!opts->mnt_opts)
886 goto out_err;
887
888 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
889 if (!opts->mnt_opts_flags) {
890 kfree(opts->mnt_opts);
891 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500892 }
893
Eric Parise0007522008-03-05 10:31:54 -0500894 if (fscontext) {
895 opts->mnt_opts[num_mnt_opts] = fscontext;
896 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
897 }
898 if (context) {
899 opts->mnt_opts[num_mnt_opts] = context;
900 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
901 }
902 if (rootcontext) {
903 opts->mnt_opts[num_mnt_opts] = rootcontext;
904 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
905 }
906 if (defcontext) {
907 opts->mnt_opts[num_mnt_opts] = defcontext;
908 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
909 }
910
911 opts->num_mnt_opts = num_mnt_opts;
912 return 0;
913
Eric Parisc9180a52007-11-30 13:00:35 -0500914out_err:
915 kfree(context);
916 kfree(defcontext);
917 kfree(fscontext);
918 kfree(rootcontext);
919 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920}
Eric Parise0007522008-03-05 10:31:54 -0500921/*
922 * string mount options parsing and call set the sbsec
923 */
924static int superblock_doinit(struct super_block *sb, void *data)
925{
926 int rc = 0;
927 char *options = data;
928 struct security_mnt_opts opts;
929
930 security_init_mnt_opts(&opts);
931
932 if (!data)
933 goto out;
934
935 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
936
937 rc = selinux_parse_opts_str(options, &opts);
938 if (rc)
939 goto out_err;
940
941out:
942 rc = selinux_set_mnt_opts(sb, &opts);
943
944out_err:
945 security_free_mnt_opts(&opts);
946 return rc;
947}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949static inline u16 inode_mode_to_security_class(umode_t mode)
950{
951 switch (mode & S_IFMT) {
952 case S_IFSOCK:
953 return SECCLASS_SOCK_FILE;
954 case S_IFLNK:
955 return SECCLASS_LNK_FILE;
956 case S_IFREG:
957 return SECCLASS_FILE;
958 case S_IFBLK:
959 return SECCLASS_BLK_FILE;
960 case S_IFDIR:
961 return SECCLASS_DIR;
962 case S_IFCHR:
963 return SECCLASS_CHR_FILE;
964 case S_IFIFO:
965 return SECCLASS_FIFO_FILE;
966
967 }
968
969 return SECCLASS_FILE;
970}
971
James Morris13402582005-09-30 14:24:34 -0400972static inline int default_protocol_stream(int protocol)
973{
974 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
975}
976
977static inline int default_protocol_dgram(int protocol)
978{
979 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
980}
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982static inline u16 socket_type_to_security_class(int family, int type, int protocol)
983{
984 switch (family) {
985 case PF_UNIX:
986 switch (type) {
987 case SOCK_STREAM:
988 case SOCK_SEQPACKET:
989 return SECCLASS_UNIX_STREAM_SOCKET;
990 case SOCK_DGRAM:
991 return SECCLASS_UNIX_DGRAM_SOCKET;
992 }
993 break;
994 case PF_INET:
995 case PF_INET6:
996 switch (type) {
997 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -0400998 if (default_protocol_stream(protocol))
999 return SECCLASS_TCP_SOCKET;
1000 else
1001 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001003 if (default_protocol_dgram(protocol))
1004 return SECCLASS_UDP_SOCKET;
1005 else
1006 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001007 case SOCK_DCCP:
1008 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001009 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 return SECCLASS_RAWIP_SOCKET;
1011 }
1012 break;
1013 case PF_NETLINK:
1014 switch (protocol) {
1015 case NETLINK_ROUTE:
1016 return SECCLASS_NETLINK_ROUTE_SOCKET;
1017 case NETLINK_FIREWALL:
1018 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001019 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1021 case NETLINK_NFLOG:
1022 return SECCLASS_NETLINK_NFLOG_SOCKET;
1023 case NETLINK_XFRM:
1024 return SECCLASS_NETLINK_XFRM_SOCKET;
1025 case NETLINK_SELINUX:
1026 return SECCLASS_NETLINK_SELINUX_SOCKET;
1027 case NETLINK_AUDIT:
1028 return SECCLASS_NETLINK_AUDIT_SOCKET;
1029 case NETLINK_IP6_FW:
1030 return SECCLASS_NETLINK_IP6FW_SOCKET;
1031 case NETLINK_DNRTMSG:
1032 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001033 case NETLINK_KOBJECT_UEVENT:
1034 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 default:
1036 return SECCLASS_NETLINK_SOCKET;
1037 }
1038 case PF_PACKET:
1039 return SECCLASS_PACKET_SOCKET;
1040 case PF_KEY:
1041 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001042 case PF_APPLETALK:
1043 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 }
1045
1046 return SECCLASS_SOCKET;
1047}
1048
1049#ifdef CONFIG_PROC_FS
1050static int selinux_proc_get_sid(struct proc_dir_entry *de,
1051 u16 tclass,
1052 u32 *sid)
1053{
1054 int buflen, rc;
1055 char *buffer, *path, *end;
1056
Eric Paris828dfe12008-04-17 13:17:49 -04001057 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 if (!buffer)
1059 return -ENOMEM;
1060
1061 buflen = PAGE_SIZE;
1062 end = buffer+buflen;
1063 *--end = '\0';
1064 buflen--;
1065 path = end-1;
1066 *path = '/';
1067 while (de && de != de->parent) {
1068 buflen -= de->namelen + 1;
1069 if (buflen < 0)
1070 break;
1071 end -= de->namelen;
1072 memcpy(end, de->name, de->namelen);
1073 *--end = '/';
1074 path = end;
1075 de = de->parent;
1076 }
1077 rc = security_genfs_sid("proc", path, tclass, sid);
1078 free_page((unsigned long)buffer);
1079 return rc;
1080}
1081#else
1082static int selinux_proc_get_sid(struct proc_dir_entry *de,
1083 u16 tclass,
1084 u32 *sid)
1085{
1086 return -EINVAL;
1087}
1088#endif
1089
1090/* The inode's security attributes must be initialized before first use. */
1091static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1092{
1093 struct superblock_security_struct *sbsec = NULL;
1094 struct inode_security_struct *isec = inode->i_security;
1095 u32 sid;
1096 struct dentry *dentry;
1097#define INITCONTEXTLEN 255
1098 char *context = NULL;
1099 unsigned len = 0;
1100 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 if (isec->initialized)
1103 goto out;
1104
Eric Paris23970742006-09-25 23:32:01 -07001105 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001107 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
1109 sbsec = inode->i_sb->s_security;
1110 if (!sbsec->initialized) {
1111 /* Defer initialization until selinux_complete_init,
1112 after the initial policy is loaded and the security
1113 server is ready to handle calls. */
1114 spin_lock(&sbsec->isec_lock);
1115 if (list_empty(&isec->list))
1116 list_add(&isec->list, &sbsec->isec_head);
1117 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001118 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
1120
1121 switch (sbsec->behavior) {
1122 case SECURITY_FS_USE_XATTR:
1123 if (!inode->i_op->getxattr) {
1124 isec->sid = sbsec->def_sid;
1125 break;
1126 }
1127
1128 /* Need a dentry, since the xattr API requires one.
1129 Life would be simpler if we could just pass the inode. */
1130 if (opt_dentry) {
1131 /* Called from d_instantiate or d_splice_alias. */
1132 dentry = dget(opt_dentry);
1133 } else {
1134 /* Called from selinux_complete_init, try to find a dentry. */
1135 dentry = d_find_alias(inode);
1136 }
1137 if (!dentry) {
Eric Paris744ba352008-04-17 11:52:44 -04001138 printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001139 "ino=%ld\n", __func__, inode->i_sb->s_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001141 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 }
1143
1144 len = INITCONTEXTLEN;
Stephen Smalley869ab512008-04-04 08:46:05 -04001145 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 if (!context) {
1147 rc = -ENOMEM;
1148 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001149 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1152 context, len);
1153 if (rc == -ERANGE) {
1154 /* Need a larger buffer. Query for the right size. */
1155 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1156 NULL, 0);
1157 if (rc < 0) {
1158 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001159 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
1161 kfree(context);
1162 len = rc;
Stephen Smalley869ab512008-04-04 08:46:05 -04001163 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 if (!context) {
1165 rc = -ENOMEM;
1166 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001167 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 }
1169 rc = inode->i_op->getxattr(dentry,
1170 XATTR_NAME_SELINUX,
1171 context, len);
1172 }
1173 dput(dentry);
1174 if (rc < 0) {
1175 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001176 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001177 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 -rc, inode->i_sb->s_id, inode->i_ino);
1179 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001180 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 }
1182 /* Map ENODATA to the default file SID */
1183 sid = sbsec->def_sid;
1184 rc = 0;
1185 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001186 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001187 sbsec->def_sid,
1188 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 if (rc) {
Eric Paris744ba352008-04-17 11:52:44 -04001190 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 "returned %d for dev=%s ino=%ld\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001192 __func__, context, -rc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 inode->i_sb->s_id, inode->i_ino);
1194 kfree(context);
1195 /* Leave with the unlabeled SID */
1196 rc = 0;
1197 break;
1198 }
1199 }
1200 kfree(context);
1201 isec->sid = sid;
1202 break;
1203 case SECURITY_FS_USE_TASK:
1204 isec->sid = isec->task_sid;
1205 break;
1206 case SECURITY_FS_USE_TRANS:
1207 /* Default to the fs SID. */
1208 isec->sid = sbsec->sid;
1209
1210 /* Try to obtain a transition SID. */
1211 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1212 rc = security_transition_sid(isec->task_sid,
1213 sbsec->sid,
1214 isec->sclass,
1215 &sid);
1216 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001217 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 isec->sid = sid;
1219 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001220 case SECURITY_FS_USE_MNTPOINT:
1221 isec->sid = sbsec->mntpoint_sid;
1222 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001224 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 isec->sid = sbsec->sid;
1226
1227 if (sbsec->proc) {
1228 struct proc_inode *proci = PROC_I(inode);
1229 if (proci->pde) {
1230 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1231 rc = selinux_proc_get_sid(proci->pde,
1232 isec->sclass,
1233 &sid);
1234 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001235 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 isec->sid = sid;
1237 }
1238 }
1239 break;
1240 }
1241
1242 isec->initialized = 1;
1243
Eric Paris23970742006-09-25 23:32:01 -07001244out_unlock:
1245 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246out:
1247 if (isec->sclass == SECCLASS_FILE)
1248 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 return rc;
1250}
1251
1252/* Convert a Linux signal to an access vector. */
1253static inline u32 signal_to_av(int sig)
1254{
1255 u32 perm = 0;
1256
1257 switch (sig) {
1258 case SIGCHLD:
1259 /* Commonly granted from child to parent. */
1260 perm = PROCESS__SIGCHLD;
1261 break;
1262 case SIGKILL:
1263 /* Cannot be caught or ignored */
1264 perm = PROCESS__SIGKILL;
1265 break;
1266 case SIGSTOP:
1267 /* Cannot be caught or ignored */
1268 perm = PROCESS__SIGSTOP;
1269 break;
1270 default:
1271 /* All other signals. */
1272 perm = PROCESS__SIGNAL;
1273 break;
1274 }
1275
1276 return perm;
1277}
1278
1279/* Check permission betweeen a pair of tasks, e.g. signal checks,
1280 fork check, ptrace check, etc. */
1281static int task_has_perm(struct task_struct *tsk1,
1282 struct task_struct *tsk2,
1283 u32 perms)
1284{
1285 struct task_security_struct *tsec1, *tsec2;
1286
1287 tsec1 = tsk1->security;
1288 tsec2 = tsk2->security;
1289 return avc_has_perm(tsec1->sid, tsec2->sid,
1290 SECCLASS_PROCESS, perms, NULL);
1291}
1292
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001293#if CAP_LAST_CAP > 63
1294#error Fix SELinux to handle capabilities > 63.
1295#endif
1296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297/* Check whether a task is allowed to use a capability. */
1298static int task_has_capability(struct task_struct *tsk,
1299 int cap)
1300{
1301 struct task_security_struct *tsec;
1302 struct avc_audit_data ad;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001303 u16 sclass;
1304 u32 av = CAP_TO_MASK(cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306 tsec = tsk->security;
1307
Eric Paris828dfe12008-04-17 13:17:49 -04001308 AVC_AUDIT_DATA_INIT(&ad, CAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 ad.tsk = tsk;
1310 ad.u.cap = cap;
1311
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001312 switch (CAP_TO_INDEX(cap)) {
1313 case 0:
1314 sclass = SECCLASS_CAPABILITY;
1315 break;
1316 case 1:
1317 sclass = SECCLASS_CAPABILITY2;
1318 break;
1319 default:
1320 printk(KERN_ERR
1321 "SELinux: out of range capability %d\n", cap);
1322 BUG();
1323 }
1324 return avc_has_perm(tsec->sid, tsec->sid, sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325}
1326
1327/* Check whether a task is allowed to use a system operation. */
1328static int task_has_system(struct task_struct *tsk,
1329 u32 perms)
1330{
1331 struct task_security_struct *tsec;
1332
1333 tsec = tsk->security;
1334
1335 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1336 SECCLASS_SYSTEM, perms, NULL);
1337}
1338
1339/* Check whether a task has a particular permission to an inode.
1340 The 'adp' parameter is optional and allows other audit
1341 data to be passed (e.g. the dentry). */
1342static int inode_has_perm(struct task_struct *tsk,
1343 struct inode *inode,
1344 u32 perms,
1345 struct avc_audit_data *adp)
1346{
1347 struct task_security_struct *tsec;
1348 struct inode_security_struct *isec;
1349 struct avc_audit_data ad;
1350
Eric Paris828dfe12008-04-17 13:17:49 -04001351 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001352 return 0;
1353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 tsec = tsk->security;
1355 isec = inode->i_security;
1356
1357 if (!adp) {
1358 adp = &ad;
1359 AVC_AUDIT_DATA_INIT(&ad, FS);
1360 ad.u.fs.inode = inode;
1361 }
1362
1363 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1364}
1365
1366/* Same as inode_has_perm, but pass explicit audit data containing
1367 the dentry to help the auditing code to more easily generate the
1368 pathname if needed. */
1369static inline int dentry_has_perm(struct task_struct *tsk,
1370 struct vfsmount *mnt,
1371 struct dentry *dentry,
1372 u32 av)
1373{
1374 struct inode *inode = dentry->d_inode;
1375 struct avc_audit_data ad;
Eric Paris828dfe12008-04-17 13:17:49 -04001376 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001377 ad.u.fs.path.mnt = mnt;
1378 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 return inode_has_perm(tsk, inode, av, &ad);
1380}
1381
1382/* Check whether a task can use an open file descriptor to
1383 access an inode in a given way. Check access to the
1384 descriptor itself, and then use dentry_has_perm to
1385 check a particular permission to the file.
1386 Access to the descriptor is implicitly granted if it
1387 has the same SID as the process. If av is zero, then
1388 access to the file is not checked, e.g. for cases
1389 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001390static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 struct file *file,
1392 u32 av)
1393{
1394 struct task_security_struct *tsec = tsk->security;
1395 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001396 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 struct avc_audit_data ad;
1398 int rc;
1399
1400 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001401 ad.u.fs.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
1403 if (tsec->sid != fsec->sid) {
1404 rc = avc_has_perm(tsec->sid, fsec->sid,
1405 SECCLASS_FD,
1406 FD__USE,
1407 &ad);
1408 if (rc)
1409 return rc;
1410 }
1411
1412 /* av is zero if only checking access to the descriptor. */
1413 if (av)
1414 return inode_has_perm(tsk, inode, av, &ad);
1415
1416 return 0;
1417}
1418
1419/* Check whether a task can create a file. */
1420static int may_create(struct inode *dir,
1421 struct dentry *dentry,
1422 u16 tclass)
1423{
1424 struct task_security_struct *tsec;
1425 struct inode_security_struct *dsec;
1426 struct superblock_security_struct *sbsec;
1427 u32 newsid;
1428 struct avc_audit_data ad;
1429 int rc;
1430
1431 tsec = current->security;
1432 dsec = dir->i_security;
1433 sbsec = dir->i_sb->s_security;
1434
1435 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001436 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
1438 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1439 DIR__ADD_NAME | DIR__SEARCH,
1440 &ad);
1441 if (rc)
1442 return rc;
1443
1444 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1445 newsid = tsec->create_sid;
1446 } else {
1447 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1448 &newsid);
1449 if (rc)
1450 return rc;
1451 }
1452
1453 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1454 if (rc)
1455 return rc;
1456
1457 return avc_has_perm(newsid, sbsec->sid,
1458 SECCLASS_FILESYSTEM,
1459 FILESYSTEM__ASSOCIATE, &ad);
1460}
1461
Michael LeMay4eb582c2006-06-26 00:24:57 -07001462/* Check whether a task can create a key. */
1463static int may_create_key(u32 ksid,
1464 struct task_struct *ctx)
1465{
1466 struct task_security_struct *tsec;
1467
1468 tsec = ctx->security;
1469
1470 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1471}
1472
Eric Paris828dfe12008-04-17 13:17:49 -04001473#define MAY_LINK 0
1474#define MAY_UNLINK 1
1475#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
1477/* Check whether a task can link, unlink, or rmdir a file/directory. */
1478static int may_link(struct inode *dir,
1479 struct dentry *dentry,
1480 int kind)
1481
1482{
1483 struct task_security_struct *tsec;
1484 struct inode_security_struct *dsec, *isec;
1485 struct avc_audit_data ad;
1486 u32 av;
1487 int rc;
1488
1489 tsec = current->security;
1490 dsec = dir->i_security;
1491 isec = dentry->d_inode->i_security;
1492
1493 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001494 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
1496 av = DIR__SEARCH;
1497 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1498 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1499 if (rc)
1500 return rc;
1501
1502 switch (kind) {
1503 case MAY_LINK:
1504 av = FILE__LINK;
1505 break;
1506 case MAY_UNLINK:
1507 av = FILE__UNLINK;
1508 break;
1509 case MAY_RMDIR:
1510 av = DIR__RMDIR;
1511 break;
1512 default:
Eric Paris744ba352008-04-17 11:52:44 -04001513 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1514 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 return 0;
1516 }
1517
1518 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1519 return rc;
1520}
1521
1522static inline int may_rename(struct inode *old_dir,
1523 struct dentry *old_dentry,
1524 struct inode *new_dir,
1525 struct dentry *new_dentry)
1526{
1527 struct task_security_struct *tsec;
1528 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1529 struct avc_audit_data ad;
1530 u32 av;
1531 int old_is_dir, new_is_dir;
1532 int rc;
1533
1534 tsec = current->security;
1535 old_dsec = old_dir->i_security;
1536 old_isec = old_dentry->d_inode->i_security;
1537 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1538 new_dsec = new_dir->i_security;
1539
1540 AVC_AUDIT_DATA_INIT(&ad, FS);
1541
Jan Blunck44707fd2008-02-14 19:38:33 -08001542 ad.u.fs.path.dentry = old_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1544 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1545 if (rc)
1546 return rc;
1547 rc = avc_has_perm(tsec->sid, old_isec->sid,
1548 old_isec->sclass, FILE__RENAME, &ad);
1549 if (rc)
1550 return rc;
1551 if (old_is_dir && new_dir != old_dir) {
1552 rc = avc_has_perm(tsec->sid, old_isec->sid,
1553 old_isec->sclass, DIR__REPARENT, &ad);
1554 if (rc)
1555 return rc;
1556 }
1557
Jan Blunck44707fd2008-02-14 19:38:33 -08001558 ad.u.fs.path.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 av = DIR__ADD_NAME | DIR__SEARCH;
1560 if (new_dentry->d_inode)
1561 av |= DIR__REMOVE_NAME;
1562 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1563 if (rc)
1564 return rc;
1565 if (new_dentry->d_inode) {
1566 new_isec = new_dentry->d_inode->i_security;
1567 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1568 rc = avc_has_perm(tsec->sid, new_isec->sid,
1569 new_isec->sclass,
1570 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1571 if (rc)
1572 return rc;
1573 }
1574
1575 return 0;
1576}
1577
1578/* Check whether a task can perform a filesystem operation. */
1579static int superblock_has_perm(struct task_struct *tsk,
1580 struct super_block *sb,
1581 u32 perms,
1582 struct avc_audit_data *ad)
1583{
1584 struct task_security_struct *tsec;
1585 struct superblock_security_struct *sbsec;
1586
1587 tsec = tsk->security;
1588 sbsec = sb->s_security;
1589 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1590 perms, ad);
1591}
1592
1593/* Convert a Linux mode and permission mask to an access vector. */
1594static inline u32 file_mask_to_av(int mode, int mask)
1595{
1596 u32 av = 0;
1597
1598 if ((mode & S_IFMT) != S_IFDIR) {
1599 if (mask & MAY_EXEC)
1600 av |= FILE__EXECUTE;
1601 if (mask & MAY_READ)
1602 av |= FILE__READ;
1603
1604 if (mask & MAY_APPEND)
1605 av |= FILE__APPEND;
1606 else if (mask & MAY_WRITE)
1607 av |= FILE__WRITE;
1608
1609 } else {
1610 if (mask & MAY_EXEC)
1611 av |= DIR__SEARCH;
1612 if (mask & MAY_WRITE)
1613 av |= DIR__WRITE;
1614 if (mask & MAY_READ)
1615 av |= DIR__READ;
1616 }
1617
1618 return av;
1619}
1620
Eric Parisb0c636b2008-02-28 12:58:40 -05001621/*
1622 * Convert a file mask to an access vector and include the correct open
1623 * open permission.
1624 */
1625static inline u32 open_file_mask_to_av(int mode, int mask)
1626{
1627 u32 av = file_mask_to_av(mode, mask);
1628
1629 if (selinux_policycap_openperm) {
1630 /*
1631 * lnk files and socks do not really have an 'open'
1632 */
1633 if (S_ISREG(mode))
1634 av |= FILE__OPEN;
1635 else if (S_ISCHR(mode))
1636 av |= CHR_FILE__OPEN;
1637 else if (S_ISBLK(mode))
1638 av |= BLK_FILE__OPEN;
1639 else if (S_ISFIFO(mode))
1640 av |= FIFO_FILE__OPEN;
1641 else if (S_ISDIR(mode))
1642 av |= DIR__OPEN;
1643 else
Eric Paris744ba352008-04-17 11:52:44 -04001644 printk(KERN_ERR "SELinux: WARNING: inside %s with "
1645 "unknown mode:%x\n", __func__, mode);
Eric Parisb0c636b2008-02-28 12:58:40 -05001646 }
1647 return av;
1648}
1649
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650/* Convert a Linux file to an access vector. */
1651static inline u32 file_to_av(struct file *file)
1652{
1653 u32 av = 0;
1654
1655 if (file->f_mode & FMODE_READ)
1656 av |= FILE__READ;
1657 if (file->f_mode & FMODE_WRITE) {
1658 if (file->f_flags & O_APPEND)
1659 av |= FILE__APPEND;
1660 else
1661 av |= FILE__WRITE;
1662 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001663 if (!av) {
1664 /*
1665 * Special file opened with flags 3 for ioctl-only use.
1666 */
1667 av = FILE__IOCTL;
1668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 return av;
1671}
1672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673/* Hook functions begin here. */
1674
1675static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1676{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 int rc;
1678
Eric Paris828dfe12008-04-17 13:17:49 -04001679 rc = secondary_ops->ptrace(parent, child);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 if (rc)
1681 return rc;
1682
Roland McGrath03563572008-03-26 15:46:39 -07001683 return task_has_perm(parent, child, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684}
1685
1686static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001687 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688{
1689 int error;
1690
1691 error = task_has_perm(current, target, PROCESS__GETCAP);
1692 if (error)
1693 return error;
1694
1695 return secondary_ops->capget(target, effective, inheritable, permitted);
1696}
1697
1698static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001699 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
1701 int error;
1702
1703 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1704 if (error)
1705 return error;
1706
1707 return task_has_perm(current, target, PROCESS__SETCAP);
1708}
1709
1710static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001711 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712{
1713 secondary_ops->capset_set(target, effective, inheritable, permitted);
1714}
1715
1716static int selinux_capable(struct task_struct *tsk, int cap)
1717{
1718 int rc;
1719
1720 rc = secondary_ops->capable(tsk, cap);
1721 if (rc)
1722 return rc;
1723
Eric Paris828dfe12008-04-17 13:17:49 -04001724 return task_has_capability(tsk, cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725}
1726
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001727static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1728{
1729 int buflen, rc;
1730 char *buffer, *path, *end;
1731
1732 rc = -ENOMEM;
Eric Paris828dfe12008-04-17 13:17:49 -04001733 buffer = (char *)__get_free_page(GFP_KERNEL);
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001734 if (!buffer)
1735 goto out;
1736
1737 buflen = PAGE_SIZE;
1738 end = buffer+buflen;
1739 *--end = '\0';
1740 buflen--;
1741 path = end-1;
1742 *path = '/';
1743 while (table) {
1744 const char *name = table->procname;
1745 size_t namelen = strlen(name);
1746 buflen -= namelen + 1;
1747 if (buflen < 0)
1748 goto out_free;
1749 end -= namelen;
1750 memcpy(end, name, namelen);
1751 *--end = '/';
1752 path = end;
1753 table = table->parent;
1754 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001755 buflen -= 4;
1756 if (buflen < 0)
1757 goto out_free;
1758 end -= 4;
1759 memcpy(end, "/sys", 4);
1760 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001761 rc = security_genfs_sid("proc", path, tclass, sid);
1762out_free:
1763 free_page((unsigned long)buffer);
1764out:
1765 return rc;
1766}
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768static int selinux_sysctl(ctl_table *table, int op)
1769{
1770 int error = 0;
1771 u32 av;
1772 struct task_security_struct *tsec;
1773 u32 tsid;
1774 int rc;
1775
1776 rc = secondary_ops->sysctl(table, op);
1777 if (rc)
1778 return rc;
1779
1780 tsec = current->security;
1781
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001782 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1783 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 if (rc) {
1785 /* Default to the well-defined sysctl SID. */
1786 tsid = SECINITSID_SYSCTL;
1787 }
1788
1789 /* The op values are "defined" in sysctl.c, thereby creating
1790 * a bad coupling between this module and sysctl.c */
Eric Paris828dfe12008-04-17 13:17:49 -04001791 if (op == 001) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 error = avc_has_perm(tsec->sid, tsid,
1793 SECCLASS_DIR, DIR__SEARCH, NULL);
1794 } else {
1795 av = 0;
1796 if (op & 004)
1797 av |= FILE__READ;
1798 if (op & 002)
1799 av |= FILE__WRITE;
1800 if (av)
1801 error = avc_has_perm(tsec->sid, tsid,
1802 SECCLASS_FILE, av, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
1805 return error;
1806}
1807
1808static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1809{
1810 int rc = 0;
1811
1812 if (!sb)
1813 return 0;
1814
1815 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001816 case Q_SYNC:
1817 case Q_QUOTAON:
1818 case Q_QUOTAOFF:
1819 case Q_SETINFO:
1820 case Q_SETQUOTA:
1821 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
1822 NULL);
1823 break;
1824 case Q_GETFMT:
1825 case Q_GETINFO:
1826 case Q_GETQUOTA:
1827 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
1828 NULL);
1829 break;
1830 default:
1831 rc = 0; /* let the kernel handle invalid cmds */
1832 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 }
1834 return rc;
1835}
1836
1837static int selinux_quota_on(struct dentry *dentry)
1838{
1839 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1840}
1841
1842static int selinux_syslog(int type)
1843{
1844 int rc;
1845
1846 rc = secondary_ops->syslog(type);
1847 if (rc)
1848 return rc;
1849
1850 switch (type) {
Eric Paris828dfe12008-04-17 13:17:49 -04001851 case 3: /* Read last kernel messages */
1852 case 10: /* Return size of the log buffer */
1853 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1854 break;
1855 case 6: /* Disable logging to console */
1856 case 7: /* Enable logging to console */
1857 case 8: /* Set level of messages printed to console */
1858 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1859 break;
1860 case 0: /* Close log */
1861 case 1: /* Open log */
1862 case 2: /* Read from log */
1863 case 4: /* Read/clear last kernel messages */
1864 case 5: /* Clear ring buffer */
1865 default:
1866 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1867 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 }
1869 return rc;
1870}
1871
1872/*
1873 * Check that a process has enough memory to allocate a new virtual
1874 * mapping. 0 means there is enough memory for the allocation to
1875 * succeed and -ENOMEM implies there is not.
1876 *
1877 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1878 * if the capability is granted, but __vm_enough_memory requires 1 if
1879 * the capability is granted.
1880 *
1881 * Do not audit the selinux permission check, as this is applied to all
1882 * processes that allocate mappings.
1883 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001884static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885{
1886 int rc, cap_sys_admin = 0;
1887 struct task_security_struct *tsec = current->security;
1888
1889 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1890 if (rc == 0)
1891 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001892 SECCLASS_CAPABILITY,
1893 CAP_TO_MASK(CAP_SYS_ADMIN),
1894 0,
1895 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
1897 if (rc == 0)
1898 cap_sys_admin = 1;
1899
Alan Cox34b4e4a2007-08-22 14:01:28 -07001900 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901}
1902
Roland McGrath03563572008-03-26 15:46:39 -07001903/**
1904 * task_tracer_task - return the task that is tracing the given task
1905 * @task: task to consider
1906 *
1907 * Returns NULL if noone is tracing @task, or the &struct task_struct
1908 * pointer to its tracer.
1909 *
1910 * Must be called under rcu_read_lock().
1911 */
1912static struct task_struct *task_tracer_task(struct task_struct *task)
1913{
1914 if (task->ptrace & PT_PTRACED)
1915 return rcu_dereference(task->parent);
1916 return NULL;
1917}
1918
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919/* binprm security operations */
1920
1921static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1922{
1923 struct bprm_security_struct *bsec;
1924
James Morris89d155e2005-10-30 14:59:21 -08001925 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if (!bsec)
1927 return -ENOMEM;
1928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 bsec->sid = SECINITSID_UNLABELED;
1930 bsec->set = 0;
1931
1932 bprm->security = bsec;
1933 return 0;
1934}
1935
1936static int selinux_bprm_set_security(struct linux_binprm *bprm)
1937{
1938 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001939 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 struct inode_security_struct *isec;
1941 struct bprm_security_struct *bsec;
1942 u32 newsid;
1943 struct avc_audit_data ad;
1944 int rc;
1945
1946 rc = secondary_ops->bprm_set_security(bprm);
1947 if (rc)
1948 return rc;
1949
1950 bsec = bprm->security;
1951
1952 if (bsec->set)
1953 return 0;
1954
1955 tsec = current->security;
1956 isec = inode->i_security;
1957
1958 /* Default to the current task SID. */
1959 bsec->sid = tsec->sid;
1960
Michael LeMay28eba5b2006-06-27 02:53:42 -07001961 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001963 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001964 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
1966 if (tsec->exec_sid) {
1967 newsid = tsec->exec_sid;
1968 /* Reset exec SID on execve. */
1969 tsec->exec_sid = 0;
1970 } else {
1971 /* Check for a default transition on this program. */
1972 rc = security_transition_sid(tsec->sid, isec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04001973 SECCLASS_PROCESS, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 if (rc)
1975 return rc;
1976 }
1977
1978 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001979 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
Josef Sipek3d5ff522006-12-08 02:37:38 -08001981 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 newsid = tsec->sid;
1983
Eric Paris828dfe12008-04-17 13:17:49 -04001984 if (tsec->sid == newsid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 rc = avc_has_perm(tsec->sid, isec->sid,
1986 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1987 if (rc)
1988 return rc;
1989 } else {
1990 /* Check permissions for the transition. */
1991 rc = avc_has_perm(tsec->sid, newsid,
1992 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1993 if (rc)
1994 return rc;
1995
1996 rc = avc_has_perm(newsid, isec->sid,
1997 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1998 if (rc)
1999 return rc;
2000
2001 /* Clear any possibly unsafe personality bits on exec: */
2002 current->personality &= ~PER_CLEAR_ON_SETID;
2003
2004 /* Set the security field to the new SID. */
2005 bsec->sid = newsid;
2006 }
2007
2008 bsec->set = 1;
2009 return 0;
2010}
2011
Eric Paris828dfe12008-04-17 13:17:49 -04002012static int selinux_bprm_check_security(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
2014 return secondary_ops->bprm_check_security(bprm);
2015}
2016
2017
Eric Paris828dfe12008-04-17 13:17:49 -04002018static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019{
2020 struct task_security_struct *tsec = current->security;
2021 int atsecure = 0;
2022
2023 if (tsec->osid != tsec->sid) {
2024 /* Enable secure mode for SIDs transitions unless
2025 the noatsecure permission is granted between
2026 the two SIDs, i.e. ahp returns 0. */
2027 atsecure = avc_has_perm(tsec->osid, tsec->sid,
2028 SECCLASS_PROCESS,
2029 PROCESS__NOATSECURE, NULL);
2030 }
2031
2032 return (atsecure || secondary_ops->bprm_secureexec(bprm));
2033}
2034
2035static void selinux_bprm_free_security(struct linux_binprm *bprm)
2036{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07002037 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039}
2040
2041extern struct vfsmount *selinuxfs_mount;
2042extern struct dentry *selinux_null;
2043
2044/* Derived from fs/exec.c:flush_old_files. */
Eric Paris828dfe12008-04-17 13:17:49 -04002045static inline void flush_unauthorized_files(struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
2047 struct avc_audit_data ad;
2048 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002049 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002050 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002052 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002054 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002055 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 if (tty) {
2057 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08002058 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 if (file) {
2060 /* Revalidate access to controlling tty.
2061 Use inode_has_perm on the tty inode directly rather
2062 than using file_has_perm, as this particular open
2063 file may belong to another process and we are only
2064 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002065 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 if (inode_has_perm(current, inode,
2067 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002068 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 }
2070 }
2071 file_list_unlock();
2072 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002073 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002074 /* Reset controlling tty. */
2075 if (drop_tty)
2076 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
2078 /* Revalidate access to inherited open files. */
2079
Eric Paris828dfe12008-04-17 13:17:49 -04002080 AVC_AUDIT_DATA_INIT(&ad, FS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
2082 spin_lock(&files->file_lock);
2083 for (;;) {
2084 unsigned long set, i;
2085 int fd;
2086
2087 j++;
2088 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002089 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002090 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002092 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 if (!set)
2094 continue;
2095 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002096 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 if (set & 1) {
2098 file = fget(i);
2099 if (!file)
2100 continue;
2101 if (file_has_perm(current,
2102 file,
2103 file_to_av(file))) {
2104 sys_close(i);
2105 fd = get_unused_fd();
2106 if (fd != i) {
2107 if (fd >= 0)
2108 put_unused_fd(fd);
2109 fput(file);
2110 continue;
2111 }
2112 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002113 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 } else {
2115 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002116 if (IS_ERR(devnull)) {
2117 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 put_unused_fd(fd);
2119 fput(file);
2120 continue;
2121 }
2122 }
2123 fd_install(fd, devnull);
2124 }
2125 fput(file);
2126 }
2127 }
2128 spin_lock(&files->file_lock);
2129
2130 }
2131 spin_unlock(&files->file_lock);
2132}
2133
2134static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2135{
2136 struct task_security_struct *tsec;
2137 struct bprm_security_struct *bsec;
2138 u32 sid;
2139 int rc;
2140
2141 secondary_ops->bprm_apply_creds(bprm, unsafe);
2142
2143 tsec = current->security;
2144
2145 bsec = bprm->security;
2146 sid = bsec->sid;
2147
2148 tsec->osid = tsec->sid;
2149 bsec->unsafe = 0;
2150 if (tsec->sid != sid) {
2151 /* Check for shared state. If not ok, leave SID
2152 unchanged and kill. */
2153 if (unsafe & LSM_UNSAFE_SHARE) {
2154 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2155 PROCESS__SHARE, NULL);
2156 if (rc) {
2157 bsec->unsafe = 1;
2158 return;
2159 }
2160 }
2161
2162 /* Check for ptracing, and update the task SID if ok.
2163 Otherwise, leave SID unchanged and kill. */
2164 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Roland McGrath03563572008-03-26 15:46:39 -07002165 struct task_struct *tracer;
2166 struct task_security_struct *sec;
2167 u32 ptsid = 0;
2168
2169 rcu_read_lock();
2170 tracer = task_tracer_task(current);
2171 if (likely(tracer != NULL)) {
2172 sec = tracer->security;
2173 ptsid = sec->sid;
2174 }
2175 rcu_read_unlock();
2176
2177 if (ptsid != 0) {
2178 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
2179 PROCESS__PTRACE, NULL);
2180 if (rc) {
2181 bsec->unsafe = 1;
2182 return;
2183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 }
2185 }
2186 tsec->sid = sid;
2187 }
2188}
2189
2190/*
2191 * called after apply_creds without the task lock held
2192 */
2193static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2194{
2195 struct task_security_struct *tsec;
2196 struct rlimit *rlim, *initrlim;
2197 struct itimerval itimer;
2198 struct bprm_security_struct *bsec;
2199 int rc, i;
2200
2201 tsec = current->security;
2202 bsec = bprm->security;
2203
2204 if (bsec->unsafe) {
2205 force_sig_specific(SIGKILL, current);
2206 return;
2207 }
2208 if (tsec->osid == tsec->sid)
2209 return;
2210
2211 /* Close files for which the new task SID is not authorized. */
2212 flush_unauthorized_files(current->files);
2213
2214 /* Check whether the new SID can inherit signal state
2215 from the old SID. If not, clear itimers to avoid
2216 subsequent signal generation and flush and unblock
2217 signals. This must occur _after_ the task SID has
2218 been updated so that any kill done after the flush
2219 will be checked against the new SID. */
2220 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2221 PROCESS__SIGINH, NULL);
2222 if (rc) {
2223 memset(&itimer, 0, sizeof itimer);
2224 for (i = 0; i < 3; i++)
2225 do_setitimer(i, &itimer, NULL);
2226 flush_signals(current);
2227 spin_lock_irq(&current->sighand->siglock);
2228 flush_signal_handlers(current, 1);
2229 sigemptyset(&current->blocked);
2230 recalc_sigpending();
2231 spin_unlock_irq(&current->sighand->siglock);
2232 }
2233
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002234 /* Always clear parent death signal on SID transitions. */
2235 current->pdeath_signal = 0;
2236
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 /* Check whether the new SID can inherit resource limits
2238 from the old SID. If not, reset all soft limits to
2239 the lower of the current task's hard limit and the init
2240 task's soft limit. Note that the setting of hard limits
2241 (even to lower them) can be controlled by the setrlimit
2242 check. The inclusion of the init task's soft limit into
2243 the computation is to avoid resetting soft limits higher
2244 than the default soft limit for cases where the default
2245 is lower than the hard limit, e.g. RLIMIT_CORE or
2246 RLIMIT_STACK.*/
2247 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2248 PROCESS__RLIMITINH, NULL);
2249 if (rc) {
2250 for (i = 0; i < RLIM_NLIMITS; i++) {
2251 rlim = current->signal->rlim + i;
2252 initrlim = init_task.signal->rlim+i;
Eric Paris828dfe12008-04-17 13:17:49 -04002253 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2256 /*
2257 * This will cause RLIMIT_CPU calculations
2258 * to be refigured.
2259 */
2260 current->it_prof_expires = jiffies_to_cputime(1);
2261 }
2262 }
2263
2264 /* Wake up the parent if it is waiting so that it can
2265 recheck wait permission to the new task SID. */
2266 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2267}
2268
2269/* superblock security operations */
2270
2271static int selinux_sb_alloc_security(struct super_block *sb)
2272{
2273 return superblock_alloc_security(sb);
2274}
2275
2276static void selinux_sb_free_security(struct super_block *sb)
2277{
2278 superblock_free_security(sb);
2279}
2280
2281static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2282{
2283 if (plen > olen)
2284 return 0;
2285
2286 return !memcmp(prefix, option, plen);
2287}
2288
2289static inline int selinux_option(char *option, int len)
2290{
Eric Paris832cbd92008-04-01 13:24:09 -04002291 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2292 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2293 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2294 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295}
2296
2297static inline void take_option(char **to, char *from, int *first, int len)
2298{
2299 if (!*first) {
2300 **to = ',';
2301 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002302 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 *first = 0;
2304 memcpy(*to, from, len);
2305 *to += len;
2306}
2307
Eric Paris828dfe12008-04-17 13:17:49 -04002308static inline void take_selinux_option(char **to, char *from, int *first,
2309 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002310{
2311 int current_size = 0;
2312
2313 if (!*first) {
2314 **to = '|';
2315 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002316 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002317 *first = 0;
2318
2319 while (current_size < len) {
2320 if (*from != '"') {
2321 **to = *from;
2322 *to += 1;
2323 }
2324 from += 1;
2325 current_size += 1;
2326 }
2327}
2328
Eric Parise0007522008-03-05 10:31:54 -05002329static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
2331 int fnosec, fsec, rc = 0;
2332 char *in_save, *in_curr, *in_end;
2333 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002334 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
2336 in_curr = orig;
2337 sec_curr = copy;
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2340 if (!nosec) {
2341 rc = -ENOMEM;
2342 goto out;
2343 }
2344
2345 nosec_save = nosec;
2346 fnosec = fsec = 1;
2347 in_save = in_end = orig;
2348
2349 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002350 if (*in_end == '"')
2351 open_quote = !open_quote;
2352 if ((*in_end == ',' && open_quote == 0) ||
2353 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 int len = in_end - in_curr;
2355
2356 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002357 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 else
2359 take_option(&nosec, in_curr, &fnosec, len);
2360
2361 in_curr = in_end + 1;
2362 }
2363 } while (*in_end++);
2364
Eric Paris6931dfc2005-06-30 02:58:51 -07002365 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002366 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367out:
2368 return rc;
2369}
2370
2371static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2372{
2373 struct avc_audit_data ad;
2374 int rc;
2375
2376 rc = superblock_doinit(sb, data);
2377 if (rc)
2378 return rc;
2379
Eric Paris828dfe12008-04-17 13:17:49 -04002380 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002381 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2383}
2384
David Howells726c3342006-06-23 02:02:58 -07002385static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386{
2387 struct avc_audit_data ad;
2388
Eric Paris828dfe12008-04-17 13:17:49 -04002389 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002390 ad.u.fs.path.dentry = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002391 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392}
2393
Eric Paris828dfe12008-04-17 13:17:49 -04002394static int selinux_mount(char *dev_name,
2395 struct nameidata *nd,
2396 char *type,
2397 unsigned long flags,
2398 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399{
2400 int rc;
2401
2402 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
2403 if (rc)
2404 return rc;
2405
2406 if (flags & MS_REMOUNT)
Jan Blunck4ac91372008-02-14 19:34:32 -08002407 return superblock_has_perm(current, nd->path.mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002408 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 else
Jan Blunck4ac91372008-02-14 19:34:32 -08002410 return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002411 FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412}
2413
2414static int selinux_umount(struct vfsmount *mnt, int flags)
2415{
2416 int rc;
2417
2418 rc = secondary_ops->sb_umount(mnt, flags);
2419 if (rc)
2420 return rc;
2421
Eric Paris828dfe12008-04-17 13:17:49 -04002422 return superblock_has_perm(current, mnt->mnt_sb,
2423 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424}
2425
2426/* inode security operations */
2427
2428static int selinux_inode_alloc_security(struct inode *inode)
2429{
2430 return inode_alloc_security(inode);
2431}
2432
2433static void selinux_inode_free_security(struct inode *inode)
2434{
2435 inode_free_security(inode);
2436}
2437
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002438static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2439 char **name, void **value,
2440 size_t *len)
2441{
2442 struct task_security_struct *tsec;
2443 struct inode_security_struct *dsec;
2444 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002445 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002446 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002447 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002448
2449 tsec = current->security;
2450 dsec = dir->i_security;
2451 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002452
2453 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2454 newsid = tsec->create_sid;
2455 } else {
2456 rc = security_transition_sid(tsec->sid, dsec->sid,
2457 inode_mode_to_security_class(inode->i_mode),
2458 &newsid);
2459 if (rc) {
2460 printk(KERN_WARNING "%s: "
2461 "security_transition_sid failed, rc=%d (dev=%s "
2462 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002463 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002464 -rc, inode->i_sb->s_id, inode->i_ino);
2465 return rc;
2466 }
2467 }
2468
Eric Paris296fddf2006-09-25 23:32:00 -07002469 /* Possibly defer initialization to selinux_complete_init. */
2470 if (sbsec->initialized) {
2471 struct inode_security_struct *isec = inode->i_security;
2472 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2473 isec->sid = newsid;
2474 isec->initialized = 1;
2475 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002476
Stephen Smalley8aad3872006-03-22 00:09:13 -08002477 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002478 return -EOPNOTSUPP;
2479
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002480 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002481 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002482 if (!namep)
2483 return -ENOMEM;
2484 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002485 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002486
2487 if (value && len) {
2488 rc = security_sid_to_context(newsid, &context, &clen);
2489 if (rc) {
2490 kfree(namep);
2491 return rc;
2492 }
2493 *value = context;
2494 *len = clen;
2495 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002496
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002497 return 0;
2498}
2499
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2501{
2502 return may_create(dir, dentry, SECCLASS_FILE);
2503}
2504
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2506{
2507 int rc;
2508
Eric Paris828dfe12008-04-17 13:17:49 -04002509 rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 if (rc)
2511 return rc;
2512 return may_link(dir, old_dentry, MAY_LINK);
2513}
2514
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2516{
2517 int rc;
2518
2519 rc = secondary_ops->inode_unlink(dir, dentry);
2520 if (rc)
2521 return rc;
2522 return may_link(dir, dentry, MAY_UNLINK);
2523}
2524
2525static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2526{
2527 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2528}
2529
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2531{
2532 return may_create(dir, dentry, SECCLASS_DIR);
2533}
2534
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2536{
2537 return may_link(dir, dentry, MAY_RMDIR);
2538}
2539
2540static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2541{
2542 int rc;
2543
2544 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2545 if (rc)
2546 return rc;
2547
2548 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2549}
2550
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002552 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553{
2554 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2555}
2556
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557static int selinux_inode_readlink(struct dentry *dentry)
2558{
2559 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2560}
2561
2562static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2563{
2564 int rc;
2565
Eric Paris828dfe12008-04-17 13:17:49 -04002566 rc = secondary_ops->inode_follow_link(dentry, nameidata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 if (rc)
2568 return rc;
2569 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2570}
2571
2572static int selinux_inode_permission(struct inode *inode, int mask,
2573 struct nameidata *nd)
2574{
2575 int rc;
2576
2577 rc = secondary_ops->inode_permission(inode, mask, nd);
2578 if (rc)
2579 return rc;
2580
2581 if (!mask) {
2582 /* No permission to check. Existence test. */
2583 return 0;
2584 }
2585
2586 return inode_has_perm(current, inode,
Eric Parisb0c636b2008-02-28 12:58:40 -05002587 open_file_mask_to_av(inode->i_mode, mask), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588}
2589
2590static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2591{
2592 int rc;
2593
2594 rc = secondary_ops->inode_setattr(dentry, iattr);
2595 if (rc)
2596 return rc;
2597
2598 if (iattr->ia_valid & ATTR_FORCE)
2599 return 0;
2600
2601 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2602 ATTR_ATIME_SET | ATTR_MTIME_SET))
2603 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2604
2605 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2606}
2607
2608static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2609{
2610 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2611}
2612
Serge E. Hallynb5376772007-10-16 23:31:36 -07002613static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2614{
2615 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2616 sizeof XATTR_SECURITY_PREFIX - 1)) {
2617 if (!strcmp(name, XATTR_NAME_CAPS)) {
2618 if (!capable(CAP_SETFCAP))
2619 return -EPERM;
2620 } else if (!capable(CAP_SYS_ADMIN)) {
2621 /* A different attribute in the security namespace.
2622 Restrict to administrator. */
2623 return -EPERM;
2624 }
2625 }
2626
2627 /* Not an attribute we recognize, so just check the
2628 ordinary setattr permission. */
2629 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2630}
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2633{
2634 struct task_security_struct *tsec = current->security;
2635 struct inode *inode = dentry->d_inode;
2636 struct inode_security_struct *isec = inode->i_security;
2637 struct superblock_security_struct *sbsec;
2638 struct avc_audit_data ad;
2639 u32 newsid;
2640 int rc = 0;
2641
Serge E. Hallynb5376772007-10-16 23:31:36 -07002642 if (strcmp(name, XATTR_NAME_SELINUX))
2643 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645 sbsec = inode->i_sb->s_security;
2646 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2647 return -EOPNOTSUPP;
2648
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302649 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 return -EPERM;
2651
Eric Paris828dfe12008-04-17 13:17:49 -04002652 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002653 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654
2655 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2656 FILE__RELABELFROM, &ad);
2657 if (rc)
2658 return rc;
2659
2660 rc = security_context_to_sid(value, size, &newsid);
2661 if (rc)
2662 return rc;
2663
2664 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2665 FILE__RELABELTO, &ad);
2666 if (rc)
2667 return rc;
2668
2669 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002670 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 if (rc)
2672 return rc;
2673
2674 return avc_has_perm(newsid,
2675 sbsec->sid,
2676 SECCLASS_FILESYSTEM,
2677 FILESYSTEM__ASSOCIATE,
2678 &ad);
2679}
2680
2681static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002682 void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683{
2684 struct inode *inode = dentry->d_inode;
2685 struct inode_security_struct *isec = inode->i_security;
2686 u32 newsid;
2687 int rc;
2688
2689 if (strcmp(name, XATTR_NAME_SELINUX)) {
2690 /* Not an attribute we recognize, so nothing to do. */
2691 return;
2692 }
2693
2694 rc = security_context_to_sid(value, size, &newsid);
2695 if (rc) {
2696 printk(KERN_WARNING "%s: unable to obtain SID for context "
Andrew Mortonf0115e62008-03-06 10:05:08 +11002697 "%s, rc=%d\n", __func__, (char *)value, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 return;
2699 }
2700
2701 isec->sid = newsid;
2702 return;
2703}
2704
Eric Paris828dfe12008-04-17 13:17:49 -04002705static int selinux_inode_getxattr(struct dentry *dentry, char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2708}
2709
Eric Paris828dfe12008-04-17 13:17:49 -04002710static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711{
2712 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2713}
2714
Eric Paris828dfe12008-04-17 13:17:49 -04002715static int selinux_inode_removexattr(struct dentry *dentry, char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002717 if (strcmp(name, XATTR_NAME_SELINUX))
2718 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 /* No one is allowed to remove a SELinux security label.
2721 You can change the label, but all data must be labeled. */
2722 return -EACCES;
2723}
2724
James Morrisd381d8a2005-10-30 14:59:22 -08002725/*
2726 * Copy the in-core inode security context value to the user. If the
2727 * getxattr() prior to this succeeded, check to see if we need to
2728 * canonicalize the value to be finally returned to the user.
2729 *
2730 * Permission check is handled by selinux_inode_getxattr hook.
2731 */
David P. Quigley42492592008-02-04 22:29:39 -08002732static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
David P. Quigley42492592008-02-04 22:29:39 -08002734 u32 size;
2735 int error;
2736 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002739 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2740 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741
David P. Quigley42492592008-02-04 22:29:39 -08002742 error = security_sid_to_context(isec->sid, &context, &size);
2743 if (error)
2744 return error;
2745 error = size;
2746 if (alloc) {
2747 *buffer = context;
2748 goto out_nofree;
2749 }
2750 kfree(context);
2751out_nofree:
2752 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753}
2754
2755static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002756 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757{
2758 struct inode_security_struct *isec = inode->i_security;
2759 u32 newsid;
2760 int rc;
2761
2762 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2763 return -EOPNOTSUPP;
2764
2765 if (!value || !size)
2766 return -EACCES;
2767
Eric Paris828dfe12008-04-17 13:17:49 -04002768 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 if (rc)
2770 return rc;
2771
2772 isec->sid = newsid;
2773 return 0;
2774}
2775
2776static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2777{
2778 const int len = sizeof(XATTR_NAME_SELINUX);
2779 if (buffer && len <= buffer_size)
2780 memcpy(buffer, XATTR_NAME_SELINUX, len);
2781 return len;
2782}
2783
Serge E. Hallynb5376772007-10-16 23:31:36 -07002784static int selinux_inode_need_killpriv(struct dentry *dentry)
2785{
2786 return secondary_ops->inode_need_killpriv(dentry);
2787}
2788
2789static int selinux_inode_killpriv(struct dentry *dentry)
2790{
2791 return secondary_ops->inode_killpriv(dentry);
2792}
2793
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02002794static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2795{
2796 struct inode_security_struct *isec = inode->i_security;
2797 *secid = isec->sid;
2798}
2799
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800/* file security operations */
2801
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002802static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002804 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002805 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806
2807 if (!mask) {
2808 /* No permission to check. Existence test. */
2809 return 0;
2810 }
2811
2812 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2813 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2814 mask |= MAY_APPEND;
2815
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002816 rc = file_has_perm(current, file,
2817 file_mask_to_av(inode->i_mode, mask));
2818 if (rc)
2819 return rc;
2820
2821 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822}
2823
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002824static int selinux_file_permission(struct file *file, int mask)
2825{
2826 struct inode *inode = file->f_path.dentry->d_inode;
2827 struct task_security_struct *tsec = current->security;
2828 struct file_security_struct *fsec = file->f_security;
2829 struct inode_security_struct *isec = inode->i_security;
2830
2831 if (!mask) {
2832 /* No permission to check. Existence test. */
2833 return 0;
2834 }
2835
2836 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2837 && fsec->pseqno == avc_policy_seqno())
2838 return selinux_netlbl_inode_permission(inode, mask);
2839
2840 return selinux_revalidate_file_permission(file, mask);
2841}
2842
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843static int selinux_file_alloc_security(struct file *file)
2844{
2845 return file_alloc_security(file);
2846}
2847
2848static void selinux_file_free_security(struct file *file)
2849{
2850 file_free_security(file);
2851}
2852
2853static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2854 unsigned long arg)
2855{
2856 int error = 0;
2857
2858 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04002859 case FIONREAD:
2860 /* fall through */
2861 case FIBMAP:
2862 /* fall through */
2863 case FIGETBSZ:
2864 /* fall through */
2865 case EXT2_IOC_GETFLAGS:
2866 /* fall through */
2867 case EXT2_IOC_GETVERSION:
2868 error = file_has_perm(current, file, FILE__GETATTR);
2869 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
Eric Paris828dfe12008-04-17 13:17:49 -04002871 case EXT2_IOC_SETFLAGS:
2872 /* fall through */
2873 case EXT2_IOC_SETVERSION:
2874 error = file_has_perm(current, file, FILE__SETATTR);
2875 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
Eric Paris828dfe12008-04-17 13:17:49 -04002877 /* sys_ioctl() checks */
2878 case FIONBIO:
2879 /* fall through */
2880 case FIOASYNC:
2881 error = file_has_perm(current, file, 0);
2882 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Eric Paris828dfe12008-04-17 13:17:49 -04002884 case KDSKBENT:
2885 case KDSKBSENT:
2886 error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
2887 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
Eric Paris828dfe12008-04-17 13:17:49 -04002889 /* default case assumes that the command will go
2890 * to the file's ioctl() function.
2891 */
2892 default:
2893 error = file_has_perm(current, file, FILE__IOCTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 }
2895 return error;
2896}
2897
2898static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2899{
2900#ifndef CONFIG_PPC32
2901 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2902 /*
2903 * We are making executable an anonymous mapping or a
2904 * private file mapping that will also be writable.
2905 * This has an additional check.
2906 */
2907 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2908 if (rc)
2909 return rc;
2910 }
2911#endif
2912
2913 if (file) {
2914 /* read access is always possible with a mapping */
2915 u32 av = FILE__READ;
2916
2917 /* write access only matters if the mapping is shared */
2918 if (shared && (prot & PROT_WRITE))
2919 av |= FILE__WRITE;
2920
2921 if (prot & PROT_EXEC)
2922 av |= FILE__EXECUTE;
2923
2924 return file_has_perm(current, file, av);
2925 }
2926 return 0;
2927}
2928
2929static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002930 unsigned long prot, unsigned long flags,
2931 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
Eric Parised032182007-06-28 15:55:21 -04002933 int rc = 0;
Eric Paris828dfe12008-04-17 13:17:49 -04002934 u32 sid = ((struct task_security_struct *)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
Eric Parised032182007-06-28 15:55:21 -04002936 if (addr < mmap_min_addr)
2937 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2938 MEMPROTECT__MMAP_ZERO, NULL);
2939 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 return rc;
2941
2942 if (selinux_checkreqprot)
2943 prot = reqprot;
2944
2945 return file_map_prot_check(file, prot,
2946 (flags & MAP_TYPE) == MAP_SHARED);
2947}
2948
2949static int selinux_file_mprotect(struct vm_area_struct *vma,
2950 unsigned long reqprot,
2951 unsigned long prot)
2952{
2953 int rc;
2954
2955 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2956 if (rc)
2957 return rc;
2958
2959 if (selinux_checkreqprot)
2960 prot = reqprot;
2961
2962#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002963 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2964 rc = 0;
2965 if (vma->vm_start >= vma->vm_mm->start_brk &&
2966 vma->vm_end <= vma->vm_mm->brk) {
2967 rc = task_has_perm(current, current,
2968 PROCESS__EXECHEAP);
2969 } else if (!vma->vm_file &&
2970 vma->vm_start <= vma->vm_mm->start_stack &&
2971 vma->vm_end >= vma->vm_mm->start_stack) {
2972 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2973 } else if (vma->vm_file && vma->anon_vma) {
2974 /*
2975 * We are making executable a file mapping that has
2976 * had some COW done. Since pages might have been
2977 * written, check ability to execute the possibly
2978 * modified content. This typically should only
2979 * occur for text relocations.
2980 */
2981 rc = file_has_perm(current, vma->vm_file,
2982 FILE__EXECMOD);
2983 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07002984 if (rc)
2985 return rc;
2986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987#endif
2988
2989 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2990}
2991
2992static int selinux_file_lock(struct file *file, unsigned int cmd)
2993{
2994 return file_has_perm(current, file, FILE__LOCK);
2995}
2996
2997static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2998 unsigned long arg)
2999{
3000 int err = 0;
3001
3002 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003003 case F_SETFL:
3004 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3005 err = -EINVAL;
3006 break;
3007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Eric Paris828dfe12008-04-17 13:17:49 -04003009 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
3010 err = file_has_perm(current, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003012 }
3013 /* fall through */
3014 case F_SETOWN:
3015 case F_SETSIG:
3016 case F_GETFL:
3017 case F_GETOWN:
3018 case F_GETSIG:
3019 /* Just check FD__USE permission */
3020 err = file_has_perm(current, file, 0);
3021 break;
3022 case F_GETLK:
3023 case F_SETLK:
3024 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003026 case F_GETLK64:
3027 case F_SETLK64:
3028 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003030 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3031 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003033 }
3034 err = file_has_perm(current, file, FILE__LOCK);
3035 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 }
3037
3038 return err;
3039}
3040
3041static int selinux_file_set_fowner(struct file *file)
3042{
3043 struct task_security_struct *tsec;
3044 struct file_security_struct *fsec;
3045
3046 tsec = current->security;
3047 fsec = file->f_security;
3048 fsec->fown_sid = tsec->sid;
3049
3050 return 0;
3051}
3052
3053static int selinux_file_send_sigiotask(struct task_struct *tsk,
3054 struct fown_struct *fown, int signum)
3055{
Eric Paris828dfe12008-04-17 13:17:49 -04003056 struct file *file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 u32 perm;
3058 struct task_security_struct *tsec;
3059 struct file_security_struct *fsec;
3060
3061 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003062 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
3064 tsec = tsk->security;
3065 fsec = file->f_security;
3066
3067 if (!signum)
3068 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3069 else
3070 perm = signal_to_av(signum);
3071
3072 return avc_has_perm(fsec->fown_sid, tsec->sid,
3073 SECCLASS_PROCESS, perm, NULL);
3074}
3075
3076static int selinux_file_receive(struct file *file)
3077{
3078 return file_has_perm(current, file, file_to_av(file));
3079}
3080
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003081static int selinux_dentry_open(struct file *file)
3082{
3083 struct file_security_struct *fsec;
3084 struct inode *inode;
3085 struct inode_security_struct *isec;
3086 inode = file->f_path.dentry->d_inode;
3087 fsec = file->f_security;
3088 isec = inode->i_security;
3089 /*
3090 * Save inode label and policy sequence number
3091 * at open-time so that selinux_file_permission
3092 * can determine whether revalidation is necessary.
3093 * Task label is already saved in the file security
3094 * struct as its SID.
3095 */
3096 fsec->isid = isec->sid;
3097 fsec->pseqno = avc_policy_seqno();
3098 /*
3099 * Since the inode label or policy seqno may have changed
3100 * between the selinux_inode_permission check and the saving
3101 * of state above, recheck that access is still permitted.
3102 * Otherwise, access might never be revalidated against the
3103 * new inode label or new policy.
3104 * This check is not redundant - do not remove.
3105 */
3106 return inode_has_perm(current, inode, file_to_av(file), NULL);
3107}
3108
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109/* task security operations */
3110
3111static int selinux_task_create(unsigned long clone_flags)
3112{
3113 int rc;
3114
3115 rc = secondary_ops->task_create(clone_flags);
3116 if (rc)
3117 return rc;
3118
3119 return task_has_perm(current, current, PROCESS__FORK);
3120}
3121
3122static int selinux_task_alloc_security(struct task_struct *tsk)
3123{
3124 struct task_security_struct *tsec1, *tsec2;
3125 int rc;
3126
3127 tsec1 = current->security;
3128
3129 rc = task_alloc_security(tsk);
3130 if (rc)
3131 return rc;
3132 tsec2 = tsk->security;
3133
3134 tsec2->osid = tsec1->osid;
3135 tsec2->sid = tsec1->sid;
3136
Michael LeMay28eba5b2006-06-27 02:53:42 -07003137 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 tsec2->exec_sid = tsec1->exec_sid;
3139 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003140 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003141 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 return 0;
3144}
3145
3146static void selinux_task_free_security(struct task_struct *tsk)
3147{
3148 task_free_security(tsk);
3149}
3150
3151static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3152{
3153 /* Since setuid only affects the current process, and
3154 since the SELinux controls are not based on the Linux
3155 identity attributes, SELinux does not need to control
3156 this operation. However, SELinux does control the use
3157 of the CAP_SETUID and CAP_SETGID capabilities using the
3158 capable hook. */
3159 return 0;
3160}
3161
3162static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3163{
Eric Paris828dfe12008-04-17 13:17:49 -04003164 return secondary_ops->task_post_setuid(id0, id1, id2, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165}
3166
3167static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3168{
3169 /* See the comment for setuid above. */
3170 return 0;
3171}
3172
3173static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3174{
3175 return task_has_perm(current, p, PROCESS__SETPGID);
3176}
3177
3178static int selinux_task_getpgid(struct task_struct *p)
3179{
3180 return task_has_perm(current, p, PROCESS__GETPGID);
3181}
3182
3183static int selinux_task_getsid(struct task_struct *p)
3184{
3185 return task_has_perm(current, p, PROCESS__GETSESSION);
3186}
3187
David Quigleyf9008e42006-06-30 01:55:46 -07003188static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3189{
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003190 struct task_security_struct *tsec = p->security;
3191 *secid = tsec->sid;
David Quigleyf9008e42006-06-30 01:55:46 -07003192}
3193
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194static int selinux_task_setgroups(struct group_info *group_info)
3195{
3196 /* See the comment for setuid above. */
3197 return 0;
3198}
3199
3200static int selinux_task_setnice(struct task_struct *p, int nice)
3201{
3202 int rc;
3203
3204 rc = secondary_ops->task_setnice(p, nice);
3205 if (rc)
3206 return rc;
3207
Eric Paris828dfe12008-04-17 13:17:49 -04003208 return task_has_perm(current, p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209}
3210
James Morris03e68062006-06-23 02:03:58 -07003211static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3212{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003213 int rc;
3214
3215 rc = secondary_ops->task_setioprio(p, ioprio);
3216 if (rc)
3217 return rc;
3218
James Morris03e68062006-06-23 02:03:58 -07003219 return task_has_perm(current, p, PROCESS__SETSCHED);
3220}
3221
David Quigleya1836a42006-06-30 01:55:49 -07003222static int selinux_task_getioprio(struct task_struct *p)
3223{
3224 return task_has_perm(current, p, PROCESS__GETSCHED);
3225}
3226
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3228{
3229 struct rlimit *old_rlim = current->signal->rlim + resource;
3230 int rc;
3231
3232 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3233 if (rc)
3234 return rc;
3235
3236 /* Control the ability to change the hard limit (whether
3237 lowering or raising it), so that the hard limit can
3238 later be used as a safe reset point for the soft limit
3239 upon context transitions. See selinux_bprm_apply_creds. */
3240 if (old_rlim->rlim_max != new_rlim->rlim_max)
3241 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3242
3243 return 0;
3244}
3245
3246static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3247{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003248 int rc;
3249
3250 rc = secondary_ops->task_setscheduler(p, policy, lp);
3251 if (rc)
3252 return rc;
3253
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 return task_has_perm(current, p, PROCESS__SETSCHED);
3255}
3256
3257static int selinux_task_getscheduler(struct task_struct *p)
3258{
3259 return task_has_perm(current, p, PROCESS__GETSCHED);
3260}
3261
David Quigley35601542006-06-23 02:04:01 -07003262static int selinux_task_movememory(struct task_struct *p)
3263{
3264 return task_has_perm(current, p, PROCESS__SETSCHED);
3265}
3266
David Quigleyf9008e42006-06-30 01:55:46 -07003267static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3268 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
3270 u32 perm;
3271 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003272 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
David Quigleyf9008e42006-06-30 01:55:46 -07003274 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 if (rc)
3276 return rc;
3277
Oleg Nesterov621d3122005-10-30 15:03:45 -08003278 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 return 0;
3280
3281 if (!sig)
3282 perm = PROCESS__SIGNULL; /* null signal; existence test */
3283 else
3284 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003285 tsec = p->security;
3286 if (secid)
3287 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3288 else
3289 rc = task_has_perm(current, p, perm);
3290 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291}
3292
3293static int selinux_task_prctl(int option,
3294 unsigned long arg2,
3295 unsigned long arg3,
3296 unsigned long arg4,
3297 unsigned long arg5)
3298{
3299 /* The current prctl operations do not appear to require
3300 any SELinux controls since they merely observe or modify
3301 the state of the current process. */
3302 return 0;
3303}
3304
3305static int selinux_task_wait(struct task_struct *p)
3306{
Eric Paris8a535142007-10-22 16:10:31 -04003307 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308}
3309
3310static void selinux_task_reparent_to_init(struct task_struct *p)
3311{
Eric Paris828dfe12008-04-17 13:17:49 -04003312 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
3314 secondary_ops->task_reparent_to_init(p);
3315
3316 tsec = p->security;
3317 tsec->osid = tsec->sid;
3318 tsec->sid = SECINITSID_KERNEL;
3319 return;
3320}
3321
3322static void selinux_task_to_inode(struct task_struct *p,
3323 struct inode *inode)
3324{
3325 struct task_security_struct *tsec = p->security;
3326 struct inode_security_struct *isec = inode->i_security;
3327
3328 isec->sid = tsec->sid;
3329 isec->initialized = 1;
3330 return;
3331}
3332
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003334static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3335 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336{
3337 int offset, ihlen, ret = -EINVAL;
3338 struct iphdr _iph, *ih;
3339
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003340 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3342 if (ih == NULL)
3343 goto out;
3344
3345 ihlen = ih->ihl * 4;
3346 if (ihlen < sizeof(_iph))
3347 goto out;
3348
3349 ad->u.net.v4info.saddr = ih->saddr;
3350 ad->u.net.v4info.daddr = ih->daddr;
3351 ret = 0;
3352
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003353 if (proto)
3354 *proto = ih->protocol;
3355
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003357 case IPPROTO_TCP: {
3358 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Eric Paris828dfe12008-04-17 13:17:49 -04003360 if (ntohs(ih->frag_off) & IP_OFFSET)
3361 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362
3363 offset += ihlen;
3364 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3365 if (th == NULL)
3366 break;
3367
3368 ad->u.net.sport = th->source;
3369 ad->u.net.dport = th->dest;
3370 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
Eric Paris828dfe12008-04-17 13:17:49 -04003373 case IPPROTO_UDP: {
3374 struct udphdr _udph, *uh;
3375
3376 if (ntohs(ih->frag_off) & IP_OFFSET)
3377 break;
3378
3379 offset += ihlen;
3380 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3381 if (uh == NULL)
3382 break;
3383
3384 ad->u.net.sport = uh->source;
3385 ad->u.net.dport = uh->dest;
3386 break;
3387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
James Morris2ee92d42006-11-13 16:09:01 -08003389 case IPPROTO_DCCP: {
3390 struct dccp_hdr _dccph, *dh;
3391
3392 if (ntohs(ih->frag_off) & IP_OFFSET)
3393 break;
3394
3395 offset += ihlen;
3396 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3397 if (dh == NULL)
3398 break;
3399
3400 ad->u.net.sport = dh->dccph_sport;
3401 ad->u.net.dport = dh->dccph_dport;
3402 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003403 }
James Morris2ee92d42006-11-13 16:09:01 -08003404
Eric Paris828dfe12008-04-17 13:17:49 -04003405 default:
3406 break;
3407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408out:
3409 return ret;
3410}
3411
3412#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3413
3414/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003415static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3416 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417{
3418 u8 nexthdr;
3419 int ret = -EINVAL, offset;
3420 struct ipv6hdr _ipv6h, *ip6;
3421
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003422 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3424 if (ip6 == NULL)
3425 goto out;
3426
3427 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3428 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3429 ret = 0;
3430
3431 nexthdr = ip6->nexthdr;
3432 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003433 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 if (offset < 0)
3435 goto out;
3436
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003437 if (proto)
3438 *proto = nexthdr;
3439
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 switch (nexthdr) {
3441 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003442 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443
3444 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3445 if (th == NULL)
3446 break;
3447
3448 ad->u.net.sport = th->source;
3449 ad->u.net.dport = th->dest;
3450 break;
3451 }
3452
3453 case IPPROTO_UDP: {
3454 struct udphdr _udph, *uh;
3455
3456 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3457 if (uh == NULL)
3458 break;
3459
3460 ad->u.net.sport = uh->source;
3461 ad->u.net.dport = uh->dest;
3462 break;
3463 }
3464
James Morris2ee92d42006-11-13 16:09:01 -08003465 case IPPROTO_DCCP: {
3466 struct dccp_hdr _dccph, *dh;
3467
3468 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3469 if (dh == NULL)
3470 break;
3471
3472 ad->u.net.sport = dh->dccph_sport;
3473 ad->u.net.dport = dh->dccph_dport;
3474 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003475 }
James Morris2ee92d42006-11-13 16:09:01 -08003476
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 /* includes fragments */
3478 default:
3479 break;
3480 }
3481out:
3482 return ret;
3483}
3484
3485#endif /* IPV6 */
3486
3487static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003488 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
3490 int ret = 0;
3491
3492 switch (ad->u.net.family) {
3493 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003494 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495 if (ret || !addrp)
3496 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3498 &ad->u.net.v4info.daddr);
3499 break;
3500
3501#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3502 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003503 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 if (ret || !addrp)
3505 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3507 &ad->u.net.v6info.daddr);
3508 break;
3509#endif /* IPV6 */
3510 default:
3511 break;
3512 }
3513
Paul Moore71f1cb02008-01-29 08:51:16 -05003514 if (unlikely(ret))
3515 printk(KERN_WARNING
3516 "SELinux: failure in selinux_parse_skb(),"
3517 " unable to parse packet\n");
3518
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 return ret;
3520}
3521
Paul Moore4f6a9932007-03-01 14:35:22 -05003522/**
Paul Moore220deb92008-01-29 08:38:23 -05003523 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003524 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003525 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003526 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003527 *
3528 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003529 * Check the various different forms of network peer labeling and determine
3530 * the peer label/SID for the packet; most of the magic actually occurs in
3531 * the security server function security_net_peersid_cmp(). The function
3532 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3533 * or -EACCES if @sid is invalid due to inconsistencies with the different
3534 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003535 *
3536 */
Paul Moore220deb92008-01-29 08:38:23 -05003537static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003538{
Paul Moore71f1cb02008-01-29 08:51:16 -05003539 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003540 u32 xfrm_sid;
3541 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003542 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003543
3544 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003545 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003546
Paul Moore71f1cb02008-01-29 08:51:16 -05003547 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3548 if (unlikely(err)) {
3549 printk(KERN_WARNING
3550 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3551 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003552 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003553 }
Paul Moore220deb92008-01-29 08:38:23 -05003554
3555 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003556}
3557
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558/* socket security operations */
3559static int socket_has_perm(struct task_struct *task, struct socket *sock,
3560 u32 perms)
3561{
3562 struct inode_security_struct *isec;
3563 struct task_security_struct *tsec;
3564 struct avc_audit_data ad;
3565 int err = 0;
3566
3567 tsec = task->security;
3568 isec = SOCK_INODE(sock)->i_security;
3569
3570 if (isec->sid == SECINITSID_KERNEL)
3571 goto out;
3572
Eric Paris828dfe12008-04-17 13:17:49 -04003573 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 ad.u.net.sk = sock->sk;
3575 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3576
3577out:
3578 return err;
3579}
3580
3581static int selinux_socket_create(int family, int type,
3582 int protocol, int kern)
3583{
3584 int err = 0;
3585 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003586 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
3588 if (kern)
3589 goto out;
3590
3591 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003592 newsid = tsec->sockcreate_sid ? : tsec->sid;
3593 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 socket_type_to_security_class(family, type,
3595 protocol), SOCKET__CREATE, NULL);
3596
3597out:
3598 return err;
3599}
3600
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003601static int selinux_socket_post_create(struct socket *sock, int family,
3602 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003604 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 struct inode_security_struct *isec;
3606 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003607 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003608 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
3610 isec = SOCK_INODE(sock)->i_security;
3611
3612 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003613 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003615 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 isec->initialized = 1;
3617
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003618 if (sock->sk) {
3619 sksec = sock->sk->sk_security;
3620 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003621 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003622 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003623 }
3624
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003625 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626}
3627
3628/* Range of port numbers used to automatically bind.
3629 Need to determine whether we should perform a name_bind
3630 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
3632static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3633{
3634 u16 family;
3635 int err;
3636
3637 err = socket_has_perm(current, sock, SOCKET__BIND);
3638 if (err)
3639 goto out;
3640
3641 /*
3642 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003643 * Multiple address binding for SCTP is not supported yet: we just
3644 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 */
3646 family = sock->sk->sk_family;
3647 if (family == PF_INET || family == PF_INET6) {
3648 char *addrp;
3649 struct inode_security_struct *isec;
3650 struct task_security_struct *tsec;
3651 struct avc_audit_data ad;
3652 struct sockaddr_in *addr4 = NULL;
3653 struct sockaddr_in6 *addr6 = NULL;
3654 unsigned short snum;
3655 struct sock *sk = sock->sk;
3656 u32 sid, node_perm, addrlen;
3657
3658 tsec = current->security;
3659 isec = SOCK_INODE(sock)->i_security;
3660
3661 if (family == PF_INET) {
3662 addr4 = (struct sockaddr_in *)address;
3663 snum = ntohs(addr4->sin_port);
3664 addrlen = sizeof(addr4->sin_addr.s_addr);
3665 addrp = (char *)&addr4->sin_addr.s_addr;
3666 } else {
3667 addr6 = (struct sockaddr_in6 *)address;
3668 snum = ntohs(addr6->sin6_port);
3669 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3670 addrp = (char *)&addr6->sin6_addr.s6_addr;
3671 }
3672
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003673 if (snum) {
3674 int low, high;
3675
3676 inet_get_local_port_range(&low, &high);
3677
3678 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003679 err = sel_netport_sid(sk->sk_protocol,
3680 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003681 if (err)
3682 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003683 AVC_AUDIT_DATA_INIT(&ad, NET);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003684 ad.u.net.sport = htons(snum);
3685 ad.u.net.family = family;
3686 err = avc_has_perm(isec->sid, sid,
3687 isec->sclass,
3688 SOCKET__NAME_BIND, &ad);
3689 if (err)
3690 goto out;
3691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 }
Eric Paris828dfe12008-04-17 13:17:49 -04003693
3694 switch (isec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003695 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 node_perm = TCP_SOCKET__NODE_BIND;
3697 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003698
James Morris13402582005-09-30 14:24:34 -04003699 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 node_perm = UDP_SOCKET__NODE_BIND;
3701 break;
James Morris2ee92d42006-11-13 16:09:01 -08003702
3703 case SECCLASS_DCCP_SOCKET:
3704 node_perm = DCCP_SOCKET__NODE_BIND;
3705 break;
3706
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 default:
3708 node_perm = RAWIP_SOCKET__NODE_BIND;
3709 break;
3710 }
Eric Paris828dfe12008-04-17 13:17:49 -04003711
Paul Moore224dfbd2008-01-29 08:38:13 -05003712 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 if (err)
3714 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003715
3716 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 ad.u.net.sport = htons(snum);
3718 ad.u.net.family = family;
3719
3720 if (family == PF_INET)
3721 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3722 else
3723 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3724
3725 err = avc_has_perm(isec->sid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003726 isec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 if (err)
3728 goto out;
3729 }
3730out:
3731 return err;
3732}
3733
3734static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3735{
3736 struct inode_security_struct *isec;
3737 int err;
3738
3739 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3740 if (err)
3741 return err;
3742
3743 /*
James Morris2ee92d42006-11-13 16:09:01 -08003744 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 */
3746 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003747 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3748 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 struct sock *sk = sock->sk;
3750 struct avc_audit_data ad;
3751 struct sockaddr_in *addr4 = NULL;
3752 struct sockaddr_in6 *addr6 = NULL;
3753 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003754 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
3756 if (sk->sk_family == PF_INET) {
3757 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003758 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 return -EINVAL;
3760 snum = ntohs(addr4->sin_port);
3761 } else {
3762 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003763 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 return -EINVAL;
3765 snum = ntohs(addr6->sin6_port);
3766 }
3767
Paul Moore3e112172008-04-10 10:48:14 -04003768 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 if (err)
3770 goto out;
3771
James Morris2ee92d42006-11-13 16:09:01 -08003772 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3773 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3774
Eric Paris828dfe12008-04-17 13:17:49 -04003775 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 ad.u.net.dport = htons(snum);
3777 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003778 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 if (err)
3780 goto out;
3781 }
3782
3783out:
3784 return err;
3785}
3786
3787static int selinux_socket_listen(struct socket *sock, int backlog)
3788{
3789 return socket_has_perm(current, sock, SOCKET__LISTEN);
3790}
3791
3792static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3793{
3794 int err;
3795 struct inode_security_struct *isec;
3796 struct inode_security_struct *newisec;
3797
3798 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3799 if (err)
3800 return err;
3801
3802 newisec = SOCK_INODE(newsock)->i_security;
3803
3804 isec = SOCK_INODE(sock)->i_security;
3805 newisec->sclass = isec->sclass;
3806 newisec->sid = isec->sid;
3807 newisec->initialized = 1;
3808
3809 return 0;
3810}
3811
3812static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04003813 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003815 int rc;
3816
3817 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3818 if (rc)
3819 return rc;
3820
3821 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822}
3823
3824static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3825 int size, int flags)
3826{
3827 return socket_has_perm(current, sock, SOCKET__READ);
3828}
3829
3830static int selinux_socket_getsockname(struct socket *sock)
3831{
3832 return socket_has_perm(current, sock, SOCKET__GETATTR);
3833}
3834
3835static int selinux_socket_getpeername(struct socket *sock)
3836{
3837 return socket_has_perm(current, sock, SOCKET__GETATTR);
3838}
3839
Eric Paris828dfe12008-04-17 13:17:49 -04003840static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
Paul Mooref8687af2006-10-30 15:22:15 -08003842 int err;
3843
3844 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3845 if (err)
3846 return err;
3847
3848 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849}
3850
3851static int selinux_socket_getsockopt(struct socket *sock, int level,
3852 int optname)
3853{
3854 return socket_has_perm(current, sock, SOCKET__GETOPT);
3855}
3856
3857static int selinux_socket_shutdown(struct socket *sock, int how)
3858{
3859 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3860}
3861
3862static int selinux_socket_unix_stream_connect(struct socket *sock,
3863 struct socket *other,
3864 struct sock *newsk)
3865{
3866 struct sk_security_struct *ssec;
3867 struct inode_security_struct *isec;
3868 struct inode_security_struct *other_isec;
3869 struct avc_audit_data ad;
3870 int err;
3871
3872 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3873 if (err)
3874 return err;
3875
3876 isec = SOCK_INODE(sock)->i_security;
3877 other_isec = SOCK_INODE(other)->i_security;
3878
Eric Paris828dfe12008-04-17 13:17:49 -04003879 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 ad.u.net.sk = other->sk;
3881
3882 err = avc_has_perm(isec->sid, other_isec->sid,
3883 isec->sclass,
3884 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3885 if (err)
3886 return err;
3887
3888 /* connecting socket */
3889 ssec = sock->sk->sk_security;
3890 ssec->peer_sid = other_isec->sid;
Eric Paris828dfe12008-04-17 13:17:49 -04003891
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 /* server child socket */
3893 ssec = newsk->sk_security;
3894 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003895 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3896
3897 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898}
3899
3900static int selinux_socket_unix_may_send(struct socket *sock,
3901 struct socket *other)
3902{
3903 struct inode_security_struct *isec;
3904 struct inode_security_struct *other_isec;
3905 struct avc_audit_data ad;
3906 int err;
3907
3908 isec = SOCK_INODE(sock)->i_security;
3909 other_isec = SOCK_INODE(other)->i_security;
3910
Eric Paris828dfe12008-04-17 13:17:49 -04003911 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 ad.u.net.sk = other->sk;
3913
3914 err = avc_has_perm(isec->sid, other_isec->sid,
3915 isec->sclass, SOCKET__SENDTO, &ad);
3916 if (err)
3917 return err;
3918
3919 return 0;
3920}
3921
Paul Mooreeffad8d2008-01-29 08:49:27 -05003922static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3923 u32 peer_sid,
3924 struct avc_audit_data *ad)
3925{
3926 int err;
3927 u32 if_sid;
3928 u32 node_sid;
3929
3930 err = sel_netif_sid(ifindex, &if_sid);
3931 if (err)
3932 return err;
3933 err = avc_has_perm(peer_sid, if_sid,
3934 SECCLASS_NETIF, NETIF__INGRESS, ad);
3935 if (err)
3936 return err;
3937
3938 err = sel_netnode_sid(addrp, family, &node_sid);
3939 if (err)
3940 return err;
3941 return avc_has_perm(peer_sid, node_sid,
3942 SECCLASS_NODE, NODE__RECVFROM, ad);
3943}
3944
Paul Moore220deb92008-01-29 08:38:23 -05003945static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3946 struct sk_buff *skb,
3947 struct avc_audit_data *ad,
3948 u16 family,
3949 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950{
Paul Moore220deb92008-01-29 08:38:23 -05003951 int err;
3952 struct sk_security_struct *sksec = sk->sk_security;
3953 u16 sk_class;
3954 u32 netif_perm, node_perm, recv_perm;
3955 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003956
Paul Moore220deb92008-01-29 08:38:23 -05003957 sk_sid = sksec->sid;
3958 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Paul Moore220deb92008-01-29 08:38:23 -05003960 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 case SECCLASS_UDP_SOCKET:
3962 netif_perm = NETIF__UDP_RECV;
3963 node_perm = NODE__UDP_RECV;
3964 recv_perm = UDP_SOCKET__RECV_MSG;
3965 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 case SECCLASS_TCP_SOCKET:
3967 netif_perm = NETIF__TCP_RECV;
3968 node_perm = NODE__TCP_RECV;
3969 recv_perm = TCP_SOCKET__RECV_MSG;
3970 break;
James Morris2ee92d42006-11-13 16:09:01 -08003971 case SECCLASS_DCCP_SOCKET:
3972 netif_perm = NETIF__DCCP_RECV;
3973 node_perm = NODE__DCCP_RECV;
3974 recv_perm = DCCP_SOCKET__RECV_MSG;
3975 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 default:
3977 netif_perm = NETIF__RAWIP_RECV;
3978 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003979 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 break;
3981 }
3982
Paul Moore220deb92008-01-29 08:38:23 -05003983 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003985 return err;
3986 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3987 if (err)
3988 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04003989
Paul Moore224dfbd2008-01-29 08:38:13 -05003990 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003992 return err;
3993 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05003995 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
Paul Moore220deb92008-01-29 08:38:23 -05003997 if (!recv_perm)
3998 return 0;
Paul Moore3e112172008-04-10 10:48:14 -04003999 err = sel_netport_sid(sk->sk_protocol,
4000 ntohs(ad->u.net.sport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004001 if (unlikely(err)) {
4002 printk(KERN_WARNING
4003 "SELinux: failure in"
4004 " selinux_sock_rcv_skb_iptables_compat(),"
4005 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05004006 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004007 }
Paul Moore220deb92008-01-29 08:38:23 -05004008 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4009}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Paul Moore220deb92008-01-29 08:38:23 -05004011static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4012 struct avc_audit_data *ad,
4013 u16 family, char *addrp)
4014{
4015 int err;
4016 struct sk_security_struct *sksec = sk->sk_security;
4017 u32 peer_sid;
4018 u32 sk_sid = sksec->sid;
4019
4020 if (selinux_compat_net)
4021 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
4022 family, addrp);
4023 else
4024 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4025 PACKET__RECV, ad);
4026 if (err)
4027 return err;
4028
4029 if (selinux_policycap_netpeer) {
4030 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004032 return err;
4033 err = avc_has_perm(sk_sid, peer_sid,
4034 SECCLASS_PEER, PEER__RECV, ad);
4035 } else {
4036 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
4037 if (err)
4038 return err;
4039 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004041
James Morris4e5ab4c2006-06-09 00:33:33 -07004042 return err;
4043}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004044
James Morris4e5ab4c2006-06-09 00:33:33 -07004045static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4046{
Paul Moore220deb92008-01-29 08:38:23 -05004047 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004048 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004049 u16 family = sk->sk_family;
4050 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004051 struct avc_audit_data ad;
4052 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07004053
James Morris4e5ab4c2006-06-09 00:33:33 -07004054 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004055 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004056
4057 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004058 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004059 family = PF_INET;
4060
James Morris4e5ab4c2006-06-09 00:33:33 -07004061 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004062 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07004063 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004064 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004065 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004066 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004067
Paul Moore220deb92008-01-29 08:38:23 -05004068 /* If any sort of compatibility mode is enabled then handoff processing
4069 * to the selinux_sock_rcv_skb_compat() function to deal with the
4070 * special handling. We do this in an attempt to keep this function
4071 * as fast and as clean as possible. */
4072 if (selinux_compat_net || !selinux_policycap_netpeer)
4073 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4074 family, addrp);
4075
Paul Moored621d352008-01-29 08:43:36 -05004076 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4077 u32 peer_sid;
4078
4079 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4080 if (err)
4081 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004082 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4083 peer_sid, &ad);
4084 if (err)
4085 return err;
Paul Moored621d352008-01-29 08:43:36 -05004086 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4087 PEER__RECV, &ad);
4088 }
4089
Paul Mooreeffad8d2008-01-29 08:49:27 -05004090 if (selinux_secmark_enabled()) {
4091 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4092 PACKET__RECV, &ad);
4093 if (err)
4094 return err;
4095 }
4096
Paul Moored621d352008-01-29 08:43:36 -05004097 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098}
4099
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004100static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4101 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102{
4103 int err = 0;
4104 char *scontext;
4105 u32 scontext_len;
4106 struct sk_security_struct *ssec;
4107 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004108 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109
4110 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004111
Paul Moore3de4bab2006-11-17 17:38:54 -05004112 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4113 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004114 ssec = sock->sk->sk_security;
4115 peer_sid = ssec->peer_sid;
4116 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004117 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 err = -ENOPROTOOPT;
4119 goto out;
4120 }
4121
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004122 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4123
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 if (err)
4125 goto out;
4126
4127 if (scontext_len > len) {
4128 err = -ERANGE;
4129 goto out_len;
4130 }
4131
4132 if (copy_to_user(optval, scontext, scontext_len))
4133 err = -EFAULT;
4134
4135out_len:
4136 if (put_user(scontext_len, optlen))
4137 err = -EFAULT;
4138
4139 kfree(scontext);
Eric Paris828dfe12008-04-17 13:17:49 -04004140out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 return err;
4142}
4143
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004144static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004145{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004146 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004147 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004148
Paul Moore75e22912008-01-29 08:38:04 -05004149 if (sock)
4150 family = sock->sk->sk_family;
4151 else if (skb && skb->sk)
4152 family = skb->sk->sk_family;
4153 else
4154 goto out;
4155
4156 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004157 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004158 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004159 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004160
Paul Moore75e22912008-01-29 08:38:04 -05004161out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004162 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004163 if (peer_secid == SECSID_NULL)
4164 return -EINVAL;
4165 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004166}
4167
Al Viro7d877f32005-10-21 03:20:43 -04004168static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
4170 return sk_alloc_security(sk, family, priority);
4171}
4172
4173static void selinux_sk_free_security(struct sock *sk)
4174{
4175 sk_free_security(sk);
4176}
4177
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004178static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4179{
4180 struct sk_security_struct *ssec = sk->sk_security;
4181 struct sk_security_struct *newssec = newsk->sk_security;
4182
4183 newssec->sid = ssec->sid;
4184 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004185 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004186
Paul Mooref74af6e2008-02-25 11:40:33 -05004187 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004188}
4189
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004190static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004191{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004192 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004193 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004194 else {
4195 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004196
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004197 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004198 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004199}
4200
Eric Paris828dfe12008-04-17 13:17:49 -04004201static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004202{
4203 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4204 struct sk_security_struct *sksec = sk->sk_security;
4205
David Woodhouse2148ccc2006-09-29 15:50:25 -07004206 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4207 sk->sk_family == PF_UNIX)
4208 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004209 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004210
4211 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004212}
4213
Adrian Bunk9a673e52006-08-15 00:03:53 -07004214static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4215 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004216{
4217 struct sk_security_struct *sksec = sk->sk_security;
4218 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004219 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004220 u32 peersid;
4221
Paul Moore220deb92008-01-29 08:38:23 -05004222 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4223 if (err)
4224 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004225 if (peersid == SECSID_NULL) {
4226 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004227 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004228 return 0;
4229 }
4230
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004231 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4232 if (err)
4233 return err;
4234
4235 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004236 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004237 return 0;
4238}
4239
Adrian Bunk9a673e52006-08-15 00:03:53 -07004240static void selinux_inet_csk_clone(struct sock *newsk,
4241 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004242{
4243 struct sk_security_struct *newsksec = newsk->sk_security;
4244
4245 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004246 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004247 /* NOTE: Ideally, we should also get the isec->sid for the
4248 new socket in sync, but we don't have the isec available yet.
4249 So we will wait until sock_graft to do it, by which
4250 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004251
Paul Moore9f2ad662006-11-17 17:38:53 -05004252 /* We don't need to take any sort of lock here as we are the only
4253 * thread with access to newsksec */
4254 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004255}
4256
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004257static void selinux_inet_conn_established(struct sock *sk,
4258 struct sk_buff *skb)
4259{
4260 struct sk_security_struct *sksec = sk->sk_security;
4261
Paul Moore220deb92008-01-29 08:38:23 -05004262 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004263}
4264
Adrian Bunk9a673e52006-08-15 00:03:53 -07004265static void selinux_req_classify_flow(const struct request_sock *req,
4266 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004267{
4268 fl->secid = req->secid;
4269}
4270
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4272{
4273 int err = 0;
4274 u32 perm;
4275 struct nlmsghdr *nlh;
4276 struct socket *sock = sk->sk_socket;
4277 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004278
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 if (skb->len < NLMSG_SPACE(0)) {
4280 err = -EINVAL;
4281 goto out;
4282 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004283 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004284
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4286 if (err) {
4287 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004288 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 "SELinux: unrecognized netlink message"
4290 " type=%hu for sclass=%hu\n",
4291 nlh->nlmsg_type, isec->sclass);
4292 if (!selinux_enforcing)
4293 err = 0;
4294 }
4295
4296 /* Ignore */
4297 if (err == -ENOENT)
4298 err = 0;
4299 goto out;
4300 }
4301
4302 err = socket_has_perm(current, sock, perm);
4303out:
4304 return err;
4305}
4306
4307#ifdef CONFIG_NETFILTER
4308
Paul Mooreeffad8d2008-01-29 08:49:27 -05004309static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4310 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004312 char *addrp;
4313 u32 peer_sid;
4314 struct avc_audit_data ad;
4315 u8 secmark_active;
4316 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004317
Paul Mooreeffad8d2008-01-29 08:49:27 -05004318 if (!selinux_policycap_netpeer)
4319 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004320
Paul Mooreeffad8d2008-01-29 08:49:27 -05004321 secmark_active = selinux_secmark_enabled();
4322 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4323 if (!secmark_active && !peerlbl_active)
4324 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004325
Paul Mooreeffad8d2008-01-29 08:49:27 -05004326 AVC_AUDIT_DATA_INIT(&ad, NET);
4327 ad.u.net.netif = ifindex;
4328 ad.u.net.family = family;
4329 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4330 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331
Paul Mooreeffad8d2008-01-29 08:49:27 -05004332 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4333 return NF_DROP;
4334
4335 if (peerlbl_active)
4336 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4337 peer_sid, &ad) != 0)
4338 return NF_DROP;
4339
4340 if (secmark_active)
4341 if (avc_has_perm(peer_sid, skb->secmark,
4342 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4343 return NF_DROP;
4344
4345 return NF_ACCEPT;
4346}
4347
4348static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4349 struct sk_buff *skb,
4350 const struct net_device *in,
4351 const struct net_device *out,
4352 int (*okfn)(struct sk_buff *))
4353{
4354 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4355}
4356
4357#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4358static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4359 struct sk_buff *skb,
4360 const struct net_device *in,
4361 const struct net_device *out,
4362 int (*okfn)(struct sk_buff *))
4363{
4364 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4365}
4366#endif /* IPV6 */
4367
4368static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4369 int ifindex,
4370 struct avc_audit_data *ad,
4371 u16 family, char *addrp)
4372{
4373 int err;
4374 struct sk_security_struct *sksec = sk->sk_security;
4375 u16 sk_class;
4376 u32 netif_perm, node_perm, send_perm;
4377 u32 port_sid, node_sid, if_sid, sk_sid;
4378
4379 sk_sid = sksec->sid;
4380 sk_class = sksec->sclass;
4381
4382 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 case SECCLASS_UDP_SOCKET:
4384 netif_perm = NETIF__UDP_SEND;
4385 node_perm = NODE__UDP_SEND;
4386 send_perm = UDP_SOCKET__SEND_MSG;
4387 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 case SECCLASS_TCP_SOCKET:
4389 netif_perm = NETIF__TCP_SEND;
4390 node_perm = NODE__TCP_SEND;
4391 send_perm = TCP_SOCKET__SEND_MSG;
4392 break;
James Morris2ee92d42006-11-13 16:09:01 -08004393 case SECCLASS_DCCP_SOCKET:
4394 netif_perm = NETIF__DCCP_SEND;
4395 node_perm = NODE__DCCP_SEND;
4396 send_perm = DCCP_SOCKET__SEND_MSG;
4397 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 default:
4399 netif_perm = NETIF__RAWIP_SEND;
4400 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004401 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 break;
4403 }
4404
Paul Mooreeffad8d2008-01-29 08:49:27 -05004405 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004406 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004407 return err;
4408 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4409 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004410
Paul Moore224dfbd2008-01-29 08:38:13 -05004411 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004412 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004413 return err;
4414 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004415 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004416 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Paul Mooreeffad8d2008-01-29 08:49:27 -05004418 if (send_perm != 0)
4419 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Paul Moore3e112172008-04-10 10:48:14 -04004421 err = sel_netport_sid(sk->sk_protocol,
4422 ntohs(ad->u.net.dport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004423 if (unlikely(err)) {
4424 printk(KERN_WARNING
4425 "SELinux: failure in"
4426 " selinux_ip_postroute_iptables_compat(),"
4427 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004428 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004429 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004430 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004431}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Paul Mooreeffad8d2008-01-29 08:49:27 -05004433static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4434 int ifindex,
4435 struct avc_audit_data *ad,
4436 u16 family,
4437 char *addrp,
4438 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004439{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004440 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004441 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004442
Paul Mooreeffad8d2008-01-29 08:49:27 -05004443 if (sk == NULL)
4444 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004445 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004446
Paul Mooreeffad8d2008-01-29 08:49:27 -05004447 if (selinux_compat_net) {
4448 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4449 ad, family, addrp))
4450 return NF_DROP;
4451 } else {
4452 if (avc_has_perm(sksec->sid, skb->secmark,
4453 SECCLASS_PACKET, PACKET__SEND, ad))
4454 return NF_DROP;
4455 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004456
Paul Mooreeffad8d2008-01-29 08:49:27 -05004457 if (selinux_policycap_netpeer)
4458 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4459 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004460
Paul Mooreeffad8d2008-01-29 08:49:27 -05004461 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462}
4463
Paul Mooreeffad8d2008-01-29 08:49:27 -05004464static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4465 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004467 u32 secmark_perm;
4468 u32 peer_sid;
4469 struct sock *sk;
4470 struct avc_audit_data ad;
4471 char *addrp;
4472 u8 proto;
4473 u8 secmark_active;
4474 u8 peerlbl_active;
4475
4476 AVC_AUDIT_DATA_INIT(&ad, NET);
4477 ad.u.net.netif = ifindex;
4478 ad.u.net.family = family;
4479 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4480 return NF_DROP;
4481
4482 /* If any sort of compatibility mode is enabled then handoff processing
4483 * to the selinux_ip_postroute_compat() function to deal with the
4484 * special handling. We do this in an attempt to keep this function
4485 * as fast and as clean as possible. */
4486 if (selinux_compat_net || !selinux_policycap_netpeer)
4487 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4488 family, addrp, proto);
4489
4490 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4491 * packet transformation so allow the packet to pass without any checks
4492 * since we'll have another chance to perform access control checks
4493 * when the packet is on it's final way out.
4494 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4495 * is NULL, in this case go ahead and apply access control. */
4496 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4497 return NF_ACCEPT;
4498
4499 secmark_active = selinux_secmark_enabled();
4500 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4501 if (!secmark_active && !peerlbl_active)
4502 return NF_ACCEPT;
4503
4504 /* if the packet is locally generated (skb->sk != NULL) then use the
4505 * socket's label as the peer label, otherwise the packet is being
4506 * forwarded through this system and we need to fetch the peer label
4507 * directly from the packet */
4508 sk = skb->sk;
4509 if (sk) {
4510 struct sk_security_struct *sksec = sk->sk_security;
4511 peer_sid = sksec->sid;
4512 secmark_perm = PACKET__SEND;
4513 } else {
4514 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4515 return NF_DROP;
4516 secmark_perm = PACKET__FORWARD_OUT;
4517 }
4518
4519 if (secmark_active)
4520 if (avc_has_perm(peer_sid, skb->secmark,
4521 SECCLASS_PACKET, secmark_perm, &ad))
4522 return NF_DROP;
4523
4524 if (peerlbl_active) {
4525 u32 if_sid;
4526 u32 node_sid;
4527
4528 if (sel_netif_sid(ifindex, &if_sid))
4529 return NF_DROP;
4530 if (avc_has_perm(peer_sid, if_sid,
4531 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4532 return NF_DROP;
4533
4534 if (sel_netnode_sid(addrp, family, &node_sid))
4535 return NF_DROP;
4536 if (avc_has_perm(peer_sid, node_sid,
4537 SECCLASS_NODE, NODE__SENDTO, &ad))
4538 return NF_DROP;
4539 }
4540
4541 return NF_ACCEPT;
4542}
4543
4544static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4545 struct sk_buff *skb,
4546 const struct net_device *in,
4547 const struct net_device *out,
4548 int (*okfn)(struct sk_buff *))
4549{
4550 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551}
4552
4553#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004554static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4555 struct sk_buff *skb,
4556 const struct net_device *in,
4557 const struct net_device *out,
4558 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004560 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562#endif /* IPV6 */
4563
4564#endif /* CONFIG_NETFILTER */
4565
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4567{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 int err;
4569
4570 err = secondary_ops->netlink_send(sk, skb);
4571 if (err)
4572 return err;
4573
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4575 err = selinux_nlmsg_perm(sk, skb);
4576
4577 return err;
4578}
4579
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004580static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004582 int err;
4583 struct avc_audit_data ad;
4584
4585 err = secondary_ops->netlink_recv(skb, capability);
4586 if (err)
4587 return err;
4588
4589 AVC_AUDIT_DATA_INIT(&ad, CAP);
4590 ad.u.cap = capability;
4591
4592 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
Eric Paris828dfe12008-04-17 13:17:49 -04004593 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594}
4595
4596static int ipc_alloc_security(struct task_struct *task,
4597 struct kern_ipc_perm *perm,
4598 u16 sclass)
4599{
4600 struct task_security_struct *tsec = task->security;
4601 struct ipc_security_struct *isec;
4602
James Morris89d155e2005-10-30 14:59:21 -08004603 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 if (!isec)
4605 return -ENOMEM;
4606
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607 isec->sclass = sclass;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004608 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 perm->security = isec;
4610
4611 return 0;
4612}
4613
4614static void ipc_free_security(struct kern_ipc_perm *perm)
4615{
4616 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617 perm->security = NULL;
4618 kfree(isec);
4619}
4620
4621static int msg_msg_alloc_security(struct msg_msg *msg)
4622{
4623 struct msg_security_struct *msec;
4624
James Morris89d155e2005-10-30 14:59:21 -08004625 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 if (!msec)
4627 return -ENOMEM;
4628
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 msec->sid = SECINITSID_UNLABELED;
4630 msg->security = msec;
4631
4632 return 0;
4633}
4634
4635static void msg_msg_free_security(struct msg_msg *msg)
4636{
4637 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638
4639 msg->security = NULL;
4640 kfree(msec);
4641}
4642
4643static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004644 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645{
4646 struct task_security_struct *tsec;
4647 struct ipc_security_struct *isec;
4648 struct avc_audit_data ad;
4649
4650 tsec = current->security;
4651 isec = ipc_perms->security;
4652
4653 AVC_AUDIT_DATA_INIT(&ad, IPC);
4654 ad.u.ipc_id = ipc_perms->key;
4655
Stephen Smalley6af963f2005-05-01 08:58:39 -07004656 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657}
4658
4659static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4660{
4661 return msg_msg_alloc_security(msg);
4662}
4663
4664static void selinux_msg_msg_free_security(struct msg_msg *msg)
4665{
4666 msg_msg_free_security(msg);
4667}
4668
4669/* message queue security operations */
4670static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4671{
4672 struct task_security_struct *tsec;
4673 struct ipc_security_struct *isec;
4674 struct avc_audit_data ad;
4675 int rc;
4676
4677 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4678 if (rc)
4679 return rc;
4680
4681 tsec = current->security;
4682 isec = msq->q_perm.security;
4683
4684 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004685 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686
4687 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4688 MSGQ__CREATE, &ad);
4689 if (rc) {
4690 ipc_free_security(&msq->q_perm);
4691 return rc;
4692 }
4693 return 0;
4694}
4695
4696static void selinux_msg_queue_free_security(struct msg_queue *msq)
4697{
4698 ipc_free_security(&msq->q_perm);
4699}
4700
4701static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4702{
4703 struct task_security_struct *tsec;
4704 struct ipc_security_struct *isec;
4705 struct avc_audit_data ad;
4706
4707 tsec = current->security;
4708 isec = msq->q_perm.security;
4709
4710 AVC_AUDIT_DATA_INIT(&ad, IPC);
4711 ad.u.ipc_id = msq->q_perm.key;
4712
4713 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4714 MSGQ__ASSOCIATE, &ad);
4715}
4716
4717static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4718{
4719 int err;
4720 int perms;
4721
Eric Paris828dfe12008-04-17 13:17:49 -04004722 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723 case IPC_INFO:
4724 case MSG_INFO:
4725 /* No specific object, just general system-wide information. */
4726 return task_has_system(current, SYSTEM__IPC_INFO);
4727 case IPC_STAT:
4728 case MSG_STAT:
4729 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4730 break;
4731 case IPC_SET:
4732 perms = MSGQ__SETATTR;
4733 break;
4734 case IPC_RMID:
4735 perms = MSGQ__DESTROY;
4736 break;
4737 default:
4738 return 0;
4739 }
4740
Stephen Smalley6af963f2005-05-01 08:58:39 -07004741 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 return err;
4743}
4744
4745static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4746{
4747 struct task_security_struct *tsec;
4748 struct ipc_security_struct *isec;
4749 struct msg_security_struct *msec;
4750 struct avc_audit_data ad;
4751 int rc;
4752
4753 tsec = current->security;
4754 isec = msq->q_perm.security;
4755 msec = msg->security;
4756
4757 /*
4758 * First time through, need to assign label to the message
4759 */
4760 if (msec->sid == SECINITSID_UNLABELED) {
4761 /*
4762 * Compute new sid based on current process and
4763 * message queue this message will be stored in
4764 */
4765 rc = security_transition_sid(tsec->sid,
4766 isec->sid,
4767 SECCLASS_MSG,
4768 &msec->sid);
4769 if (rc)
4770 return rc;
4771 }
4772
4773 AVC_AUDIT_DATA_INIT(&ad, IPC);
4774 ad.u.ipc_id = msq->q_perm.key;
4775
4776 /* Can this process write to the queue? */
4777 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4778 MSGQ__WRITE, &ad);
4779 if (!rc)
4780 /* Can this process send the message */
4781 rc = avc_has_perm(tsec->sid, msec->sid,
4782 SECCLASS_MSG, MSG__SEND, &ad);
4783 if (!rc)
4784 /* Can the message be put in the queue? */
4785 rc = avc_has_perm(msec->sid, isec->sid,
4786 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4787
4788 return rc;
4789}
4790
4791static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4792 struct task_struct *target,
4793 long type, int mode)
4794{
4795 struct task_security_struct *tsec;
4796 struct ipc_security_struct *isec;
4797 struct msg_security_struct *msec;
4798 struct avc_audit_data ad;
4799 int rc;
4800
4801 tsec = target->security;
4802 isec = msq->q_perm.security;
4803 msec = msg->security;
4804
4805 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004806 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807
4808 rc = avc_has_perm(tsec->sid, isec->sid,
4809 SECCLASS_MSGQ, MSGQ__READ, &ad);
4810 if (!rc)
4811 rc = avc_has_perm(tsec->sid, msec->sid,
4812 SECCLASS_MSG, MSG__RECEIVE, &ad);
4813 return rc;
4814}
4815
4816/* Shared Memory security operations */
4817static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4818{
4819 struct task_security_struct *tsec;
4820 struct ipc_security_struct *isec;
4821 struct avc_audit_data ad;
4822 int rc;
4823
4824 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4825 if (rc)
4826 return rc;
4827
4828 tsec = current->security;
4829 isec = shp->shm_perm.security;
4830
4831 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004832 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833
4834 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4835 SHM__CREATE, &ad);
4836 if (rc) {
4837 ipc_free_security(&shp->shm_perm);
4838 return rc;
4839 }
4840 return 0;
4841}
4842
4843static void selinux_shm_free_security(struct shmid_kernel *shp)
4844{
4845 ipc_free_security(&shp->shm_perm);
4846}
4847
4848static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4849{
4850 struct task_security_struct *tsec;
4851 struct ipc_security_struct *isec;
4852 struct avc_audit_data ad;
4853
4854 tsec = current->security;
4855 isec = shp->shm_perm.security;
4856
4857 AVC_AUDIT_DATA_INIT(&ad, IPC);
4858 ad.u.ipc_id = shp->shm_perm.key;
4859
4860 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4861 SHM__ASSOCIATE, &ad);
4862}
4863
4864/* Note, at this point, shp is locked down */
4865static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4866{
4867 int perms;
4868 int err;
4869
Eric Paris828dfe12008-04-17 13:17:49 -04004870 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871 case IPC_INFO:
4872 case SHM_INFO:
4873 /* No specific object, just general system-wide information. */
4874 return task_has_system(current, SYSTEM__IPC_INFO);
4875 case IPC_STAT:
4876 case SHM_STAT:
4877 perms = SHM__GETATTR | SHM__ASSOCIATE;
4878 break;
4879 case IPC_SET:
4880 perms = SHM__SETATTR;
4881 break;
4882 case SHM_LOCK:
4883 case SHM_UNLOCK:
4884 perms = SHM__LOCK;
4885 break;
4886 case IPC_RMID:
4887 perms = SHM__DESTROY;
4888 break;
4889 default:
4890 return 0;
4891 }
4892
Stephen Smalley6af963f2005-05-01 08:58:39 -07004893 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 return err;
4895}
4896
4897static int selinux_shm_shmat(struct shmid_kernel *shp,
4898 char __user *shmaddr, int shmflg)
4899{
4900 u32 perms;
4901 int rc;
4902
4903 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4904 if (rc)
4905 return rc;
4906
4907 if (shmflg & SHM_RDONLY)
4908 perms = SHM__READ;
4909 else
4910 perms = SHM__READ | SHM__WRITE;
4911
Stephen Smalley6af963f2005-05-01 08:58:39 -07004912 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004913}
4914
4915/* Semaphore security operations */
4916static int selinux_sem_alloc_security(struct sem_array *sma)
4917{
4918 struct task_security_struct *tsec;
4919 struct ipc_security_struct *isec;
4920 struct avc_audit_data ad;
4921 int rc;
4922
4923 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4924 if (rc)
4925 return rc;
4926
4927 tsec = current->security;
4928 isec = sma->sem_perm.security;
4929
4930 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004931 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
4933 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4934 SEM__CREATE, &ad);
4935 if (rc) {
4936 ipc_free_security(&sma->sem_perm);
4937 return rc;
4938 }
4939 return 0;
4940}
4941
4942static void selinux_sem_free_security(struct sem_array *sma)
4943{
4944 ipc_free_security(&sma->sem_perm);
4945}
4946
4947static int selinux_sem_associate(struct sem_array *sma, int semflg)
4948{
4949 struct task_security_struct *tsec;
4950 struct ipc_security_struct *isec;
4951 struct avc_audit_data ad;
4952
4953 tsec = current->security;
4954 isec = sma->sem_perm.security;
4955
4956 AVC_AUDIT_DATA_INIT(&ad, IPC);
4957 ad.u.ipc_id = sma->sem_perm.key;
4958
4959 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4960 SEM__ASSOCIATE, &ad);
4961}
4962
4963/* Note, at this point, sma is locked down */
4964static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4965{
4966 int err;
4967 u32 perms;
4968
Eric Paris828dfe12008-04-17 13:17:49 -04004969 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970 case IPC_INFO:
4971 case SEM_INFO:
4972 /* No specific object, just general system-wide information. */
4973 return task_has_system(current, SYSTEM__IPC_INFO);
4974 case GETPID:
4975 case GETNCNT:
4976 case GETZCNT:
4977 perms = SEM__GETATTR;
4978 break;
4979 case GETVAL:
4980 case GETALL:
4981 perms = SEM__READ;
4982 break;
4983 case SETVAL:
4984 case SETALL:
4985 perms = SEM__WRITE;
4986 break;
4987 case IPC_RMID:
4988 perms = SEM__DESTROY;
4989 break;
4990 case IPC_SET:
4991 perms = SEM__SETATTR;
4992 break;
4993 case IPC_STAT:
4994 case SEM_STAT:
4995 perms = SEM__GETATTR | SEM__ASSOCIATE;
4996 break;
4997 default:
4998 return 0;
4999 }
5000
Stephen Smalley6af963f2005-05-01 08:58:39 -07005001 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 return err;
5003}
5004
5005static int selinux_sem_semop(struct sem_array *sma,
5006 struct sembuf *sops, unsigned nsops, int alter)
5007{
5008 u32 perms;
5009
5010 if (alter)
5011 perms = SEM__READ | SEM__WRITE;
5012 else
5013 perms = SEM__READ;
5014
Stephen Smalley6af963f2005-05-01 08:58:39 -07005015 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016}
5017
5018static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5019{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 u32 av = 0;
5021
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 av = 0;
5023 if (flag & S_IRUGO)
5024 av |= IPC__UNIX_READ;
5025 if (flag & S_IWUGO)
5026 av |= IPC__UNIX_WRITE;
5027
5028 if (av == 0)
5029 return 0;
5030
Stephen Smalley6af963f2005-05-01 08:58:39 -07005031 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032}
5033
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005034static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5035{
5036 struct ipc_security_struct *isec = ipcp->security;
5037 *secid = isec->sid;
5038}
5039
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040/* module stacking operations */
Eric Paris828dfe12008-04-17 13:17:49 -04005041static int selinux_register_security(const char *name, struct security_operations *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042{
5043 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005044 printk(KERN_ERR "%s: There is already a secondary security "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005045 "module registered.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046 return -EINVAL;
Eric Paris828dfe12008-04-17 13:17:49 -04005047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048
5049 secondary_ops = ops;
5050
5051 printk(KERN_INFO "%s: Registering secondary module %s\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005052 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 name);
5054
5055 return 0;
5056}
5057
Eric Paris828dfe12008-04-17 13:17:49 -04005058static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059{
5060 if (inode)
5061 inode_doinit_with_dentry(inode, dentry);
5062}
5063
5064static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005065 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066{
5067 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005068 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005070 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071
5072 if (current != p) {
5073 error = task_has_perm(current, p, PROCESS__GETATTR);
5074 if (error)
5075 return error;
5076 }
5077
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078 tsec = p->security;
5079
5080 if (!strcmp(name, "current"))
5081 sid = tsec->sid;
5082 else if (!strcmp(name, "prev"))
5083 sid = tsec->osid;
5084 else if (!strcmp(name, "exec"))
5085 sid = tsec->exec_sid;
5086 else if (!strcmp(name, "fscreate"))
5087 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005088 else if (!strcmp(name, "keycreate"))
5089 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005090 else if (!strcmp(name, "sockcreate"))
5091 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092 else
5093 return -EINVAL;
5094
5095 if (!sid)
5096 return 0;
5097
Al Viro04ff9702007-03-12 16:17:58 +00005098 error = security_sid_to_context(sid, value, &len);
5099 if (error)
5100 return error;
5101 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102}
5103
5104static int selinux_setprocattr(struct task_struct *p,
5105 char *name, void *value, size_t size)
5106{
5107 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005108 struct task_struct *tracer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 u32 sid = 0;
5110 int error;
5111 char *str = value;
5112
5113 if (current != p) {
5114 /* SELinux only allows a process to change its own
5115 security attributes. */
5116 return -EACCES;
5117 }
5118
5119 /*
5120 * Basic control over ability to set these attributes at all.
5121 * current == p, but we'll pass them separately in case the
5122 * above restriction is ever removed.
5123 */
5124 if (!strcmp(name, "exec"))
5125 error = task_has_perm(current, p, PROCESS__SETEXEC);
5126 else if (!strcmp(name, "fscreate"))
5127 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005128 else if (!strcmp(name, "keycreate"))
5129 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005130 else if (!strcmp(name, "sockcreate"))
5131 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132 else if (!strcmp(name, "current"))
5133 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5134 else
5135 error = -EINVAL;
5136 if (error)
5137 return error;
5138
5139 /* Obtain a SID for the context, if one was specified. */
5140 if (size && str[1] && str[1] != '\n') {
5141 if (str[size-1] == '\n') {
5142 str[size-1] = 0;
5143 size--;
5144 }
5145 error = security_context_to_sid(value, size, &sid);
5146 if (error)
5147 return error;
5148 }
5149
5150 /* Permission checking based on the specified context is
5151 performed during the actual operation (execve,
5152 open/mkdir/...), when we know the full context of the
5153 operation. See selinux_bprm_set_security for the execve
5154 checks and may_create for the file creation checks. The
5155 operation will then fail if the context is not permitted. */
5156 tsec = p->security;
5157 if (!strcmp(name, "exec"))
5158 tsec->exec_sid = sid;
5159 else if (!strcmp(name, "fscreate"))
5160 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005161 else if (!strcmp(name, "keycreate")) {
5162 error = may_create_key(sid, p);
5163 if (error)
5164 return error;
5165 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005166 } else if (!strcmp(name, "sockcreate"))
5167 tsec->sockcreate_sid = sid;
5168 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 struct av_decision avd;
5170
5171 if (sid == 0)
5172 return -EINVAL;
5173
5174 /* Only allow single threaded processes to change context */
5175 if (atomic_read(&p->mm->mm_users) != 1) {
5176 struct task_struct *g, *t;
5177 struct mm_struct *mm = p->mm;
5178 read_lock(&tasklist_lock);
5179 do_each_thread(g, t)
5180 if (t->mm == mm && t != p) {
5181 read_unlock(&tasklist_lock);
5182 return -EPERM;
5183 }
5184 while_each_thread(g, t);
5185 read_unlock(&tasklist_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04005186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
5188 /* Check permissions for the transition. */
5189 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005190 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191 if (error)
5192 return error;
5193
5194 /* Check for ptracing, and update the task SID if ok.
5195 Otherwise, leave SID unchanged and fail. */
5196 task_lock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005197 rcu_read_lock();
5198 tracer = task_tracer_task(p);
5199 if (tracer != NULL) {
5200 struct task_security_struct *ptsec = tracer->security;
5201 u32 ptsid = ptsec->sid;
5202 rcu_read_unlock();
5203 error = avc_has_perm_noaudit(ptsid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005205 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 if (!error)
5207 tsec->sid = sid;
5208 task_unlock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005209 avc_audit(ptsid, sid, SECCLASS_PROCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210 PROCESS__PTRACE, &avd, error, NULL);
5211 if (error)
5212 return error;
5213 } else {
Roland McGrath03563572008-03-26 15:46:39 -07005214 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215 tsec->sid = sid;
5216 task_unlock(p);
5217 }
Eric Paris828dfe12008-04-17 13:17:49 -04005218 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219 return -EINVAL;
5220
5221 return size;
5222}
5223
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005224static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5225{
5226 return security_sid_to_context(secid, secdata, seclen);
5227}
5228
David Howells63cb3442008-01-15 23:47:35 +00005229static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
5230{
5231 return security_context_to_sid(secdata, seclen, secid);
5232}
5233
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005234static void selinux_release_secctx(char *secdata, u32 seclen)
5235{
Paul Moore088999e2007-08-01 11:12:58 -04005236 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005237}
5238
Michael LeMayd7200242006-06-22 14:47:17 -07005239#ifdef CONFIG_KEYS
5240
David Howells7e047ef2006-06-26 00:24:50 -07005241static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5242 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005243{
5244 struct task_security_struct *tsec = tsk->security;
5245 struct key_security_struct *ksec;
5246
5247 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5248 if (!ksec)
5249 return -ENOMEM;
5250
Michael LeMay4eb582c2006-06-26 00:24:57 -07005251 if (tsec->keycreate_sid)
5252 ksec->sid = tsec->keycreate_sid;
5253 else
5254 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005255 k->security = ksec;
5256
5257 return 0;
5258}
5259
5260static void selinux_key_free(struct key *k)
5261{
5262 struct key_security_struct *ksec = k->security;
5263
5264 k->security = NULL;
5265 kfree(ksec);
5266}
5267
5268static int selinux_key_permission(key_ref_t key_ref,
5269 struct task_struct *ctx,
5270 key_perm_t perm)
5271{
5272 struct key *key;
5273 struct task_security_struct *tsec;
5274 struct key_security_struct *ksec;
5275
5276 key = key_ref_to_ptr(key_ref);
5277
5278 tsec = ctx->security;
5279 ksec = key->security;
5280
5281 /* if no specific permissions are requested, we skip the
5282 permission check. No serious, additional covert channels
5283 appear to be created. */
5284 if (perm == 0)
5285 return 0;
5286
5287 return avc_has_perm(tsec->sid, ksec->sid,
5288 SECCLASS_KEY, perm, NULL);
5289}
5290
5291#endif
5292
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005294 .name = "selinux",
5295
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296 .ptrace = selinux_ptrace,
5297 .capget = selinux_capget,
5298 .capset_check = selinux_capset_check,
5299 .capset_set = selinux_capset_set,
5300 .sysctl = selinux_sysctl,
5301 .capable = selinux_capable,
5302 .quotactl = selinux_quotactl,
5303 .quota_on = selinux_quota_on,
5304 .syslog = selinux_syslog,
5305 .vm_enough_memory = selinux_vm_enough_memory,
5306
5307 .netlink_send = selinux_netlink_send,
Eric Paris828dfe12008-04-17 13:17:49 -04005308 .netlink_recv = selinux_netlink_recv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
5310 .bprm_alloc_security = selinux_bprm_alloc_security,
5311 .bprm_free_security = selinux_bprm_free_security,
5312 .bprm_apply_creds = selinux_bprm_apply_creds,
5313 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5314 .bprm_set_security = selinux_bprm_set_security,
5315 .bprm_check_security = selinux_bprm_check_security,
5316 .bprm_secureexec = selinux_bprm_secureexec,
5317
5318 .sb_alloc_security = selinux_sb_alloc_security,
5319 .sb_free_security = selinux_sb_free_security,
5320 .sb_copy_data = selinux_sb_copy_data,
Eric Paris828dfe12008-04-17 13:17:49 -04005321 .sb_kern_mount = selinux_sb_kern_mount,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322 .sb_statfs = selinux_sb_statfs,
5323 .sb_mount = selinux_mount,
5324 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005325 .sb_get_mnt_opts = selinux_get_mnt_opts,
5326 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005327 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005328 .sb_parse_opts_str = selinux_parse_opts_str,
5329
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330
5331 .inode_alloc_security = selinux_inode_alloc_security,
5332 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005333 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 .inode_unlink = selinux_inode_unlink,
5337 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339 .inode_rmdir = selinux_inode_rmdir,
5340 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 .inode_readlink = selinux_inode_readlink,
5343 .inode_follow_link = selinux_inode_follow_link,
5344 .inode_permission = selinux_inode_permission,
5345 .inode_setattr = selinux_inode_setattr,
5346 .inode_getattr = selinux_inode_getattr,
5347 .inode_setxattr = selinux_inode_setxattr,
5348 .inode_post_setxattr = selinux_inode_post_setxattr,
5349 .inode_getxattr = selinux_inode_getxattr,
5350 .inode_listxattr = selinux_inode_listxattr,
5351 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005352 .inode_getsecurity = selinux_inode_getsecurity,
5353 .inode_setsecurity = selinux_inode_setsecurity,
5354 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005355 .inode_need_killpriv = selinux_inode_need_killpriv,
5356 .inode_killpriv = selinux_inode_killpriv,
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005357 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358
5359 .file_permission = selinux_file_permission,
5360 .file_alloc_security = selinux_file_alloc_security,
5361 .file_free_security = selinux_file_free_security,
5362 .file_ioctl = selinux_file_ioctl,
5363 .file_mmap = selinux_file_mmap,
5364 .file_mprotect = selinux_file_mprotect,
5365 .file_lock = selinux_file_lock,
5366 .file_fcntl = selinux_file_fcntl,
5367 .file_set_fowner = selinux_file_set_fowner,
5368 .file_send_sigiotask = selinux_file_send_sigiotask,
5369 .file_receive = selinux_file_receive,
5370
Eric Paris828dfe12008-04-17 13:17:49 -04005371 .dentry_open = selinux_dentry_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005372
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 .task_create = selinux_task_create,
5374 .task_alloc_security = selinux_task_alloc_security,
5375 .task_free_security = selinux_task_free_security,
5376 .task_setuid = selinux_task_setuid,
5377 .task_post_setuid = selinux_task_post_setuid,
5378 .task_setgid = selinux_task_setgid,
5379 .task_setpgid = selinux_task_setpgid,
5380 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005381 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005382 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383 .task_setgroups = selinux_task_setgroups,
5384 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005385 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005386 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387 .task_setrlimit = selinux_task_setrlimit,
5388 .task_setscheduler = selinux_task_setscheduler,
5389 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005390 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391 .task_kill = selinux_task_kill,
5392 .task_wait = selinux_task_wait,
5393 .task_prctl = selinux_task_prctl,
5394 .task_reparent_to_init = selinux_task_reparent_to_init,
Eric Paris828dfe12008-04-17 13:17:49 -04005395 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
5397 .ipc_permission = selinux_ipc_permission,
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005398 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399
5400 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5401 .msg_msg_free_security = selinux_msg_msg_free_security,
5402
5403 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5404 .msg_queue_free_security = selinux_msg_queue_free_security,
5405 .msg_queue_associate = selinux_msg_queue_associate,
5406 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5407 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5408 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5409
5410 .shm_alloc_security = selinux_shm_alloc_security,
5411 .shm_free_security = selinux_shm_free_security,
5412 .shm_associate = selinux_shm_associate,
5413 .shm_shmctl = selinux_shm_shmctl,
5414 .shm_shmat = selinux_shm_shmat,
5415
Eric Paris828dfe12008-04-17 13:17:49 -04005416 .sem_alloc_security = selinux_sem_alloc_security,
5417 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 .sem_associate = selinux_sem_associate,
5419 .sem_semctl = selinux_sem_semctl,
5420 .sem_semop = selinux_sem_semop,
5421
5422 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423
Eric Paris828dfe12008-04-17 13:17:49 -04005424 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005425
Eric Paris828dfe12008-04-17 13:17:49 -04005426 .getprocattr = selinux_getprocattr,
5427 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005429 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005430 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005431 .release_secctx = selinux_release_secctx,
5432
Eric Paris828dfe12008-04-17 13:17:49 -04005433 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 .unix_may_send = selinux_socket_unix_may_send,
5435
5436 .socket_create = selinux_socket_create,
5437 .socket_post_create = selinux_socket_post_create,
5438 .socket_bind = selinux_socket_bind,
5439 .socket_connect = selinux_socket_connect,
5440 .socket_listen = selinux_socket_listen,
5441 .socket_accept = selinux_socket_accept,
5442 .socket_sendmsg = selinux_socket_sendmsg,
5443 .socket_recvmsg = selinux_socket_recvmsg,
5444 .socket_getsockname = selinux_socket_getsockname,
5445 .socket_getpeername = selinux_socket_getpeername,
5446 .socket_getsockopt = selinux_socket_getsockopt,
5447 .socket_setsockopt = selinux_socket_setsockopt,
5448 .socket_shutdown = selinux_socket_shutdown,
5449 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005450 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5451 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452 .sk_alloc_security = selinux_sk_alloc_security,
5453 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005454 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005455 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005456 .sock_graft = selinux_sock_graft,
5457 .inet_conn_request = selinux_inet_conn_request,
5458 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005459 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005460 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005461
5462#ifdef CONFIG_SECURITY_NETWORK_XFRM
5463 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5464 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5465 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005466 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005467 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5468 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005469 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005470 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005471 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005472 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005474
5475#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005476 .key_alloc = selinux_key_alloc,
5477 .key_free = selinux_key_free,
5478 .key_permission = selinux_key_permission,
Michael LeMayd7200242006-06-22 14:47:17 -07005479#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005480
5481#ifdef CONFIG_AUDIT
5482 .audit_rule_init = selinux_audit_rule_init,
5483 .audit_rule_known = selinux_audit_rule_known,
5484 .audit_rule_match = selinux_audit_rule_match,
5485 .audit_rule_free = selinux_audit_rule_free,
5486#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487};
5488
5489static __init int selinux_init(void)
5490{
5491 struct task_security_struct *tsec;
5492
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005493 if (!security_module_enable(&selinux_ops)) {
5494 selinux_enabled = 0;
5495 return 0;
5496 }
5497
Linus Torvalds1da177e2005-04-16 15:20:36 -07005498 if (!selinux_enabled) {
5499 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5500 return 0;
5501 }
5502
5503 printk(KERN_INFO "SELinux: Initializing.\n");
5504
5505 /* Set the security state for the initial task. */
5506 if (task_alloc_security(current))
5507 panic("SELinux: Failed to initialize initial task.\n");
5508 tsec = current->security;
5509 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5510
James Morris7cae7e22006-03-22 00:09:22 -08005511 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5512 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005513 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514 avc_init();
5515
5516 original_ops = secondary_ops = security_ops;
5517 if (!secondary_ops)
Eric Paris828dfe12008-04-17 13:17:49 -04005518 panic("SELinux: No initial security operations\n");
5519 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520 panic("SELinux: Unable to register with kernel.\n");
5521
Eric Paris828dfe12008-04-17 13:17:49 -04005522 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005523 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005524 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005525 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005526
5527#ifdef CONFIG_KEYS
5528 /* Add security information to initial keyrings */
Michael LeMay4eb582c2006-06-26 00:24:57 -07005529 selinux_key_alloc(&root_user_keyring, current,
5530 KEY_ALLOC_NOT_IN_QUOTA);
5531 selinux_key_alloc(&root_session_keyring, current,
5532 KEY_ALLOC_NOT_IN_QUOTA);
Michael LeMayd7200242006-06-22 14:47:17 -07005533#endif
5534
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535 return 0;
5536}
5537
5538void selinux_complete_init(void)
5539{
Eric Parisfadcdb42007-02-22 18:11:31 -05005540 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541
5542 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005543 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005544 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545 spin_lock(&sb_security_lock);
5546next_sb:
5547 if (!list_empty(&superblock_security_head)) {
5548 struct superblock_security_struct *sbsec =
5549 list_entry(superblock_security_head.next,
Eric Paris828dfe12008-04-17 13:17:49 -04005550 struct superblock_security_struct,
5551 list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005555 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556 down_read(&sb->s_umount);
5557 if (sb->s_root)
5558 superblock_doinit(sb, NULL);
5559 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005560 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561 spin_lock(&sb_security_lock);
5562 list_del_init(&sbsec->list);
5563 goto next_sb;
5564 }
5565 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005566 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567}
5568
5569/* SELinux requires early initialization in order to label
5570 all processes and objects when they are created. */
5571security_initcall(selinux_init);
5572
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005573#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
Paul Mooreeffad8d2008-01-29 08:49:27 -05005575static struct nf_hook_ops selinux_ipv4_ops[] = {
5576 {
5577 .hook = selinux_ipv4_postroute,
5578 .owner = THIS_MODULE,
5579 .pf = PF_INET,
5580 .hooknum = NF_INET_POST_ROUTING,
5581 .priority = NF_IP_PRI_SELINUX_LAST,
5582 },
5583 {
5584 .hook = selinux_ipv4_forward,
5585 .owner = THIS_MODULE,
5586 .pf = PF_INET,
5587 .hooknum = NF_INET_FORWARD,
5588 .priority = NF_IP_PRI_SELINUX_FIRST,
5589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590};
5591
5592#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5593
Paul Mooreeffad8d2008-01-29 08:49:27 -05005594static struct nf_hook_ops selinux_ipv6_ops[] = {
5595 {
5596 .hook = selinux_ipv6_postroute,
5597 .owner = THIS_MODULE,
5598 .pf = PF_INET6,
5599 .hooknum = NF_INET_POST_ROUTING,
5600 .priority = NF_IP6_PRI_SELINUX_LAST,
5601 },
5602 {
5603 .hook = selinux_ipv6_forward,
5604 .owner = THIS_MODULE,
5605 .pf = PF_INET6,
5606 .hooknum = NF_INET_FORWARD,
5607 .priority = NF_IP6_PRI_SELINUX_FIRST,
5608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609};
5610
5611#endif /* IPV6 */
5612
5613static int __init selinux_nf_ip_init(void)
5614{
5615 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005616 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617
5618 if (!selinux_enabled)
5619 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005620
5621 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5622
Paul Mooreeffad8d2008-01-29 08:49:27 -05005623 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5624 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5625 if (err)
5626 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5627 err);
5628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629
5630#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005631 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5632 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5633 if (err)
5634 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5635 err);
5636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005638
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639out:
5640 return err;
5641}
5642
5643__initcall(selinux_nf_ip_init);
5644
5645#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5646static void selinux_nf_ip_exit(void)
5647{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005648 u32 iter;
5649
Eric Parisfadcdb42007-02-22 18:11:31 -05005650 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651
Paul Mooreeffad8d2008-01-29 08:49:27 -05005652 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5653 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005654#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005655 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5656 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657#endif /* IPV6 */
5658}
5659#endif
5660
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005661#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662
5663#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5664#define selinux_nf_ip_exit()
5665#endif
5666
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005667#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668
5669#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005670static int selinux_disabled;
5671
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672int selinux_disable(void)
5673{
5674 extern void exit_sel_fs(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675
5676 if (ss_initialized) {
5677 /* Not permitted after initial policy load. */
5678 return -EINVAL;
5679 }
5680
5681 if (selinux_disabled) {
5682 /* Only do this once. */
5683 return -EINVAL;
5684 }
5685
5686 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5687
5688 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005689 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690
5691 /* Reset security_ops to the secondary module, dummy or capability. */
5692 security_ops = secondary_ops;
5693
5694 /* Unregister netfilter hooks. */
5695 selinux_nf_ip_exit();
5696
5697 /* Unregister selinuxfs. */
5698 exit_sel_fs();
5699
5700 return 0;
5701}
5702#endif