blob: 91b666aec452884fed8be469270413eefb915f51 [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>
Al Viro9f3acc32008-04-24 07:44:08 -040042#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/namei.h>
44#include <linux/mount.h>
45#include <linux/ext2_fs.h>
46#include <linux/proc_fs.h>
47#include <linux/kd.h>
48#include <linux/netfilter_ipv4.h>
49#include <linux/netfilter_ipv6.h>
50#include <linux/tty.h>
51#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070052#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050054#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050055#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040056#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <asm/ioctls.h>
Paul Moored621d352008-01-29 08:43:36 -050058#include <asm/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <linux/bitops.h>
60#include <linux/interrupt.h>
61#include <linux/netdevice.h> /* for network interface checks */
62#include <linux/netlink.h>
63#include <linux/tcp.h>
64#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080065#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <linux/quota.h>
67#include <linux/un.h> /* for Unix socket types */
68#include <net/af_unix.h> /* for Unix socket types */
69#include <linux/parser.h>
70#include <linux/nfs_mount.h>
71#include <net/ipv6.h>
72#include <linux/hugetlb.h>
73#include <linux/personality.h>
74#include <linux/sysctl.h>
75#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070076#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070077#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070078#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80#include "avc.h"
81#include "objsec.h"
82#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050083#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040084#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080085#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050086#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020087#include "audit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89#define XATTR_SELINUX_SUFFIX "selinux"
90#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
91
Eric Parisc9180a52007-11-30 13:00:35 -050092#define NUM_SEL_MNT_OPTS 4
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094extern unsigned int policydb_loaded_version;
95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
James Morris4e5ab4c2006-06-09 00:33:33 -070096extern int selinux_compat_net;
James Morris20510f22007-10-16 23:31:32 -070097extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Paul Moored621d352008-01-29 08:43:36 -050099/* SECMARK reference count */
100atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400103int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105static int __init enforcing_setup(char *str)
106{
Eric Parisf5269712008-05-14 11:27:45 -0400107 unsigned long enforcing;
108 if (!strict_strtoul(str, 0, &enforcing))
109 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return 1;
111}
112__setup("enforcing=", enforcing_setup);
113#endif
114
115#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
116int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
117
118static int __init selinux_enabled_setup(char *str)
119{
Eric Parisf5269712008-05-14 11:27:45 -0400120 unsigned long enabled;
121 if (!strict_strtoul(str, 0, &enabled))
122 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return 1;
124}
125__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400126#else
127int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#endif
129
130/* Original (dummy) security module. */
Eric Paris828dfe12008-04-17 13:17:49 -0400131static struct security_operations *original_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/* Minimal support for a secondary security module,
134 just to allow the use of the dummy or capability modules.
135 The owlsm module can alternatively be used as a secondary
136 module as long as CONFIG_OWLSM_FD is not enabled. */
Eric Paris828dfe12008-04-17 13:17:49 -0400137static struct security_operations *secondary_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139/* Lists of inode and superblock security structures initialized
140 before the policy was loaded. */
141static LIST_HEAD(superblock_security_head);
142static DEFINE_SPINLOCK(sb_security_lock);
143
Christoph Lametere18b8902006-12-06 20:33:20 -0800144static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800145
Paul Moored621d352008-01-29 08:43:36 -0500146/**
147 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
148 *
149 * Description:
150 * This function checks the SECMARK reference counter to see if any SECMARK
151 * targets are currently configured, if the reference counter is greater than
152 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
153 * enabled, false (0) if SECMARK is disabled.
154 *
155 */
156static int selinux_secmark_enabled(void)
157{
158 return (atomic_read(&selinux_secmark_refcount) > 0);
159}
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161/* Allocate and free functions for each kind of security blob. */
162
163static int task_alloc_security(struct task_struct *task)
164{
165 struct task_security_struct *tsec;
166
James Morris89d155e2005-10-30 14:59:21 -0800167 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 if (!tsec)
169 return -ENOMEM;
170
Roland McGrath03563572008-03-26 15:46:39 -0700171 tsec->osid = tsec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 task->security = tsec;
173
174 return 0;
175}
176
177static void task_free_security(struct task_struct *task)
178{
179 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 task->security = NULL;
181 kfree(tsec);
182}
183
184static int inode_alloc_security(struct inode *inode)
185{
186 struct task_security_struct *tsec = current->security;
187 struct inode_security_struct *isec;
188
Josef Bacika02fe132008-04-04 09:35:05 +1100189 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 if (!isec)
191 return -ENOMEM;
192
Eric Paris23970742006-09-25 23:32:01 -0700193 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 isec->inode = inode;
196 isec->sid = SECINITSID_UNLABELED;
197 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800198 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 inode->i_security = isec;
200
201 return 0;
202}
203
204static void inode_free_security(struct inode *inode)
205{
206 struct inode_security_struct *isec = inode->i_security;
207 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 spin_lock(&sbsec->isec_lock);
210 if (!list_empty(&isec->list))
211 list_del_init(&isec->list);
212 spin_unlock(&sbsec->isec_lock);
213
214 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800215 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
218static int file_alloc_security(struct file *file)
219{
220 struct task_security_struct *tsec = current->security;
221 struct file_security_struct *fsec;
222
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800223 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 if (!fsec)
225 return -ENOMEM;
226
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800227 fsec->sid = tsec->sid;
228 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 file->f_security = fsec;
230
231 return 0;
232}
233
234static void file_free_security(struct file *file)
235{
236 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 file->f_security = NULL;
238 kfree(fsec);
239}
240
241static int superblock_alloc_security(struct super_block *sb)
242{
243 struct superblock_security_struct *sbsec;
244
James Morris89d155e2005-10-30 14:59:21 -0800245 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 if (!sbsec)
247 return -ENOMEM;
248
Eric Parisbc7e9822006-09-25 23:32:02 -0700249 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 INIT_LIST_HEAD(&sbsec->list);
251 INIT_LIST_HEAD(&sbsec->isec_head);
252 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 sbsec->sb = sb;
254 sbsec->sid = SECINITSID_UNLABELED;
255 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700256 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 sb->s_security = sbsec;
258
259 return 0;
260}
261
262static void superblock_free_security(struct super_block *sb)
263{
264 struct superblock_security_struct *sbsec = sb->s_security;
265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 spin_lock(&sb_security_lock);
267 if (!list_empty(&sbsec->list))
268 list_del_init(&sbsec->list);
269 spin_unlock(&sb_security_lock);
270
271 sb->s_security = NULL;
272 kfree(sbsec);
273}
274
Al Viro7d877f32005-10-21 03:20:43 -0400275static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276{
277 struct sk_security_struct *ssec;
278
James Morris89d155e2005-10-30 14:59:21 -0800279 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!ssec)
281 return -ENOMEM;
282
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700284 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 sk->sk_security = ssec;
286
Paul Mooref74af6e2008-02-25 11:40:33 -0500287 selinux_netlbl_sk_security_reset(ssec, family);
Paul Moore99f59ed2006-08-29 17:53:48 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 return 0;
290}
291
292static void sk_free_security(struct sock *sk)
293{
294 struct sk_security_struct *ssec = sk->sk_security;
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 sk->sk_security = NULL;
297 kfree(ssec);
298}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300/* The security server must be initialized before
301 any labeling or access decisions can be provided. */
302extern int ss_initialized;
303
304/* The file system's label must be initialized prior to use. */
305
306static char *labeling_behaviors[6] = {
307 "uses xattr",
308 "uses transition SIDs",
309 "uses task SIDs",
310 "uses genfs_contexts",
311 "not configured for labeling",
312 "uses mountpoint labeling",
313};
314
315static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
316
317static inline int inode_doinit(struct inode *inode)
318{
319 return inode_doinit_with_dentry(inode, NULL);
320}
321
322enum {
Eric Paris31e87932007-09-19 17:19:12 -0400323 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 Opt_context = 1,
325 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500326 Opt_defcontext = 3,
327 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328};
329
330static match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400331 {Opt_context, CONTEXT_STR "%s"},
332 {Opt_fscontext, FSCONTEXT_STR "%s"},
333 {Opt_defcontext, DEFCONTEXT_STR "%s"},
334 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400335 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336};
337
338#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
339
Eric Parisc312feb2006-07-10 04:43:53 -0700340static int may_context_mount_sb_relabel(u32 sid,
341 struct superblock_security_struct *sbsec,
342 struct task_security_struct *tsec)
343{
344 int rc;
345
346 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
347 FILESYSTEM__RELABELFROM, NULL);
348 if (rc)
349 return rc;
350
351 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
352 FILESYSTEM__RELABELTO, NULL);
353 return rc;
354}
355
Eric Paris08089252006-07-10 04:43:55 -0700356static int may_context_mount_inode_relabel(u32 sid,
357 struct superblock_security_struct *sbsec,
358 struct task_security_struct *tsec)
359{
360 int rc;
361 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
362 FILESYSTEM__RELABELFROM, NULL);
363 if (rc)
364 return rc;
365
366 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
367 FILESYSTEM__ASSOCIATE, NULL);
368 return rc;
369}
370
Eric Parisc9180a52007-11-30 13:00:35 -0500371static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372{
373 struct superblock_security_struct *sbsec = sb->s_security;
374 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500375 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 int rc = 0;
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
379 /* Make sure that the xattr handler exists and that no
380 error other than -ENODATA is returned by getxattr on
381 the root directory. -ENODATA is ok, as this may be
382 the first boot of the SELinux kernel before we have
383 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500384 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
386 "xattr support\n", sb->s_id, sb->s_type->name);
387 rc = -EOPNOTSUPP;
388 goto out;
389 }
Eric Parisc9180a52007-11-30 13:00:35 -0500390 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (rc < 0 && rc != -ENODATA) {
392 if (rc == -EOPNOTSUPP)
393 printk(KERN_WARNING "SELinux: (dev %s, type "
394 "%s) has no security xattr handler\n",
395 sb->s_id, sb->s_type->name);
396 else
397 printk(KERN_WARNING "SELinux: (dev %s, type "
398 "%s) getxattr errno %d\n", sb->s_id,
399 sb->s_type->name, -rc);
400 goto out;
401 }
402 }
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 sbsec->initialized = 1;
405
Eric Parisc9180a52007-11-30 13:00:35 -0500406 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500407 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500409 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500410 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 sb->s_id, sb->s_type->name,
412 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
414 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500415 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417 /* Initialize any other inodes associated with the superblock, e.g.
418 inodes created prior to initial policy load or inodes created
419 during get_sb by a pseudo filesystem that directly
420 populates itself. */
421 spin_lock(&sbsec->isec_lock);
422next_inode:
423 if (!list_empty(&sbsec->isec_head)) {
424 struct inode_security_struct *isec =
425 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500426 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 struct inode *inode = isec->inode;
428 spin_unlock(&sbsec->isec_lock);
429 inode = igrab(inode);
430 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500431 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 inode_doinit(inode);
433 iput(inode);
434 }
435 spin_lock(&sbsec->isec_lock);
436 list_del_init(&isec->list);
437 goto next_inode;
438 }
439 spin_unlock(&sbsec->isec_lock);
440out:
Eric Parisc9180a52007-11-30 13:00:35 -0500441 return rc;
442}
443
444/*
445 * This function should allow an FS to ask what it's mount security
446 * options were so it can use those later for submounts, displaying
447 * mount options, or whatever.
448 */
449static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500450 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500451{
452 int rc = 0, i;
453 struct superblock_security_struct *sbsec = sb->s_security;
454 char *context = NULL;
455 u32 len;
456 char tmp;
457
Eric Parise0007522008-03-05 10:31:54 -0500458 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500459
460 if (!sbsec->initialized)
461 return -EINVAL;
462
463 if (!ss_initialized)
464 return -EINVAL;
465
466 /*
467 * if we ever use sbsec flags for anything other than tracking mount
468 * settings this is going to need a mask
469 */
470 tmp = sbsec->flags;
471 /* count the number of mount options for this sb */
472 for (i = 0; i < 8; i++) {
473 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500474 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500475 tmp >>= 1;
476 }
477
Eric Parise0007522008-03-05 10:31:54 -0500478 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
479 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500480 rc = -ENOMEM;
481 goto out_free;
482 }
483
Eric Parise0007522008-03-05 10:31:54 -0500484 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
485 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500486 rc = -ENOMEM;
487 goto out_free;
488 }
489
490 i = 0;
491 if (sbsec->flags & FSCONTEXT_MNT) {
492 rc = security_sid_to_context(sbsec->sid, &context, &len);
493 if (rc)
494 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500495 opts->mnt_opts[i] = context;
496 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500497 }
498 if (sbsec->flags & CONTEXT_MNT) {
499 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
500 if (rc)
501 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500502 opts->mnt_opts[i] = context;
503 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500504 }
505 if (sbsec->flags & DEFCONTEXT_MNT) {
506 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
507 if (rc)
508 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500509 opts->mnt_opts[i] = context;
510 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500511 }
512 if (sbsec->flags & ROOTCONTEXT_MNT) {
513 struct inode *root = sbsec->sb->s_root->d_inode;
514 struct inode_security_struct *isec = root->i_security;
515
516 rc = security_sid_to_context(isec->sid, &context, &len);
517 if (rc)
518 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500519 opts->mnt_opts[i] = context;
520 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500521 }
522
Eric Parise0007522008-03-05 10:31:54 -0500523 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500524
525 return 0;
526
527out_free:
Eric Parise0007522008-03-05 10:31:54 -0500528 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500529 return rc;
530}
531
532static int bad_option(struct superblock_security_struct *sbsec, char flag,
533 u32 old_sid, u32 new_sid)
534{
535 /* check if the old mount command had the same options */
536 if (sbsec->initialized)
537 if (!(sbsec->flags & flag) ||
538 (old_sid != new_sid))
539 return 1;
540
541 /* check if we were passed the same options twice,
542 * aka someone passed context=a,context=b
543 */
544 if (!sbsec->initialized)
545 if (sbsec->flags & flag)
546 return 1;
547 return 0;
548}
Eric Parise0007522008-03-05 10:31:54 -0500549
Eric Parisc9180a52007-11-30 13:00:35 -0500550/*
551 * Allow filesystems with binary mount data to explicitly set mount point
552 * labeling information.
553 */
Eric Parise0007522008-03-05 10:31:54 -0500554static int selinux_set_mnt_opts(struct super_block *sb,
555 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500556{
557 int rc = 0, i;
558 struct task_security_struct *tsec = current->security;
559 struct superblock_security_struct *sbsec = sb->s_security;
560 const char *name = sb->s_type->name;
561 struct inode *inode = sbsec->sb->s_root->d_inode;
562 struct inode_security_struct *root_isec = inode->i_security;
563 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
564 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500565 char **mount_options = opts->mnt_opts;
566 int *flags = opts->mnt_opts_flags;
567 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500568
569 mutex_lock(&sbsec->lock);
570
571 if (!ss_initialized) {
572 if (!num_opts) {
573 /* Defer initialization until selinux_complete_init,
574 after the initial policy is loaded and the security
575 server is ready to handle calls. */
576 spin_lock(&sb_security_lock);
577 if (list_empty(&sbsec->list))
578 list_add(&sbsec->list, &superblock_security_head);
579 spin_unlock(&sb_security_lock);
580 goto out;
581 }
582 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400583 printk(KERN_WARNING "SELinux: Unable to set superblock options "
584 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500585 goto out;
586 }
587
588 /*
Eric Parise0007522008-03-05 10:31:54 -0500589 * Binary mount data FS will come through this function twice. Once
590 * from an explicit call and once from the generic calls from the vfs.
591 * Since the generic VFS calls will not contain any security mount data
592 * we need to skip the double mount verification.
593 *
594 * This does open a hole in which we will not notice if the first
595 * mount using this sb set explict options and a second mount using
596 * this sb does not set any security options. (The first options
597 * will be used for both mounts)
598 */
599 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
600 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400601 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500602
603 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500604 * parse the mount options, check if they are valid sids.
605 * also check if someone is trying to mount the same sb more
606 * than once with different security options.
607 */
608 for (i = 0; i < num_opts; i++) {
609 u32 sid;
610 rc = security_context_to_sid(mount_options[i],
611 strlen(mount_options[i]), &sid);
612 if (rc) {
613 printk(KERN_WARNING "SELinux: security_context_to_sid"
614 "(%s) failed for (dev %s, type %s) errno=%d\n",
615 mount_options[i], sb->s_id, name, rc);
616 goto out;
617 }
618 switch (flags[i]) {
619 case FSCONTEXT_MNT:
620 fscontext_sid = sid;
621
622 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
623 fscontext_sid))
624 goto out_double_mount;
625
626 sbsec->flags |= FSCONTEXT_MNT;
627 break;
628 case CONTEXT_MNT:
629 context_sid = sid;
630
631 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
632 context_sid))
633 goto out_double_mount;
634
635 sbsec->flags |= CONTEXT_MNT;
636 break;
637 case ROOTCONTEXT_MNT:
638 rootcontext_sid = sid;
639
640 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
641 rootcontext_sid))
642 goto out_double_mount;
643
644 sbsec->flags |= ROOTCONTEXT_MNT;
645
646 break;
647 case DEFCONTEXT_MNT:
648 defcontext_sid = sid;
649
650 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
651 defcontext_sid))
652 goto out_double_mount;
653
654 sbsec->flags |= DEFCONTEXT_MNT;
655
656 break;
657 default:
658 rc = -EINVAL;
659 goto out;
660 }
661 }
662
663 if (sbsec->initialized) {
664 /* previously mounted with options, but not on this attempt? */
665 if (sbsec->flags && !num_opts)
666 goto out_double_mount;
667 rc = 0;
668 goto out;
669 }
670
671 if (strcmp(sb->s_type->name, "proc") == 0)
672 sbsec->proc = 1;
673
674 /* Determine the labeling behavior to use for this filesystem type. */
675 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
676 if (rc) {
677 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +1100678 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500679 goto out;
680 }
681
682 /* sets the context of the superblock for the fs being mounted. */
683 if (fscontext_sid) {
684
685 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
686 if (rc)
687 goto out;
688
689 sbsec->sid = fscontext_sid;
690 }
691
692 /*
693 * Switch to using mount point labeling behavior.
694 * sets the label used on all file below the mountpoint, and will set
695 * the superblock context if not already set.
696 */
697 if (context_sid) {
698 if (!fscontext_sid) {
699 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
700 if (rc)
701 goto out;
702 sbsec->sid = context_sid;
703 } else {
704 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
705 if (rc)
706 goto out;
707 }
708 if (!rootcontext_sid)
709 rootcontext_sid = context_sid;
710
711 sbsec->mntpoint_sid = context_sid;
712 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
713 }
714
715 if (rootcontext_sid) {
716 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
717 if (rc)
718 goto out;
719
720 root_isec->sid = rootcontext_sid;
721 root_isec->initialized = 1;
722 }
723
724 if (defcontext_sid) {
725 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
726 rc = -EINVAL;
727 printk(KERN_WARNING "SELinux: defcontext option is "
728 "invalid for this filesystem type\n");
729 goto out;
730 }
731
732 if (defcontext_sid != sbsec->def_sid) {
733 rc = may_context_mount_inode_relabel(defcontext_sid,
734 sbsec, tsec);
735 if (rc)
736 goto out;
737 }
738
739 sbsec->def_sid = defcontext_sid;
740 }
741
742 rc = sb_finish_set_opts(sb);
743out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700744 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500746out_double_mount:
747 rc = -EINVAL;
748 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
749 "security settings for (dev %s, type %s)\n", sb->s_id, name);
750 goto out;
751}
752
753static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
754 struct super_block *newsb)
755{
756 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
757 struct superblock_security_struct *newsbsec = newsb->s_security;
758
759 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
760 int set_context = (oldsbsec->flags & CONTEXT_MNT);
761 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
762
Eric Paris0f5e6422008-04-21 16:24:11 -0400763 /*
764 * if the parent was able to be mounted it clearly had no special lsm
765 * mount options. thus we can safely put this sb on the list and deal
766 * with it later
767 */
768 if (!ss_initialized) {
769 spin_lock(&sb_security_lock);
770 if (list_empty(&newsbsec->list))
771 list_add(&newsbsec->list, &superblock_security_head);
772 spin_unlock(&sb_security_lock);
773 return;
774 }
Eric Parisc9180a52007-11-30 13:00:35 -0500775
Eric Parisc9180a52007-11-30 13:00:35 -0500776 /* how can we clone if the old one wasn't set up?? */
777 BUG_ON(!oldsbsec->initialized);
778
Eric Paris5a552612008-04-09 14:08:35 -0400779 /* if fs is reusing a sb, just let its options stand... */
780 if (newsbsec->initialized)
781 return;
782
Eric Parisc9180a52007-11-30 13:00:35 -0500783 mutex_lock(&newsbsec->lock);
784
785 newsbsec->flags = oldsbsec->flags;
786
787 newsbsec->sid = oldsbsec->sid;
788 newsbsec->def_sid = oldsbsec->def_sid;
789 newsbsec->behavior = oldsbsec->behavior;
790
791 if (set_context) {
792 u32 sid = oldsbsec->mntpoint_sid;
793
794 if (!set_fscontext)
795 newsbsec->sid = sid;
796 if (!set_rootcontext) {
797 struct inode *newinode = newsb->s_root->d_inode;
798 struct inode_security_struct *newisec = newinode->i_security;
799 newisec->sid = sid;
800 }
801 newsbsec->mntpoint_sid = sid;
802 }
803 if (set_rootcontext) {
804 const struct inode *oldinode = oldsb->s_root->d_inode;
805 const struct inode_security_struct *oldisec = oldinode->i_security;
806 struct inode *newinode = newsb->s_root->d_inode;
807 struct inode_security_struct *newisec = newinode->i_security;
808
809 newisec->sid = oldisec->sid;
810 }
811
812 sb_finish_set_opts(newsb);
813 mutex_unlock(&newsbsec->lock);
814}
815
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200816static int selinux_parse_opts_str(char *options,
817 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500818{
Eric Parise0007522008-03-05 10:31:54 -0500819 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500820 char *context = NULL, *defcontext = NULL;
821 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500822 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500823
Eric Parise0007522008-03-05 10:31:54 -0500824 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500825
826 /* Standard string-based options. */
827 while ((p = strsep(&options, "|")) != NULL) {
828 int token;
829 substring_t args[MAX_OPT_ARGS];
830
831 if (!*p)
832 continue;
833
834 token = match_token(p, tokens, args);
835
836 switch (token) {
837 case Opt_context:
838 if (context || defcontext) {
839 rc = -EINVAL;
840 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
841 goto out_err;
842 }
843 context = match_strdup(&args[0]);
844 if (!context) {
845 rc = -ENOMEM;
846 goto out_err;
847 }
848 break;
849
850 case Opt_fscontext:
851 if (fscontext) {
852 rc = -EINVAL;
853 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
854 goto out_err;
855 }
856 fscontext = match_strdup(&args[0]);
857 if (!fscontext) {
858 rc = -ENOMEM;
859 goto out_err;
860 }
861 break;
862
863 case Opt_rootcontext:
864 if (rootcontext) {
865 rc = -EINVAL;
866 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
867 goto out_err;
868 }
869 rootcontext = match_strdup(&args[0]);
870 if (!rootcontext) {
871 rc = -ENOMEM;
872 goto out_err;
873 }
874 break;
875
876 case Opt_defcontext:
877 if (context || defcontext) {
878 rc = -EINVAL;
879 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
880 goto out_err;
881 }
882 defcontext = match_strdup(&args[0]);
883 if (!defcontext) {
884 rc = -ENOMEM;
885 goto out_err;
886 }
887 break;
888
889 default:
890 rc = -EINVAL;
891 printk(KERN_WARNING "SELinux: unknown mount option\n");
892 goto out_err;
893
894 }
895 }
896
Eric Parise0007522008-03-05 10:31:54 -0500897 rc = -ENOMEM;
898 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
899 if (!opts->mnt_opts)
900 goto out_err;
901
902 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
903 if (!opts->mnt_opts_flags) {
904 kfree(opts->mnt_opts);
905 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500906 }
907
Eric Parise0007522008-03-05 10:31:54 -0500908 if (fscontext) {
909 opts->mnt_opts[num_mnt_opts] = fscontext;
910 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
911 }
912 if (context) {
913 opts->mnt_opts[num_mnt_opts] = context;
914 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
915 }
916 if (rootcontext) {
917 opts->mnt_opts[num_mnt_opts] = rootcontext;
918 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
919 }
920 if (defcontext) {
921 opts->mnt_opts[num_mnt_opts] = defcontext;
922 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
923 }
924
925 opts->num_mnt_opts = num_mnt_opts;
926 return 0;
927
Eric Parisc9180a52007-11-30 13:00:35 -0500928out_err:
929 kfree(context);
930 kfree(defcontext);
931 kfree(fscontext);
932 kfree(rootcontext);
933 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
Eric Parise0007522008-03-05 10:31:54 -0500935/*
936 * string mount options parsing and call set the sbsec
937 */
938static int superblock_doinit(struct super_block *sb, void *data)
939{
940 int rc = 0;
941 char *options = data;
942 struct security_mnt_opts opts;
943
944 security_init_mnt_opts(&opts);
945
946 if (!data)
947 goto out;
948
949 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
950
951 rc = selinux_parse_opts_str(options, &opts);
952 if (rc)
953 goto out_err;
954
955out:
956 rc = selinux_set_mnt_opts(sb, &opts);
957
958out_err:
959 security_free_mnt_opts(&opts);
960 return rc;
961}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
963static inline u16 inode_mode_to_security_class(umode_t mode)
964{
965 switch (mode & S_IFMT) {
966 case S_IFSOCK:
967 return SECCLASS_SOCK_FILE;
968 case S_IFLNK:
969 return SECCLASS_LNK_FILE;
970 case S_IFREG:
971 return SECCLASS_FILE;
972 case S_IFBLK:
973 return SECCLASS_BLK_FILE;
974 case S_IFDIR:
975 return SECCLASS_DIR;
976 case S_IFCHR:
977 return SECCLASS_CHR_FILE;
978 case S_IFIFO:
979 return SECCLASS_FIFO_FILE;
980
981 }
982
983 return SECCLASS_FILE;
984}
985
James Morris13402582005-09-30 14:24:34 -0400986static inline int default_protocol_stream(int protocol)
987{
988 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
989}
990
991static inline int default_protocol_dgram(int protocol)
992{
993 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
994}
995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996static inline u16 socket_type_to_security_class(int family, int type, int protocol)
997{
998 switch (family) {
999 case PF_UNIX:
1000 switch (type) {
1001 case SOCK_STREAM:
1002 case SOCK_SEQPACKET:
1003 return SECCLASS_UNIX_STREAM_SOCKET;
1004 case SOCK_DGRAM:
1005 return SECCLASS_UNIX_DGRAM_SOCKET;
1006 }
1007 break;
1008 case PF_INET:
1009 case PF_INET6:
1010 switch (type) {
1011 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001012 if (default_protocol_stream(protocol))
1013 return SECCLASS_TCP_SOCKET;
1014 else
1015 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001017 if (default_protocol_dgram(protocol))
1018 return SECCLASS_UDP_SOCKET;
1019 else
1020 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001021 case SOCK_DCCP:
1022 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001023 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return SECCLASS_RAWIP_SOCKET;
1025 }
1026 break;
1027 case PF_NETLINK:
1028 switch (protocol) {
1029 case NETLINK_ROUTE:
1030 return SECCLASS_NETLINK_ROUTE_SOCKET;
1031 case NETLINK_FIREWALL:
1032 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001033 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1035 case NETLINK_NFLOG:
1036 return SECCLASS_NETLINK_NFLOG_SOCKET;
1037 case NETLINK_XFRM:
1038 return SECCLASS_NETLINK_XFRM_SOCKET;
1039 case NETLINK_SELINUX:
1040 return SECCLASS_NETLINK_SELINUX_SOCKET;
1041 case NETLINK_AUDIT:
1042 return SECCLASS_NETLINK_AUDIT_SOCKET;
1043 case NETLINK_IP6_FW:
1044 return SECCLASS_NETLINK_IP6FW_SOCKET;
1045 case NETLINK_DNRTMSG:
1046 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001047 case NETLINK_KOBJECT_UEVENT:
1048 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 default:
1050 return SECCLASS_NETLINK_SOCKET;
1051 }
1052 case PF_PACKET:
1053 return SECCLASS_PACKET_SOCKET;
1054 case PF_KEY:
1055 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001056 case PF_APPLETALK:
1057 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059
1060 return SECCLASS_SOCKET;
1061}
1062
1063#ifdef CONFIG_PROC_FS
1064static int selinux_proc_get_sid(struct proc_dir_entry *de,
1065 u16 tclass,
1066 u32 *sid)
1067{
1068 int buflen, rc;
1069 char *buffer, *path, *end;
1070
Eric Paris828dfe12008-04-17 13:17:49 -04001071 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 if (!buffer)
1073 return -ENOMEM;
1074
1075 buflen = PAGE_SIZE;
1076 end = buffer+buflen;
1077 *--end = '\0';
1078 buflen--;
1079 path = end-1;
1080 *path = '/';
1081 while (de && de != de->parent) {
1082 buflen -= de->namelen + 1;
1083 if (buflen < 0)
1084 break;
1085 end -= de->namelen;
1086 memcpy(end, de->name, de->namelen);
1087 *--end = '/';
1088 path = end;
1089 de = de->parent;
1090 }
1091 rc = security_genfs_sid("proc", path, tclass, sid);
1092 free_page((unsigned long)buffer);
1093 return rc;
1094}
1095#else
1096static int selinux_proc_get_sid(struct proc_dir_entry *de,
1097 u16 tclass,
1098 u32 *sid)
1099{
1100 return -EINVAL;
1101}
1102#endif
1103
1104/* The inode's security attributes must be initialized before first use. */
1105static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1106{
1107 struct superblock_security_struct *sbsec = NULL;
1108 struct inode_security_struct *isec = inode->i_security;
1109 u32 sid;
1110 struct dentry *dentry;
1111#define INITCONTEXTLEN 255
1112 char *context = NULL;
1113 unsigned len = 0;
1114 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116 if (isec->initialized)
1117 goto out;
1118
Eric Paris23970742006-09-25 23:32:01 -07001119 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001121 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 sbsec = inode->i_sb->s_security;
1124 if (!sbsec->initialized) {
1125 /* Defer initialization until selinux_complete_init,
1126 after the initial policy is loaded and the security
1127 server is ready to handle calls. */
1128 spin_lock(&sbsec->isec_lock);
1129 if (list_empty(&isec->list))
1130 list_add(&isec->list, &sbsec->isec_head);
1131 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001132 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 }
1134
1135 switch (sbsec->behavior) {
1136 case SECURITY_FS_USE_XATTR:
1137 if (!inode->i_op->getxattr) {
1138 isec->sid = sbsec->def_sid;
1139 break;
1140 }
1141
1142 /* Need a dentry, since the xattr API requires one.
1143 Life would be simpler if we could just pass the inode. */
1144 if (opt_dentry) {
1145 /* Called from d_instantiate or d_splice_alias. */
1146 dentry = dget(opt_dentry);
1147 } else {
1148 /* Called from selinux_complete_init, try to find a dentry. */
1149 dentry = d_find_alias(inode);
1150 }
1151 if (!dentry) {
Eric Paris744ba352008-04-17 11:52:44 -04001152 printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001153 "ino=%ld\n", __func__, inode->i_sb->s_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001155 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
1157
1158 len = INITCONTEXTLEN;
Stephen Smalley869ab512008-04-04 08:46:05 -04001159 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 if (!context) {
1161 rc = -ENOMEM;
1162 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001163 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
1165 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1166 context, len);
1167 if (rc == -ERANGE) {
1168 /* Need a larger buffer. Query for the right size. */
1169 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1170 NULL, 0);
1171 if (rc < 0) {
1172 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001173 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 }
1175 kfree(context);
1176 len = rc;
Stephen Smalley869ab512008-04-04 08:46:05 -04001177 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 if (!context) {
1179 rc = -ENOMEM;
1180 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001181 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 rc = inode->i_op->getxattr(dentry,
1184 XATTR_NAME_SELINUX,
1185 context, len);
1186 }
1187 dput(dentry);
1188 if (rc < 0) {
1189 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001190 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001191 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 -rc, inode->i_sb->s_id, inode->i_ino);
1193 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001194 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
1196 /* Map ENODATA to the default file SID */
1197 sid = sbsec->def_sid;
1198 rc = 0;
1199 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001200 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001201 sbsec->def_sid,
1202 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 if (rc) {
Eric Paris744ba352008-04-17 11:52:44 -04001204 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 "returned %d for dev=%s ino=%ld\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001206 __func__, context, -rc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 inode->i_sb->s_id, inode->i_ino);
1208 kfree(context);
1209 /* Leave with the unlabeled SID */
1210 rc = 0;
1211 break;
1212 }
1213 }
1214 kfree(context);
1215 isec->sid = sid;
1216 break;
1217 case SECURITY_FS_USE_TASK:
1218 isec->sid = isec->task_sid;
1219 break;
1220 case SECURITY_FS_USE_TRANS:
1221 /* Default to the fs SID. */
1222 isec->sid = sbsec->sid;
1223
1224 /* Try to obtain a transition SID. */
1225 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1226 rc = security_transition_sid(isec->task_sid,
1227 sbsec->sid,
1228 isec->sclass,
1229 &sid);
1230 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001231 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 isec->sid = sid;
1233 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001234 case SECURITY_FS_USE_MNTPOINT:
1235 isec->sid = sbsec->mntpoint_sid;
1236 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001238 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 isec->sid = sbsec->sid;
1240
1241 if (sbsec->proc) {
1242 struct proc_inode *proci = PROC_I(inode);
1243 if (proci->pde) {
1244 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1245 rc = selinux_proc_get_sid(proci->pde,
1246 isec->sclass,
1247 &sid);
1248 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001249 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 isec->sid = sid;
1251 }
1252 }
1253 break;
1254 }
1255
1256 isec->initialized = 1;
1257
Eric Paris23970742006-09-25 23:32:01 -07001258out_unlock:
1259 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260out:
1261 if (isec->sclass == SECCLASS_FILE)
1262 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 return rc;
1264}
1265
1266/* Convert a Linux signal to an access vector. */
1267static inline u32 signal_to_av(int sig)
1268{
1269 u32 perm = 0;
1270
1271 switch (sig) {
1272 case SIGCHLD:
1273 /* Commonly granted from child to parent. */
1274 perm = PROCESS__SIGCHLD;
1275 break;
1276 case SIGKILL:
1277 /* Cannot be caught or ignored */
1278 perm = PROCESS__SIGKILL;
1279 break;
1280 case SIGSTOP:
1281 /* Cannot be caught or ignored */
1282 perm = PROCESS__SIGSTOP;
1283 break;
1284 default:
1285 /* All other signals. */
1286 perm = PROCESS__SIGNAL;
1287 break;
1288 }
1289
1290 return perm;
1291}
1292
1293/* Check permission betweeen a pair of tasks, e.g. signal checks,
1294 fork check, ptrace check, etc. */
1295static int task_has_perm(struct task_struct *tsk1,
1296 struct task_struct *tsk2,
1297 u32 perms)
1298{
1299 struct task_security_struct *tsec1, *tsec2;
1300
1301 tsec1 = tsk1->security;
1302 tsec2 = tsk2->security;
1303 return avc_has_perm(tsec1->sid, tsec2->sid,
1304 SECCLASS_PROCESS, perms, NULL);
1305}
1306
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001307#if CAP_LAST_CAP > 63
1308#error Fix SELinux to handle capabilities > 63.
1309#endif
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311/* Check whether a task is allowed to use a capability. */
1312static int task_has_capability(struct task_struct *tsk,
1313 int cap)
1314{
1315 struct task_security_struct *tsec;
1316 struct avc_audit_data ad;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001317 u16 sclass;
1318 u32 av = CAP_TO_MASK(cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
1320 tsec = tsk->security;
1321
Eric Paris828dfe12008-04-17 13:17:49 -04001322 AVC_AUDIT_DATA_INIT(&ad, CAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 ad.tsk = tsk;
1324 ad.u.cap = cap;
1325
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001326 switch (CAP_TO_INDEX(cap)) {
1327 case 0:
1328 sclass = SECCLASS_CAPABILITY;
1329 break;
1330 case 1:
1331 sclass = SECCLASS_CAPABILITY2;
1332 break;
1333 default:
1334 printk(KERN_ERR
1335 "SELinux: out of range capability %d\n", cap);
1336 BUG();
1337 }
1338 return avc_has_perm(tsec->sid, tsec->sid, sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
1341/* Check whether a task is allowed to use a system operation. */
1342static int task_has_system(struct task_struct *tsk,
1343 u32 perms)
1344{
1345 struct task_security_struct *tsec;
1346
1347 tsec = tsk->security;
1348
1349 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1350 SECCLASS_SYSTEM, perms, NULL);
1351}
1352
1353/* Check whether a task has a particular permission to an inode.
1354 The 'adp' parameter is optional and allows other audit
1355 data to be passed (e.g. the dentry). */
1356static int inode_has_perm(struct task_struct *tsk,
1357 struct inode *inode,
1358 u32 perms,
1359 struct avc_audit_data *adp)
1360{
1361 struct task_security_struct *tsec;
1362 struct inode_security_struct *isec;
1363 struct avc_audit_data ad;
1364
Eric Paris828dfe12008-04-17 13:17:49 -04001365 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001366 return 0;
1367
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 tsec = tsk->security;
1369 isec = inode->i_security;
1370
1371 if (!adp) {
1372 adp = &ad;
1373 AVC_AUDIT_DATA_INIT(&ad, FS);
1374 ad.u.fs.inode = inode;
1375 }
1376
1377 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1378}
1379
1380/* Same as inode_has_perm, but pass explicit audit data containing
1381 the dentry to help the auditing code to more easily generate the
1382 pathname if needed. */
1383static inline int dentry_has_perm(struct task_struct *tsk,
1384 struct vfsmount *mnt,
1385 struct dentry *dentry,
1386 u32 av)
1387{
1388 struct inode *inode = dentry->d_inode;
1389 struct avc_audit_data ad;
Eric Paris828dfe12008-04-17 13:17:49 -04001390 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001391 ad.u.fs.path.mnt = mnt;
1392 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return inode_has_perm(tsk, inode, av, &ad);
1394}
1395
1396/* Check whether a task can use an open file descriptor to
1397 access an inode in a given way. Check access to the
1398 descriptor itself, and then use dentry_has_perm to
1399 check a particular permission to the file.
1400 Access to the descriptor is implicitly granted if it
1401 has the same SID as the process. If av is zero, then
1402 access to the file is not checked, e.g. for cases
1403 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001404static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 struct file *file,
1406 u32 av)
1407{
1408 struct task_security_struct *tsec = tsk->security;
1409 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001410 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 struct avc_audit_data ad;
1412 int rc;
1413
1414 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001415 ad.u.fs.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
1417 if (tsec->sid != fsec->sid) {
1418 rc = avc_has_perm(tsec->sid, fsec->sid,
1419 SECCLASS_FD,
1420 FD__USE,
1421 &ad);
1422 if (rc)
1423 return rc;
1424 }
1425
1426 /* av is zero if only checking access to the descriptor. */
1427 if (av)
1428 return inode_has_perm(tsk, inode, av, &ad);
1429
1430 return 0;
1431}
1432
1433/* Check whether a task can create a file. */
1434static int may_create(struct inode *dir,
1435 struct dentry *dentry,
1436 u16 tclass)
1437{
1438 struct task_security_struct *tsec;
1439 struct inode_security_struct *dsec;
1440 struct superblock_security_struct *sbsec;
1441 u32 newsid;
1442 struct avc_audit_data ad;
1443 int rc;
1444
1445 tsec = current->security;
1446 dsec = dir->i_security;
1447 sbsec = dir->i_sb->s_security;
1448
1449 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001450 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1453 DIR__ADD_NAME | DIR__SEARCH,
1454 &ad);
1455 if (rc)
1456 return rc;
1457
1458 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1459 newsid = tsec->create_sid;
1460 } else {
1461 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1462 &newsid);
1463 if (rc)
1464 return rc;
1465 }
1466
1467 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1468 if (rc)
1469 return rc;
1470
1471 return avc_has_perm(newsid, sbsec->sid,
1472 SECCLASS_FILESYSTEM,
1473 FILESYSTEM__ASSOCIATE, &ad);
1474}
1475
Michael LeMay4eb582c2006-06-26 00:24:57 -07001476/* Check whether a task can create a key. */
1477static int may_create_key(u32 ksid,
1478 struct task_struct *ctx)
1479{
1480 struct task_security_struct *tsec;
1481
1482 tsec = ctx->security;
1483
1484 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1485}
1486
Eric Paris828dfe12008-04-17 13:17:49 -04001487#define MAY_LINK 0
1488#define MAY_UNLINK 1
1489#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491/* Check whether a task can link, unlink, or rmdir a file/directory. */
1492static int may_link(struct inode *dir,
1493 struct dentry *dentry,
1494 int kind)
1495
1496{
1497 struct task_security_struct *tsec;
1498 struct inode_security_struct *dsec, *isec;
1499 struct avc_audit_data ad;
1500 u32 av;
1501 int rc;
1502
1503 tsec = current->security;
1504 dsec = dir->i_security;
1505 isec = dentry->d_inode->i_security;
1506
1507 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001508 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
1510 av = DIR__SEARCH;
1511 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1512 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1513 if (rc)
1514 return rc;
1515
1516 switch (kind) {
1517 case MAY_LINK:
1518 av = FILE__LINK;
1519 break;
1520 case MAY_UNLINK:
1521 av = FILE__UNLINK;
1522 break;
1523 case MAY_RMDIR:
1524 av = DIR__RMDIR;
1525 break;
1526 default:
Eric Paris744ba352008-04-17 11:52:44 -04001527 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1528 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 return 0;
1530 }
1531
1532 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1533 return rc;
1534}
1535
1536static inline int may_rename(struct inode *old_dir,
1537 struct dentry *old_dentry,
1538 struct inode *new_dir,
1539 struct dentry *new_dentry)
1540{
1541 struct task_security_struct *tsec;
1542 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1543 struct avc_audit_data ad;
1544 u32 av;
1545 int old_is_dir, new_is_dir;
1546 int rc;
1547
1548 tsec = current->security;
1549 old_dsec = old_dir->i_security;
1550 old_isec = old_dentry->d_inode->i_security;
1551 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1552 new_dsec = new_dir->i_security;
1553
1554 AVC_AUDIT_DATA_INIT(&ad, FS);
1555
Jan Blunck44707fd2008-02-14 19:38:33 -08001556 ad.u.fs.path.dentry = old_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1558 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1559 if (rc)
1560 return rc;
1561 rc = avc_has_perm(tsec->sid, old_isec->sid,
1562 old_isec->sclass, FILE__RENAME, &ad);
1563 if (rc)
1564 return rc;
1565 if (old_is_dir && new_dir != old_dir) {
1566 rc = avc_has_perm(tsec->sid, old_isec->sid,
1567 old_isec->sclass, DIR__REPARENT, &ad);
1568 if (rc)
1569 return rc;
1570 }
1571
Jan Blunck44707fd2008-02-14 19:38:33 -08001572 ad.u.fs.path.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 av = DIR__ADD_NAME | DIR__SEARCH;
1574 if (new_dentry->d_inode)
1575 av |= DIR__REMOVE_NAME;
1576 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1577 if (rc)
1578 return rc;
1579 if (new_dentry->d_inode) {
1580 new_isec = new_dentry->d_inode->i_security;
1581 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1582 rc = avc_has_perm(tsec->sid, new_isec->sid,
1583 new_isec->sclass,
1584 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1585 if (rc)
1586 return rc;
1587 }
1588
1589 return 0;
1590}
1591
1592/* Check whether a task can perform a filesystem operation. */
1593static int superblock_has_perm(struct task_struct *tsk,
1594 struct super_block *sb,
1595 u32 perms,
1596 struct avc_audit_data *ad)
1597{
1598 struct task_security_struct *tsec;
1599 struct superblock_security_struct *sbsec;
1600
1601 tsec = tsk->security;
1602 sbsec = sb->s_security;
1603 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1604 perms, ad);
1605}
1606
1607/* Convert a Linux mode and permission mask to an access vector. */
1608static inline u32 file_mask_to_av(int mode, int mask)
1609{
1610 u32 av = 0;
1611
1612 if ((mode & S_IFMT) != S_IFDIR) {
1613 if (mask & MAY_EXEC)
1614 av |= FILE__EXECUTE;
1615 if (mask & MAY_READ)
1616 av |= FILE__READ;
1617
1618 if (mask & MAY_APPEND)
1619 av |= FILE__APPEND;
1620 else if (mask & MAY_WRITE)
1621 av |= FILE__WRITE;
1622
1623 } else {
1624 if (mask & MAY_EXEC)
1625 av |= DIR__SEARCH;
1626 if (mask & MAY_WRITE)
1627 av |= DIR__WRITE;
1628 if (mask & MAY_READ)
1629 av |= DIR__READ;
1630 }
1631
1632 return av;
1633}
1634
Eric Parisb0c636b2008-02-28 12:58:40 -05001635/*
1636 * Convert a file mask to an access vector and include the correct open
1637 * open permission.
1638 */
1639static inline u32 open_file_mask_to_av(int mode, int mask)
1640{
1641 u32 av = file_mask_to_av(mode, mask);
1642
1643 if (selinux_policycap_openperm) {
1644 /*
1645 * lnk files and socks do not really have an 'open'
1646 */
1647 if (S_ISREG(mode))
1648 av |= FILE__OPEN;
1649 else if (S_ISCHR(mode))
1650 av |= CHR_FILE__OPEN;
1651 else if (S_ISBLK(mode))
1652 av |= BLK_FILE__OPEN;
1653 else if (S_ISFIFO(mode))
1654 av |= FIFO_FILE__OPEN;
1655 else if (S_ISDIR(mode))
1656 av |= DIR__OPEN;
1657 else
Eric Paris744ba352008-04-17 11:52:44 -04001658 printk(KERN_ERR "SELinux: WARNING: inside %s with "
1659 "unknown mode:%x\n", __func__, mode);
Eric Parisb0c636b2008-02-28 12:58:40 -05001660 }
1661 return av;
1662}
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664/* Convert a Linux file to an access vector. */
1665static inline u32 file_to_av(struct file *file)
1666{
1667 u32 av = 0;
1668
1669 if (file->f_mode & FMODE_READ)
1670 av |= FILE__READ;
1671 if (file->f_mode & FMODE_WRITE) {
1672 if (file->f_flags & O_APPEND)
1673 av |= FILE__APPEND;
1674 else
1675 av |= FILE__WRITE;
1676 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001677 if (!av) {
1678 /*
1679 * Special file opened with flags 3 for ioctl-only use.
1680 */
1681 av = FILE__IOCTL;
1682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 return av;
1685}
1686
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687/* Hook functions begin here. */
1688
Stephen Smalley006ebb42008-05-19 08:32:49 -04001689static int selinux_ptrace(struct task_struct *parent,
1690 struct task_struct *child,
1691 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 int rc;
1694
Stephen Smalley006ebb42008-05-19 08:32:49 -04001695 rc = secondary_ops->ptrace(parent, child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 if (rc)
1697 return rc;
1698
Stephen Smalley006ebb42008-05-19 08:32:49 -04001699 if (mode == PTRACE_MODE_READ) {
1700 struct task_security_struct *tsec = parent->security;
1701 struct task_security_struct *csec = child->security;
1702 return avc_has_perm(tsec->sid, csec->sid,
1703 SECCLASS_FILE, FILE__READ, NULL);
1704 }
1705
Roland McGrath03563572008-03-26 15:46:39 -07001706 return task_has_perm(parent, child, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707}
1708
1709static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001710 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
1712 int error;
1713
1714 error = task_has_perm(current, target, PROCESS__GETCAP);
1715 if (error)
1716 return error;
1717
1718 return secondary_ops->capget(target, effective, inheritable, permitted);
1719}
1720
1721static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001722 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723{
1724 int error;
1725
1726 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1727 if (error)
1728 return error;
1729
1730 return task_has_perm(current, target, PROCESS__SETCAP);
1731}
1732
1733static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001734 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735{
1736 secondary_ops->capset_set(target, effective, inheritable, permitted);
1737}
1738
1739static int selinux_capable(struct task_struct *tsk, int cap)
1740{
1741 int rc;
1742
1743 rc = secondary_ops->capable(tsk, cap);
1744 if (rc)
1745 return rc;
1746
Eric Paris828dfe12008-04-17 13:17:49 -04001747 return task_has_capability(tsk, cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748}
1749
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001750static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1751{
1752 int buflen, rc;
1753 char *buffer, *path, *end;
1754
1755 rc = -ENOMEM;
Eric Paris828dfe12008-04-17 13:17:49 -04001756 buffer = (char *)__get_free_page(GFP_KERNEL);
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001757 if (!buffer)
1758 goto out;
1759
1760 buflen = PAGE_SIZE;
1761 end = buffer+buflen;
1762 *--end = '\0';
1763 buflen--;
1764 path = end-1;
1765 *path = '/';
1766 while (table) {
1767 const char *name = table->procname;
1768 size_t namelen = strlen(name);
1769 buflen -= namelen + 1;
1770 if (buflen < 0)
1771 goto out_free;
1772 end -= namelen;
1773 memcpy(end, name, namelen);
1774 *--end = '/';
1775 path = end;
1776 table = table->parent;
1777 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001778 buflen -= 4;
1779 if (buflen < 0)
1780 goto out_free;
1781 end -= 4;
1782 memcpy(end, "/sys", 4);
1783 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001784 rc = security_genfs_sid("proc", path, tclass, sid);
1785out_free:
1786 free_page((unsigned long)buffer);
1787out:
1788 return rc;
1789}
1790
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791static int selinux_sysctl(ctl_table *table, int op)
1792{
1793 int error = 0;
1794 u32 av;
1795 struct task_security_struct *tsec;
1796 u32 tsid;
1797 int rc;
1798
1799 rc = secondary_ops->sysctl(table, op);
1800 if (rc)
1801 return rc;
1802
1803 tsec = current->security;
1804
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001805 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1806 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 if (rc) {
1808 /* Default to the well-defined sysctl SID. */
1809 tsid = SECINITSID_SYSCTL;
1810 }
1811
1812 /* The op values are "defined" in sysctl.c, thereby creating
1813 * a bad coupling between this module and sysctl.c */
Eric Paris828dfe12008-04-17 13:17:49 -04001814 if (op == 001) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 error = avc_has_perm(tsec->sid, tsid,
1816 SECCLASS_DIR, DIR__SEARCH, NULL);
1817 } else {
1818 av = 0;
1819 if (op & 004)
1820 av |= FILE__READ;
1821 if (op & 002)
1822 av |= FILE__WRITE;
1823 if (av)
1824 error = avc_has_perm(tsec->sid, tsid,
1825 SECCLASS_FILE, av, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 return error;
1829}
1830
1831static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1832{
1833 int rc = 0;
1834
1835 if (!sb)
1836 return 0;
1837
1838 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001839 case Q_SYNC:
1840 case Q_QUOTAON:
1841 case Q_QUOTAOFF:
1842 case Q_SETINFO:
1843 case Q_SETQUOTA:
1844 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
1845 NULL);
1846 break;
1847 case Q_GETFMT:
1848 case Q_GETINFO:
1849 case Q_GETQUOTA:
1850 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
1851 NULL);
1852 break;
1853 default:
1854 rc = 0; /* let the kernel handle invalid cmds */
1855 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 }
1857 return rc;
1858}
1859
1860static int selinux_quota_on(struct dentry *dentry)
1861{
1862 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1863}
1864
1865static int selinux_syslog(int type)
1866{
1867 int rc;
1868
1869 rc = secondary_ops->syslog(type);
1870 if (rc)
1871 return rc;
1872
1873 switch (type) {
Eric Paris828dfe12008-04-17 13:17:49 -04001874 case 3: /* Read last kernel messages */
1875 case 10: /* Return size of the log buffer */
1876 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1877 break;
1878 case 6: /* Disable logging to console */
1879 case 7: /* Enable logging to console */
1880 case 8: /* Set level of messages printed to console */
1881 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1882 break;
1883 case 0: /* Close log */
1884 case 1: /* Open log */
1885 case 2: /* Read from log */
1886 case 4: /* Read/clear last kernel messages */
1887 case 5: /* Clear ring buffer */
1888 default:
1889 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1890 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 }
1892 return rc;
1893}
1894
1895/*
1896 * Check that a process has enough memory to allocate a new virtual
1897 * mapping. 0 means there is enough memory for the allocation to
1898 * succeed and -ENOMEM implies there is not.
1899 *
1900 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1901 * if the capability is granted, but __vm_enough_memory requires 1 if
1902 * the capability is granted.
1903 *
1904 * Do not audit the selinux permission check, as this is applied to all
1905 * processes that allocate mappings.
1906 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001907static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908{
1909 int rc, cap_sys_admin = 0;
1910 struct task_security_struct *tsec = current->security;
1911
1912 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1913 if (rc == 0)
1914 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001915 SECCLASS_CAPABILITY,
1916 CAP_TO_MASK(CAP_SYS_ADMIN),
1917 0,
1918 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
1920 if (rc == 0)
1921 cap_sys_admin = 1;
1922
Alan Cox34b4e4a2007-08-22 14:01:28 -07001923 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924}
1925
Roland McGrath03563572008-03-26 15:46:39 -07001926/**
1927 * task_tracer_task - return the task that is tracing the given task
1928 * @task: task to consider
1929 *
1930 * Returns NULL if noone is tracing @task, or the &struct task_struct
1931 * pointer to its tracer.
1932 *
1933 * Must be called under rcu_read_lock().
1934 */
1935static struct task_struct *task_tracer_task(struct task_struct *task)
1936{
1937 if (task->ptrace & PT_PTRACED)
1938 return rcu_dereference(task->parent);
1939 return NULL;
1940}
1941
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942/* binprm security operations */
1943
1944static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1945{
1946 struct bprm_security_struct *bsec;
1947
James Morris89d155e2005-10-30 14:59:21 -08001948 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 if (!bsec)
1950 return -ENOMEM;
1951
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 bsec->sid = SECINITSID_UNLABELED;
1953 bsec->set = 0;
1954
1955 bprm->security = bsec;
1956 return 0;
1957}
1958
1959static int selinux_bprm_set_security(struct linux_binprm *bprm)
1960{
1961 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001962 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 struct inode_security_struct *isec;
1964 struct bprm_security_struct *bsec;
1965 u32 newsid;
1966 struct avc_audit_data ad;
1967 int rc;
1968
1969 rc = secondary_ops->bprm_set_security(bprm);
1970 if (rc)
1971 return rc;
1972
1973 bsec = bprm->security;
1974
1975 if (bsec->set)
1976 return 0;
1977
1978 tsec = current->security;
1979 isec = inode->i_security;
1980
1981 /* Default to the current task SID. */
1982 bsec->sid = tsec->sid;
1983
Michael LeMay28eba5b2006-06-27 02:53:42 -07001984 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001986 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001987 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989 if (tsec->exec_sid) {
1990 newsid = tsec->exec_sid;
1991 /* Reset exec SID on execve. */
1992 tsec->exec_sid = 0;
1993 } else {
1994 /* Check for a default transition on this program. */
1995 rc = security_transition_sid(tsec->sid, isec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04001996 SECCLASS_PROCESS, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 if (rc)
1998 return rc;
1999 }
2000
2001 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002002 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
Josef Sipek3d5ff522006-12-08 02:37:38 -08002004 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 newsid = tsec->sid;
2006
Eric Paris828dfe12008-04-17 13:17:49 -04002007 if (tsec->sid == newsid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 rc = avc_has_perm(tsec->sid, isec->sid,
2009 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2010 if (rc)
2011 return rc;
2012 } else {
2013 /* Check permissions for the transition. */
2014 rc = avc_has_perm(tsec->sid, newsid,
2015 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2016 if (rc)
2017 return rc;
2018
2019 rc = avc_has_perm(newsid, isec->sid,
2020 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2021 if (rc)
2022 return rc;
2023
2024 /* Clear any possibly unsafe personality bits on exec: */
2025 current->personality &= ~PER_CLEAR_ON_SETID;
2026
2027 /* Set the security field to the new SID. */
2028 bsec->sid = newsid;
2029 }
2030
2031 bsec->set = 1;
2032 return 0;
2033}
2034
Eric Paris828dfe12008-04-17 13:17:49 -04002035static int selinux_bprm_check_security(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
2037 return secondary_ops->bprm_check_security(bprm);
2038}
2039
2040
Eric Paris828dfe12008-04-17 13:17:49 -04002041static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
2043 struct task_security_struct *tsec = current->security;
2044 int atsecure = 0;
2045
2046 if (tsec->osid != tsec->sid) {
2047 /* Enable secure mode for SIDs transitions unless
2048 the noatsecure permission is granted between
2049 the two SIDs, i.e. ahp returns 0. */
2050 atsecure = avc_has_perm(tsec->osid, tsec->sid,
2051 SECCLASS_PROCESS,
2052 PROCESS__NOATSECURE, NULL);
2053 }
2054
2055 return (atsecure || secondary_ops->bprm_secureexec(bprm));
2056}
2057
2058static void selinux_bprm_free_security(struct linux_binprm *bprm)
2059{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07002060 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062}
2063
2064extern struct vfsmount *selinuxfs_mount;
2065extern struct dentry *selinux_null;
2066
2067/* Derived from fs/exec.c:flush_old_files. */
Eric Paris828dfe12008-04-17 13:17:49 -04002068static inline void flush_unauthorized_files(struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069{
2070 struct avc_audit_data ad;
2071 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002072 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002073 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002075 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002077 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002078 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 if (tty) {
2080 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08002081 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 if (file) {
2083 /* Revalidate access to controlling tty.
2084 Use inode_has_perm on the tty inode directly rather
2085 than using file_has_perm, as this particular open
2086 file may belong to another process and we are only
2087 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002088 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 if (inode_has_perm(current, inode,
2090 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002091 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 }
2093 }
2094 file_list_unlock();
2095 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002096 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002097 /* Reset controlling tty. */
2098 if (drop_tty)
2099 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
2101 /* Revalidate access to inherited open files. */
2102
Eric Paris828dfe12008-04-17 13:17:49 -04002103 AVC_AUDIT_DATA_INIT(&ad, FS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
2105 spin_lock(&files->file_lock);
2106 for (;;) {
2107 unsigned long set, i;
2108 int fd;
2109
2110 j++;
2111 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002112 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002113 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002115 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 if (!set)
2117 continue;
2118 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002119 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 if (set & 1) {
2121 file = fget(i);
2122 if (!file)
2123 continue;
2124 if (file_has_perm(current,
2125 file,
2126 file_to_av(file))) {
2127 sys_close(i);
2128 fd = get_unused_fd();
2129 if (fd != i) {
2130 if (fd >= 0)
2131 put_unused_fd(fd);
2132 fput(file);
2133 continue;
2134 }
2135 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002136 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 } else {
2138 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002139 if (IS_ERR(devnull)) {
2140 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 put_unused_fd(fd);
2142 fput(file);
2143 continue;
2144 }
2145 }
2146 fd_install(fd, devnull);
2147 }
2148 fput(file);
2149 }
2150 }
2151 spin_lock(&files->file_lock);
2152
2153 }
2154 spin_unlock(&files->file_lock);
2155}
2156
2157static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2158{
2159 struct task_security_struct *tsec;
2160 struct bprm_security_struct *bsec;
2161 u32 sid;
2162 int rc;
2163
2164 secondary_ops->bprm_apply_creds(bprm, unsafe);
2165
2166 tsec = current->security;
2167
2168 bsec = bprm->security;
2169 sid = bsec->sid;
2170
2171 tsec->osid = tsec->sid;
2172 bsec->unsafe = 0;
2173 if (tsec->sid != sid) {
2174 /* Check for shared state. If not ok, leave SID
2175 unchanged and kill. */
2176 if (unsafe & LSM_UNSAFE_SHARE) {
2177 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2178 PROCESS__SHARE, NULL);
2179 if (rc) {
2180 bsec->unsafe = 1;
2181 return;
2182 }
2183 }
2184
2185 /* Check for ptracing, and update the task SID if ok.
2186 Otherwise, leave SID unchanged and kill. */
2187 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Roland McGrath03563572008-03-26 15:46:39 -07002188 struct task_struct *tracer;
2189 struct task_security_struct *sec;
2190 u32 ptsid = 0;
2191
2192 rcu_read_lock();
2193 tracer = task_tracer_task(current);
2194 if (likely(tracer != NULL)) {
2195 sec = tracer->security;
2196 ptsid = sec->sid;
2197 }
2198 rcu_read_unlock();
2199
2200 if (ptsid != 0) {
2201 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
2202 PROCESS__PTRACE, NULL);
2203 if (rc) {
2204 bsec->unsafe = 1;
2205 return;
2206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 }
2208 }
2209 tsec->sid = sid;
2210 }
2211}
2212
2213/*
2214 * called after apply_creds without the task lock held
2215 */
2216static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2217{
2218 struct task_security_struct *tsec;
2219 struct rlimit *rlim, *initrlim;
2220 struct itimerval itimer;
2221 struct bprm_security_struct *bsec;
2222 int rc, i;
2223
2224 tsec = current->security;
2225 bsec = bprm->security;
2226
2227 if (bsec->unsafe) {
2228 force_sig_specific(SIGKILL, current);
2229 return;
2230 }
2231 if (tsec->osid == tsec->sid)
2232 return;
2233
2234 /* Close files for which the new task SID is not authorized. */
2235 flush_unauthorized_files(current->files);
2236
2237 /* Check whether the new SID can inherit signal state
2238 from the old SID. If not, clear itimers to avoid
2239 subsequent signal generation and flush and unblock
2240 signals. This must occur _after_ the task SID has
2241 been updated so that any kill done after the flush
2242 will be checked against the new SID. */
2243 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2244 PROCESS__SIGINH, NULL);
2245 if (rc) {
2246 memset(&itimer, 0, sizeof itimer);
2247 for (i = 0; i < 3; i++)
2248 do_setitimer(i, &itimer, NULL);
2249 flush_signals(current);
2250 spin_lock_irq(&current->sighand->siglock);
2251 flush_signal_handlers(current, 1);
2252 sigemptyset(&current->blocked);
2253 recalc_sigpending();
2254 spin_unlock_irq(&current->sighand->siglock);
2255 }
2256
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002257 /* Always clear parent death signal on SID transitions. */
2258 current->pdeath_signal = 0;
2259
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 /* Check whether the new SID can inherit resource limits
2261 from the old SID. If not, reset all soft limits to
2262 the lower of the current task's hard limit and the init
2263 task's soft limit. Note that the setting of hard limits
2264 (even to lower them) can be controlled by the setrlimit
2265 check. The inclusion of the init task's soft limit into
2266 the computation is to avoid resetting soft limits higher
2267 than the default soft limit for cases where the default
2268 is lower than the hard limit, e.g. RLIMIT_CORE or
2269 RLIMIT_STACK.*/
2270 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2271 PROCESS__RLIMITINH, NULL);
2272 if (rc) {
2273 for (i = 0; i < RLIM_NLIMITS; i++) {
2274 rlim = current->signal->rlim + i;
2275 initrlim = init_task.signal->rlim+i;
Eric Paris828dfe12008-04-17 13:17:49 -04002276 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 }
2278 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2279 /*
2280 * This will cause RLIMIT_CPU calculations
2281 * to be refigured.
2282 */
2283 current->it_prof_expires = jiffies_to_cputime(1);
2284 }
2285 }
2286
2287 /* Wake up the parent if it is waiting so that it can
2288 recheck wait permission to the new task SID. */
2289 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2290}
2291
2292/* superblock security operations */
2293
2294static int selinux_sb_alloc_security(struct super_block *sb)
2295{
2296 return superblock_alloc_security(sb);
2297}
2298
2299static void selinux_sb_free_security(struct super_block *sb)
2300{
2301 superblock_free_security(sb);
2302}
2303
2304static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2305{
2306 if (plen > olen)
2307 return 0;
2308
2309 return !memcmp(prefix, option, plen);
2310}
2311
2312static inline int selinux_option(char *option, int len)
2313{
Eric Paris832cbd92008-04-01 13:24:09 -04002314 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2315 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2316 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2317 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318}
2319
2320static inline void take_option(char **to, char *from, int *first, int len)
2321{
2322 if (!*first) {
2323 **to = ',';
2324 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002325 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 *first = 0;
2327 memcpy(*to, from, len);
2328 *to += len;
2329}
2330
Eric Paris828dfe12008-04-17 13:17:49 -04002331static inline void take_selinux_option(char **to, char *from, int *first,
2332 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002333{
2334 int current_size = 0;
2335
2336 if (!*first) {
2337 **to = '|';
2338 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002339 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002340 *first = 0;
2341
2342 while (current_size < len) {
2343 if (*from != '"') {
2344 **to = *from;
2345 *to += 1;
2346 }
2347 from += 1;
2348 current_size += 1;
2349 }
2350}
2351
Eric Parise0007522008-03-05 10:31:54 -05002352static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353{
2354 int fnosec, fsec, rc = 0;
2355 char *in_save, *in_curr, *in_end;
2356 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002357 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 in_curr = orig;
2360 sec_curr = copy;
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2363 if (!nosec) {
2364 rc = -ENOMEM;
2365 goto out;
2366 }
2367
2368 nosec_save = nosec;
2369 fnosec = fsec = 1;
2370 in_save = in_end = orig;
2371
2372 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002373 if (*in_end == '"')
2374 open_quote = !open_quote;
2375 if ((*in_end == ',' && open_quote == 0) ||
2376 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 int len = in_end - in_curr;
2378
2379 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002380 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 else
2382 take_option(&nosec, in_curr, &fnosec, len);
2383
2384 in_curr = in_end + 1;
2385 }
2386 } while (*in_end++);
2387
Eric Paris6931dfc2005-06-30 02:58:51 -07002388 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002389 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390out:
2391 return rc;
2392}
2393
2394static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2395{
2396 struct avc_audit_data ad;
2397 int rc;
2398
2399 rc = superblock_doinit(sb, data);
2400 if (rc)
2401 return rc;
2402
Eric Paris828dfe12008-04-17 13:17:49 -04002403 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002404 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2406}
2407
David Howells726c3342006-06-23 02:02:58 -07002408static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409{
2410 struct avc_audit_data ad;
2411
Eric Paris828dfe12008-04-17 13:17:49 -04002412 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002413 ad.u.fs.path.dentry = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002414 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415}
2416
Eric Paris828dfe12008-04-17 13:17:49 -04002417static int selinux_mount(char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002418 struct path *path,
Eric Paris828dfe12008-04-17 13:17:49 -04002419 char *type,
2420 unsigned long flags,
2421 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422{
2423 int rc;
2424
Al Virob5266eb2008-03-22 17:48:24 -04002425 rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 if (rc)
2427 return rc;
2428
2429 if (flags & MS_REMOUNT)
Al Virob5266eb2008-03-22 17:48:24 -04002430 return superblock_has_perm(current, path->mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002431 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 else
Al Virob5266eb2008-03-22 17:48:24 -04002433 return dentry_has_perm(current, path->mnt, path->dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002434 FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435}
2436
2437static int selinux_umount(struct vfsmount *mnt, int flags)
2438{
2439 int rc;
2440
2441 rc = secondary_ops->sb_umount(mnt, flags);
2442 if (rc)
2443 return rc;
2444
Eric Paris828dfe12008-04-17 13:17:49 -04002445 return superblock_has_perm(current, mnt->mnt_sb,
2446 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447}
2448
2449/* inode security operations */
2450
2451static int selinux_inode_alloc_security(struct inode *inode)
2452{
2453 return inode_alloc_security(inode);
2454}
2455
2456static void selinux_inode_free_security(struct inode *inode)
2457{
2458 inode_free_security(inode);
2459}
2460
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002461static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2462 char **name, void **value,
2463 size_t *len)
2464{
2465 struct task_security_struct *tsec;
2466 struct inode_security_struct *dsec;
2467 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002468 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002469 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002470 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002471
2472 tsec = current->security;
2473 dsec = dir->i_security;
2474 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002475
2476 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2477 newsid = tsec->create_sid;
2478 } else {
2479 rc = security_transition_sid(tsec->sid, dsec->sid,
2480 inode_mode_to_security_class(inode->i_mode),
2481 &newsid);
2482 if (rc) {
2483 printk(KERN_WARNING "%s: "
2484 "security_transition_sid failed, rc=%d (dev=%s "
2485 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002486 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002487 -rc, inode->i_sb->s_id, inode->i_ino);
2488 return rc;
2489 }
2490 }
2491
Eric Paris296fddf2006-09-25 23:32:00 -07002492 /* Possibly defer initialization to selinux_complete_init. */
2493 if (sbsec->initialized) {
2494 struct inode_security_struct *isec = inode->i_security;
2495 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2496 isec->sid = newsid;
2497 isec->initialized = 1;
2498 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002499
Stephen Smalley8aad3872006-03-22 00:09:13 -08002500 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002501 return -EOPNOTSUPP;
2502
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002503 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002504 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002505 if (!namep)
2506 return -ENOMEM;
2507 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002508 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002509
2510 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002511 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002512 if (rc) {
2513 kfree(namep);
2514 return rc;
2515 }
2516 *value = context;
2517 *len = clen;
2518 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002519
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002520 return 0;
2521}
2522
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2524{
2525 return may_create(dir, dentry, SECCLASS_FILE);
2526}
2527
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2529{
2530 int rc;
2531
Eric Paris828dfe12008-04-17 13:17:49 -04002532 rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 if (rc)
2534 return rc;
2535 return may_link(dir, old_dentry, MAY_LINK);
2536}
2537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2539{
2540 int rc;
2541
2542 rc = secondary_ops->inode_unlink(dir, dentry);
2543 if (rc)
2544 return rc;
2545 return may_link(dir, dentry, MAY_UNLINK);
2546}
2547
2548static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2549{
2550 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2551}
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2554{
2555 return may_create(dir, dentry, SECCLASS_DIR);
2556}
2557
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2559{
2560 return may_link(dir, dentry, MAY_RMDIR);
2561}
2562
2563static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2564{
2565 int rc;
2566
2567 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2568 if (rc)
2569 return rc;
2570
2571 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2572}
2573
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002575 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576{
2577 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2578}
2579
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580static int selinux_inode_readlink(struct dentry *dentry)
2581{
2582 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2583}
2584
2585static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2586{
2587 int rc;
2588
Eric Paris828dfe12008-04-17 13:17:49 -04002589 rc = secondary_ops->inode_follow_link(dentry, nameidata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 if (rc)
2591 return rc;
2592 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2593}
2594
2595static int selinux_inode_permission(struct inode *inode, int mask,
2596 struct nameidata *nd)
2597{
2598 int rc;
2599
2600 rc = secondary_ops->inode_permission(inode, mask, nd);
2601 if (rc)
2602 return rc;
2603
2604 if (!mask) {
2605 /* No permission to check. Existence test. */
2606 return 0;
2607 }
2608
2609 return inode_has_perm(current, inode,
Eric Parisb0c636b2008-02-28 12:58:40 -05002610 open_file_mask_to_av(inode->i_mode, mask), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611}
2612
2613static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2614{
2615 int rc;
2616
2617 rc = secondary_ops->inode_setattr(dentry, iattr);
2618 if (rc)
2619 return rc;
2620
2621 if (iattr->ia_valid & ATTR_FORCE)
2622 return 0;
2623
2624 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2625 ATTR_ATIME_SET | ATTR_MTIME_SET))
2626 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2627
2628 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2629}
2630
2631static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2632{
2633 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2634}
2635
David Howells8f0cfa52008-04-29 00:59:41 -07002636static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002637{
2638 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2639 sizeof XATTR_SECURITY_PREFIX - 1)) {
2640 if (!strcmp(name, XATTR_NAME_CAPS)) {
2641 if (!capable(CAP_SETFCAP))
2642 return -EPERM;
2643 } else if (!capable(CAP_SYS_ADMIN)) {
2644 /* A different attribute in the security namespace.
2645 Restrict to administrator. */
2646 return -EPERM;
2647 }
2648 }
2649
2650 /* Not an attribute we recognize, so just check the
2651 ordinary setattr permission. */
2652 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2653}
2654
David Howells8f0cfa52008-04-29 00:59:41 -07002655static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2656 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657{
2658 struct task_security_struct *tsec = current->security;
2659 struct inode *inode = dentry->d_inode;
2660 struct inode_security_struct *isec = inode->i_security;
2661 struct superblock_security_struct *sbsec;
2662 struct avc_audit_data ad;
2663 u32 newsid;
2664 int rc = 0;
2665
Serge E. Hallynb5376772007-10-16 23:31:36 -07002666 if (strcmp(name, XATTR_NAME_SELINUX))
2667 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
2669 sbsec = inode->i_sb->s_security;
2670 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2671 return -EOPNOTSUPP;
2672
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302673 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 return -EPERM;
2675
Eric Paris828dfe12008-04-17 13:17:49 -04002676 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002677 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678
2679 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2680 FILE__RELABELFROM, &ad);
2681 if (rc)
2682 return rc;
2683
2684 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002685 if (rc == -EINVAL) {
2686 if (!capable(CAP_MAC_ADMIN))
2687 return rc;
2688 rc = security_context_to_sid_force(value, size, &newsid);
2689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 if (rc)
2691 return rc;
2692
2693 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2694 FILE__RELABELTO, &ad);
2695 if (rc)
2696 return rc;
2697
2698 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002699 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 if (rc)
2701 return rc;
2702
2703 return avc_has_perm(newsid,
2704 sbsec->sid,
2705 SECCLASS_FILESYSTEM,
2706 FILESYSTEM__ASSOCIATE,
2707 &ad);
2708}
2709
David Howells8f0cfa52008-04-29 00:59:41 -07002710static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002711 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002712 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713{
2714 struct inode *inode = dentry->d_inode;
2715 struct inode_security_struct *isec = inode->i_security;
2716 u32 newsid;
2717 int rc;
2718
2719 if (strcmp(name, XATTR_NAME_SELINUX)) {
2720 /* Not an attribute we recognize, so nothing to do. */
2721 return;
2722 }
2723
Stephen Smalley12b29f32008-05-07 13:03:20 -04002724 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002726 printk(KERN_ERR "SELinux: unable to map context to SID"
2727 "for (%s, %lu), rc=%d\n",
2728 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 return;
2730 }
2731
2732 isec->sid = newsid;
2733 return;
2734}
2735
David Howells8f0cfa52008-04-29 00:59:41 -07002736static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2739}
2740
Eric Paris828dfe12008-04-17 13:17:49 -04002741static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742{
2743 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2744}
2745
David Howells8f0cfa52008-04-29 00:59:41 -07002746static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002748 if (strcmp(name, XATTR_NAME_SELINUX))
2749 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
2751 /* No one is allowed to remove a SELinux security label.
2752 You can change the label, but all data must be labeled. */
2753 return -EACCES;
2754}
2755
James Morrisd381d8a2005-10-30 14:59:22 -08002756/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002757 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002758 *
2759 * Permission check is handled by selinux_inode_getxattr hook.
2760 */
David P. Quigley42492592008-02-04 22:29:39 -08002761static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762{
David P. Quigley42492592008-02-04 22:29:39 -08002763 u32 size;
2764 int error;
2765 char *context = NULL;
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002766 struct task_security_struct *tsec = current->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002769 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2770 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002772 /*
2773 * If the caller has CAP_MAC_ADMIN, then get the raw context
2774 * value even if it is not defined by current policy; otherwise,
2775 * use the in-core value under current policy.
2776 * Use the non-auditing forms of the permission checks since
2777 * getxattr may be called by unprivileged processes commonly
2778 * and lack of permission just means that we fall back to the
2779 * in-core context value, not a denial.
2780 */
2781 error = secondary_ops->capable(current, CAP_MAC_ADMIN);
2782 if (!error)
2783 error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
2784 SECCLASS_CAPABILITY2,
2785 CAPABILITY2__MAC_ADMIN,
2786 0,
2787 NULL);
2788 if (!error)
2789 error = security_sid_to_context_force(isec->sid, &context,
2790 &size);
2791 else
2792 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002793 if (error)
2794 return error;
2795 error = size;
2796 if (alloc) {
2797 *buffer = context;
2798 goto out_nofree;
2799 }
2800 kfree(context);
2801out_nofree:
2802 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803}
2804
2805static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002806 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
2808 struct inode_security_struct *isec = inode->i_security;
2809 u32 newsid;
2810 int rc;
2811
2812 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2813 return -EOPNOTSUPP;
2814
2815 if (!value || !size)
2816 return -EACCES;
2817
Eric Paris828dfe12008-04-17 13:17:49 -04002818 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 if (rc)
2820 return rc;
2821
2822 isec->sid = newsid;
2823 return 0;
2824}
2825
2826static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2827{
2828 const int len = sizeof(XATTR_NAME_SELINUX);
2829 if (buffer && len <= buffer_size)
2830 memcpy(buffer, XATTR_NAME_SELINUX, len);
2831 return len;
2832}
2833
Serge E. Hallynb5376772007-10-16 23:31:36 -07002834static int selinux_inode_need_killpriv(struct dentry *dentry)
2835{
2836 return secondary_ops->inode_need_killpriv(dentry);
2837}
2838
2839static int selinux_inode_killpriv(struct dentry *dentry)
2840{
2841 return secondary_ops->inode_killpriv(dentry);
2842}
2843
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02002844static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2845{
2846 struct inode_security_struct *isec = inode->i_security;
2847 *secid = isec->sid;
2848}
2849
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850/* file security operations */
2851
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002852static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002854 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002855 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
2857 if (!mask) {
2858 /* No permission to check. Existence test. */
2859 return 0;
2860 }
2861
2862 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2863 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2864 mask |= MAY_APPEND;
2865
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002866 rc = file_has_perm(current, file,
2867 file_mask_to_av(inode->i_mode, mask));
2868 if (rc)
2869 return rc;
2870
2871 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002874static int selinux_file_permission(struct file *file, int mask)
2875{
2876 struct inode *inode = file->f_path.dentry->d_inode;
2877 struct task_security_struct *tsec = current->security;
2878 struct file_security_struct *fsec = file->f_security;
2879 struct inode_security_struct *isec = inode->i_security;
2880
2881 if (!mask) {
2882 /* No permission to check. Existence test. */
2883 return 0;
2884 }
2885
2886 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2887 && fsec->pseqno == avc_policy_seqno())
2888 return selinux_netlbl_inode_permission(inode, mask);
2889
2890 return selinux_revalidate_file_permission(file, mask);
2891}
2892
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893static int selinux_file_alloc_security(struct file *file)
2894{
2895 return file_alloc_security(file);
2896}
2897
2898static void selinux_file_free_security(struct file *file)
2899{
2900 file_free_security(file);
2901}
2902
2903static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2904 unsigned long arg)
2905{
2906 int error = 0;
2907
2908 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04002909 case FIONREAD:
2910 /* fall through */
2911 case FIBMAP:
2912 /* fall through */
2913 case FIGETBSZ:
2914 /* fall through */
2915 case EXT2_IOC_GETFLAGS:
2916 /* fall through */
2917 case EXT2_IOC_GETVERSION:
2918 error = file_has_perm(current, file, FILE__GETATTR);
2919 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920
Eric Paris828dfe12008-04-17 13:17:49 -04002921 case EXT2_IOC_SETFLAGS:
2922 /* fall through */
2923 case EXT2_IOC_SETVERSION:
2924 error = file_has_perm(current, file, FILE__SETATTR);
2925 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
Eric Paris828dfe12008-04-17 13:17:49 -04002927 /* sys_ioctl() checks */
2928 case FIONBIO:
2929 /* fall through */
2930 case FIOASYNC:
2931 error = file_has_perm(current, file, 0);
2932 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933
Eric Paris828dfe12008-04-17 13:17:49 -04002934 case KDSKBENT:
2935 case KDSKBSENT:
2936 error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
2937 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
Eric Paris828dfe12008-04-17 13:17:49 -04002939 /* default case assumes that the command will go
2940 * to the file's ioctl() function.
2941 */
2942 default:
2943 error = file_has_perm(current, file, FILE__IOCTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 }
2945 return error;
2946}
2947
2948static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2949{
2950#ifndef CONFIG_PPC32
2951 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2952 /*
2953 * We are making executable an anonymous mapping or a
2954 * private file mapping that will also be writable.
2955 * This has an additional check.
2956 */
2957 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2958 if (rc)
2959 return rc;
2960 }
2961#endif
2962
2963 if (file) {
2964 /* read access is always possible with a mapping */
2965 u32 av = FILE__READ;
2966
2967 /* write access only matters if the mapping is shared */
2968 if (shared && (prot & PROT_WRITE))
2969 av |= FILE__WRITE;
2970
2971 if (prot & PROT_EXEC)
2972 av |= FILE__EXECUTE;
2973
2974 return file_has_perm(current, file, av);
2975 }
2976 return 0;
2977}
2978
2979static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002980 unsigned long prot, unsigned long flags,
2981 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982{
Eric Parised032182007-06-28 15:55:21 -04002983 int rc = 0;
Eric Paris828dfe12008-04-17 13:17:49 -04002984 u32 sid = ((struct task_security_struct *)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
Eric Parised032182007-06-28 15:55:21 -04002986 if (addr < mmap_min_addr)
2987 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2988 MEMPROTECT__MMAP_ZERO, NULL);
2989 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 return rc;
2991
2992 if (selinux_checkreqprot)
2993 prot = reqprot;
2994
2995 return file_map_prot_check(file, prot,
2996 (flags & MAP_TYPE) == MAP_SHARED);
2997}
2998
2999static int selinux_file_mprotect(struct vm_area_struct *vma,
3000 unsigned long reqprot,
3001 unsigned long prot)
3002{
3003 int rc;
3004
3005 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
3006 if (rc)
3007 return rc;
3008
3009 if (selinux_checkreqprot)
3010 prot = reqprot;
3011
3012#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003013 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
3014 rc = 0;
3015 if (vma->vm_start >= vma->vm_mm->start_brk &&
3016 vma->vm_end <= vma->vm_mm->brk) {
3017 rc = task_has_perm(current, current,
3018 PROCESS__EXECHEAP);
3019 } else if (!vma->vm_file &&
3020 vma->vm_start <= vma->vm_mm->start_stack &&
3021 vma->vm_end >= vma->vm_mm->start_stack) {
3022 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
3023 } else if (vma->vm_file && vma->anon_vma) {
3024 /*
3025 * We are making executable a file mapping that has
3026 * had some COW done. Since pages might have been
3027 * written, check ability to execute the possibly
3028 * modified content. This typically should only
3029 * occur for text relocations.
3030 */
3031 rc = file_has_perm(current, vma->vm_file,
3032 FILE__EXECMOD);
3033 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003034 if (rc)
3035 return rc;
3036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037#endif
3038
3039 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3040}
3041
3042static int selinux_file_lock(struct file *file, unsigned int cmd)
3043{
3044 return file_has_perm(current, file, FILE__LOCK);
3045}
3046
3047static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3048 unsigned long arg)
3049{
3050 int err = 0;
3051
3052 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003053 case F_SETFL:
3054 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3055 err = -EINVAL;
3056 break;
3057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058
Eric Paris828dfe12008-04-17 13:17:49 -04003059 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
3060 err = file_has_perm(current, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003062 }
3063 /* fall through */
3064 case F_SETOWN:
3065 case F_SETSIG:
3066 case F_GETFL:
3067 case F_GETOWN:
3068 case F_GETSIG:
3069 /* Just check FD__USE permission */
3070 err = file_has_perm(current, file, 0);
3071 break;
3072 case F_GETLK:
3073 case F_SETLK:
3074 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003076 case F_GETLK64:
3077 case F_SETLK64:
3078 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003080 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3081 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003083 }
3084 err = file_has_perm(current, file, FILE__LOCK);
3085 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086 }
3087
3088 return err;
3089}
3090
3091static int selinux_file_set_fowner(struct file *file)
3092{
3093 struct task_security_struct *tsec;
3094 struct file_security_struct *fsec;
3095
3096 tsec = current->security;
3097 fsec = file->f_security;
3098 fsec->fown_sid = tsec->sid;
3099
3100 return 0;
3101}
3102
3103static int selinux_file_send_sigiotask(struct task_struct *tsk,
3104 struct fown_struct *fown, int signum)
3105{
Eric Paris828dfe12008-04-17 13:17:49 -04003106 struct file *file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 u32 perm;
3108 struct task_security_struct *tsec;
3109 struct file_security_struct *fsec;
3110
3111 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003112 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113
3114 tsec = tsk->security;
3115 fsec = file->f_security;
3116
3117 if (!signum)
3118 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3119 else
3120 perm = signal_to_av(signum);
3121
3122 return avc_has_perm(fsec->fown_sid, tsec->sid,
3123 SECCLASS_PROCESS, perm, NULL);
3124}
3125
3126static int selinux_file_receive(struct file *file)
3127{
3128 return file_has_perm(current, file, file_to_av(file));
3129}
3130
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003131static int selinux_dentry_open(struct file *file)
3132{
3133 struct file_security_struct *fsec;
3134 struct inode *inode;
3135 struct inode_security_struct *isec;
3136 inode = file->f_path.dentry->d_inode;
3137 fsec = file->f_security;
3138 isec = inode->i_security;
3139 /*
3140 * Save inode label and policy sequence number
3141 * at open-time so that selinux_file_permission
3142 * can determine whether revalidation is necessary.
3143 * Task label is already saved in the file security
3144 * struct as its SID.
3145 */
3146 fsec->isid = isec->sid;
3147 fsec->pseqno = avc_policy_seqno();
3148 /*
3149 * Since the inode label or policy seqno may have changed
3150 * between the selinux_inode_permission check and the saving
3151 * of state above, recheck that access is still permitted.
3152 * Otherwise, access might never be revalidated against the
3153 * new inode label or new policy.
3154 * This check is not redundant - do not remove.
3155 */
3156 return inode_has_perm(current, inode, file_to_av(file), NULL);
3157}
3158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159/* task security operations */
3160
3161static int selinux_task_create(unsigned long clone_flags)
3162{
3163 int rc;
3164
3165 rc = secondary_ops->task_create(clone_flags);
3166 if (rc)
3167 return rc;
3168
3169 return task_has_perm(current, current, PROCESS__FORK);
3170}
3171
3172static int selinux_task_alloc_security(struct task_struct *tsk)
3173{
3174 struct task_security_struct *tsec1, *tsec2;
3175 int rc;
3176
3177 tsec1 = current->security;
3178
3179 rc = task_alloc_security(tsk);
3180 if (rc)
3181 return rc;
3182 tsec2 = tsk->security;
3183
3184 tsec2->osid = tsec1->osid;
3185 tsec2->sid = tsec1->sid;
3186
Michael LeMay28eba5b2006-06-27 02:53:42 -07003187 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 tsec2->exec_sid = tsec1->exec_sid;
3189 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003190 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003191 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 return 0;
3194}
3195
3196static void selinux_task_free_security(struct task_struct *tsk)
3197{
3198 task_free_security(tsk);
3199}
3200
3201static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3202{
3203 /* Since setuid only affects the current process, and
3204 since the SELinux controls are not based on the Linux
3205 identity attributes, SELinux does not need to control
3206 this operation. However, SELinux does control the use
3207 of the CAP_SETUID and CAP_SETGID capabilities using the
3208 capable hook. */
3209 return 0;
3210}
3211
3212static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3213{
Eric Paris828dfe12008-04-17 13:17:49 -04003214 return secondary_ops->task_post_setuid(id0, id1, id2, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215}
3216
3217static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3218{
3219 /* See the comment for setuid above. */
3220 return 0;
3221}
3222
3223static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3224{
3225 return task_has_perm(current, p, PROCESS__SETPGID);
3226}
3227
3228static int selinux_task_getpgid(struct task_struct *p)
3229{
3230 return task_has_perm(current, p, PROCESS__GETPGID);
3231}
3232
3233static int selinux_task_getsid(struct task_struct *p)
3234{
3235 return task_has_perm(current, p, PROCESS__GETSESSION);
3236}
3237
David Quigleyf9008e42006-06-30 01:55:46 -07003238static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3239{
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003240 struct task_security_struct *tsec = p->security;
3241 *secid = tsec->sid;
David Quigleyf9008e42006-06-30 01:55:46 -07003242}
3243
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244static int selinux_task_setgroups(struct group_info *group_info)
3245{
3246 /* See the comment for setuid above. */
3247 return 0;
3248}
3249
3250static int selinux_task_setnice(struct task_struct *p, int nice)
3251{
3252 int rc;
3253
3254 rc = secondary_ops->task_setnice(p, nice);
3255 if (rc)
3256 return rc;
3257
Eric Paris828dfe12008-04-17 13:17:49 -04003258 return task_has_perm(current, p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259}
3260
James Morris03e68062006-06-23 02:03:58 -07003261static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3262{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003263 int rc;
3264
3265 rc = secondary_ops->task_setioprio(p, ioprio);
3266 if (rc)
3267 return rc;
3268
James Morris03e68062006-06-23 02:03:58 -07003269 return task_has_perm(current, p, PROCESS__SETSCHED);
3270}
3271
David Quigleya1836a42006-06-30 01:55:49 -07003272static int selinux_task_getioprio(struct task_struct *p)
3273{
3274 return task_has_perm(current, p, PROCESS__GETSCHED);
3275}
3276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3278{
3279 struct rlimit *old_rlim = current->signal->rlim + resource;
3280 int rc;
3281
3282 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3283 if (rc)
3284 return rc;
3285
3286 /* Control the ability to change the hard limit (whether
3287 lowering or raising it), so that the hard limit can
3288 later be used as a safe reset point for the soft limit
3289 upon context transitions. See selinux_bprm_apply_creds. */
3290 if (old_rlim->rlim_max != new_rlim->rlim_max)
3291 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3292
3293 return 0;
3294}
3295
3296static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3297{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003298 int rc;
3299
3300 rc = secondary_ops->task_setscheduler(p, policy, lp);
3301 if (rc)
3302 return rc;
3303
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 return task_has_perm(current, p, PROCESS__SETSCHED);
3305}
3306
3307static int selinux_task_getscheduler(struct task_struct *p)
3308{
3309 return task_has_perm(current, p, PROCESS__GETSCHED);
3310}
3311
David Quigley35601542006-06-23 02:04:01 -07003312static int selinux_task_movememory(struct task_struct *p)
3313{
3314 return task_has_perm(current, p, PROCESS__SETSCHED);
3315}
3316
David Quigleyf9008e42006-06-30 01:55:46 -07003317static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3318 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319{
3320 u32 perm;
3321 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003322 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
David Quigleyf9008e42006-06-30 01:55:46 -07003324 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325 if (rc)
3326 return rc;
3327
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328 if (!sig)
3329 perm = PROCESS__SIGNULL; /* null signal; existence test */
3330 else
3331 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003332 tsec = p->security;
3333 if (secid)
3334 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3335 else
3336 rc = task_has_perm(current, p, perm);
3337 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338}
3339
3340static int selinux_task_prctl(int option,
3341 unsigned long arg2,
3342 unsigned long arg3,
3343 unsigned long arg4,
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003344 unsigned long arg5,
3345 long *rc_p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346{
3347 /* The current prctl operations do not appear to require
3348 any SELinux controls since they merely observe or modify
3349 the state of the current process. */
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003350 return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351}
3352
3353static int selinux_task_wait(struct task_struct *p)
3354{
Eric Paris8a535142007-10-22 16:10:31 -04003355 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356}
3357
3358static void selinux_task_reparent_to_init(struct task_struct *p)
3359{
Eric Paris828dfe12008-04-17 13:17:49 -04003360 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
3362 secondary_ops->task_reparent_to_init(p);
3363
3364 tsec = p->security;
3365 tsec->osid = tsec->sid;
3366 tsec->sid = SECINITSID_KERNEL;
3367 return;
3368}
3369
3370static void selinux_task_to_inode(struct task_struct *p,
3371 struct inode *inode)
3372{
3373 struct task_security_struct *tsec = p->security;
3374 struct inode_security_struct *isec = inode->i_security;
3375
3376 isec->sid = tsec->sid;
3377 isec->initialized = 1;
3378 return;
3379}
3380
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003382static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3383 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384{
3385 int offset, ihlen, ret = -EINVAL;
3386 struct iphdr _iph, *ih;
3387
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003388 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3390 if (ih == NULL)
3391 goto out;
3392
3393 ihlen = ih->ihl * 4;
3394 if (ihlen < sizeof(_iph))
3395 goto out;
3396
3397 ad->u.net.v4info.saddr = ih->saddr;
3398 ad->u.net.v4info.daddr = ih->daddr;
3399 ret = 0;
3400
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003401 if (proto)
3402 *proto = ih->protocol;
3403
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003405 case IPPROTO_TCP: {
3406 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
Eric Paris828dfe12008-04-17 13:17:49 -04003408 if (ntohs(ih->frag_off) & IP_OFFSET)
3409 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
3411 offset += ihlen;
3412 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3413 if (th == NULL)
3414 break;
3415
3416 ad->u.net.sport = th->source;
3417 ad->u.net.dport = th->dest;
3418 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420
Eric Paris828dfe12008-04-17 13:17:49 -04003421 case IPPROTO_UDP: {
3422 struct udphdr _udph, *uh;
3423
3424 if (ntohs(ih->frag_off) & IP_OFFSET)
3425 break;
3426
3427 offset += ihlen;
3428 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3429 if (uh == NULL)
3430 break;
3431
3432 ad->u.net.sport = uh->source;
3433 ad->u.net.dport = uh->dest;
3434 break;
3435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436
James Morris2ee92d42006-11-13 16:09:01 -08003437 case IPPROTO_DCCP: {
3438 struct dccp_hdr _dccph, *dh;
3439
3440 if (ntohs(ih->frag_off) & IP_OFFSET)
3441 break;
3442
3443 offset += ihlen;
3444 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3445 if (dh == NULL)
3446 break;
3447
3448 ad->u.net.sport = dh->dccph_sport;
3449 ad->u.net.dport = dh->dccph_dport;
3450 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003451 }
James Morris2ee92d42006-11-13 16:09:01 -08003452
Eric Paris828dfe12008-04-17 13:17:49 -04003453 default:
3454 break;
3455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456out:
3457 return ret;
3458}
3459
3460#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3461
3462/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003463static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3464 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
3466 u8 nexthdr;
3467 int ret = -EINVAL, offset;
3468 struct ipv6hdr _ipv6h, *ip6;
3469
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003470 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3472 if (ip6 == NULL)
3473 goto out;
3474
3475 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3476 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3477 ret = 0;
3478
3479 nexthdr = ip6->nexthdr;
3480 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003481 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 if (offset < 0)
3483 goto out;
3484
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003485 if (proto)
3486 *proto = nexthdr;
3487
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 switch (nexthdr) {
3489 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003490 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
3492 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3493 if (th == NULL)
3494 break;
3495
3496 ad->u.net.sport = th->source;
3497 ad->u.net.dport = th->dest;
3498 break;
3499 }
3500
3501 case IPPROTO_UDP: {
3502 struct udphdr _udph, *uh;
3503
3504 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3505 if (uh == NULL)
3506 break;
3507
3508 ad->u.net.sport = uh->source;
3509 ad->u.net.dport = uh->dest;
3510 break;
3511 }
3512
James Morris2ee92d42006-11-13 16:09:01 -08003513 case IPPROTO_DCCP: {
3514 struct dccp_hdr _dccph, *dh;
3515
3516 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3517 if (dh == NULL)
3518 break;
3519
3520 ad->u.net.sport = dh->dccph_sport;
3521 ad->u.net.dport = dh->dccph_dport;
3522 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003523 }
James Morris2ee92d42006-11-13 16:09:01 -08003524
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525 /* includes fragments */
3526 default:
3527 break;
3528 }
3529out:
3530 return ret;
3531}
3532
3533#endif /* IPV6 */
3534
3535static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003536 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537{
3538 int ret = 0;
3539
3540 switch (ad->u.net.family) {
3541 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003542 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 if (ret || !addrp)
3544 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3546 &ad->u.net.v4info.daddr);
3547 break;
3548
3549#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3550 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003551 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 if (ret || !addrp)
3553 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3555 &ad->u.net.v6info.daddr);
3556 break;
3557#endif /* IPV6 */
3558 default:
3559 break;
3560 }
3561
Paul Moore71f1cb02008-01-29 08:51:16 -05003562 if (unlikely(ret))
3563 printk(KERN_WARNING
3564 "SELinux: failure in selinux_parse_skb(),"
3565 " unable to parse packet\n");
3566
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 return ret;
3568}
3569
Paul Moore4f6a9932007-03-01 14:35:22 -05003570/**
Paul Moore220deb92008-01-29 08:38:23 -05003571 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003572 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003573 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003574 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003575 *
3576 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003577 * Check the various different forms of network peer labeling and determine
3578 * the peer label/SID for the packet; most of the magic actually occurs in
3579 * the security server function security_net_peersid_cmp(). The function
3580 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3581 * or -EACCES if @sid is invalid due to inconsistencies with the different
3582 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003583 *
3584 */
Paul Moore220deb92008-01-29 08:38:23 -05003585static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003586{
Paul Moore71f1cb02008-01-29 08:51:16 -05003587 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003588 u32 xfrm_sid;
3589 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003590 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003591
3592 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003593 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003594
Paul Moore71f1cb02008-01-29 08:51:16 -05003595 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3596 if (unlikely(err)) {
3597 printk(KERN_WARNING
3598 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3599 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003600 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003601 }
Paul Moore220deb92008-01-29 08:38:23 -05003602
3603 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003604}
3605
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606/* socket security operations */
3607static int socket_has_perm(struct task_struct *task, struct socket *sock,
3608 u32 perms)
3609{
3610 struct inode_security_struct *isec;
3611 struct task_security_struct *tsec;
3612 struct avc_audit_data ad;
3613 int err = 0;
3614
3615 tsec = task->security;
3616 isec = SOCK_INODE(sock)->i_security;
3617
3618 if (isec->sid == SECINITSID_KERNEL)
3619 goto out;
3620
Eric Paris828dfe12008-04-17 13:17:49 -04003621 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 ad.u.net.sk = sock->sk;
3623 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3624
3625out:
3626 return err;
3627}
3628
3629static int selinux_socket_create(int family, int type,
3630 int protocol, int kern)
3631{
3632 int err = 0;
3633 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003634 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
3636 if (kern)
3637 goto out;
3638
3639 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003640 newsid = tsec->sockcreate_sid ? : tsec->sid;
3641 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 socket_type_to_security_class(family, type,
3643 protocol), SOCKET__CREATE, NULL);
3644
3645out:
3646 return err;
3647}
3648
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003649static int selinux_socket_post_create(struct socket *sock, int family,
3650 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003652 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 struct inode_security_struct *isec;
3654 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003655 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003656 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
3658 isec = SOCK_INODE(sock)->i_security;
3659
3660 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003661 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003663 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 isec->initialized = 1;
3665
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003666 if (sock->sk) {
3667 sksec = sock->sk->sk_security;
3668 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003669 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003670 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003671 }
3672
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003673 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674}
3675
3676/* Range of port numbers used to automatically bind.
3677 Need to determine whether we should perform a name_bind
3678 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
3680static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3681{
3682 u16 family;
3683 int err;
3684
3685 err = socket_has_perm(current, sock, SOCKET__BIND);
3686 if (err)
3687 goto out;
3688
3689 /*
3690 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003691 * Multiple address binding for SCTP is not supported yet: we just
3692 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 */
3694 family = sock->sk->sk_family;
3695 if (family == PF_INET || family == PF_INET6) {
3696 char *addrp;
3697 struct inode_security_struct *isec;
3698 struct task_security_struct *tsec;
3699 struct avc_audit_data ad;
3700 struct sockaddr_in *addr4 = NULL;
3701 struct sockaddr_in6 *addr6 = NULL;
3702 unsigned short snum;
3703 struct sock *sk = sock->sk;
3704 u32 sid, node_perm, addrlen;
3705
3706 tsec = current->security;
3707 isec = SOCK_INODE(sock)->i_security;
3708
3709 if (family == PF_INET) {
3710 addr4 = (struct sockaddr_in *)address;
3711 snum = ntohs(addr4->sin_port);
3712 addrlen = sizeof(addr4->sin_addr.s_addr);
3713 addrp = (char *)&addr4->sin_addr.s_addr;
3714 } else {
3715 addr6 = (struct sockaddr_in6 *)address;
3716 snum = ntohs(addr6->sin6_port);
3717 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3718 addrp = (char *)&addr6->sin6_addr.s6_addr;
3719 }
3720
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003721 if (snum) {
3722 int low, high;
3723
3724 inet_get_local_port_range(&low, &high);
3725
3726 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003727 err = sel_netport_sid(sk->sk_protocol,
3728 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003729 if (err)
3730 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003731 AVC_AUDIT_DATA_INIT(&ad, NET);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003732 ad.u.net.sport = htons(snum);
3733 ad.u.net.family = family;
3734 err = avc_has_perm(isec->sid, sid,
3735 isec->sclass,
3736 SOCKET__NAME_BIND, &ad);
3737 if (err)
3738 goto out;
3739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 }
Eric Paris828dfe12008-04-17 13:17:49 -04003741
3742 switch (isec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003743 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 node_perm = TCP_SOCKET__NODE_BIND;
3745 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003746
James Morris13402582005-09-30 14:24:34 -04003747 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 node_perm = UDP_SOCKET__NODE_BIND;
3749 break;
James Morris2ee92d42006-11-13 16:09:01 -08003750
3751 case SECCLASS_DCCP_SOCKET:
3752 node_perm = DCCP_SOCKET__NODE_BIND;
3753 break;
3754
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 default:
3756 node_perm = RAWIP_SOCKET__NODE_BIND;
3757 break;
3758 }
Eric Paris828dfe12008-04-17 13:17:49 -04003759
Paul Moore224dfbd2008-01-29 08:38:13 -05003760 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 if (err)
3762 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003763
3764 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 ad.u.net.sport = htons(snum);
3766 ad.u.net.family = family;
3767
3768 if (family == PF_INET)
3769 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3770 else
3771 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3772
3773 err = avc_has_perm(isec->sid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003774 isec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 if (err)
3776 goto out;
3777 }
3778out:
3779 return err;
3780}
3781
3782static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3783{
3784 struct inode_security_struct *isec;
3785 int err;
3786
3787 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3788 if (err)
3789 return err;
3790
3791 /*
James Morris2ee92d42006-11-13 16:09:01 -08003792 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 */
3794 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003795 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3796 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 struct sock *sk = sock->sk;
3798 struct avc_audit_data ad;
3799 struct sockaddr_in *addr4 = NULL;
3800 struct sockaddr_in6 *addr6 = NULL;
3801 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003802 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
3804 if (sk->sk_family == PF_INET) {
3805 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003806 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 return -EINVAL;
3808 snum = ntohs(addr4->sin_port);
3809 } else {
3810 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003811 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 return -EINVAL;
3813 snum = ntohs(addr6->sin6_port);
3814 }
3815
Paul Moore3e112172008-04-10 10:48:14 -04003816 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 if (err)
3818 goto out;
3819
James Morris2ee92d42006-11-13 16:09:01 -08003820 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3821 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3822
Eric Paris828dfe12008-04-17 13:17:49 -04003823 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 ad.u.net.dport = htons(snum);
3825 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003826 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 if (err)
3828 goto out;
3829 }
3830
3831out:
3832 return err;
3833}
3834
3835static int selinux_socket_listen(struct socket *sock, int backlog)
3836{
3837 return socket_has_perm(current, sock, SOCKET__LISTEN);
3838}
3839
3840static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3841{
3842 int err;
3843 struct inode_security_struct *isec;
3844 struct inode_security_struct *newisec;
3845
3846 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3847 if (err)
3848 return err;
3849
3850 newisec = SOCK_INODE(newsock)->i_security;
3851
3852 isec = SOCK_INODE(sock)->i_security;
3853 newisec->sclass = isec->sclass;
3854 newisec->sid = isec->sid;
3855 newisec->initialized = 1;
3856
3857 return 0;
3858}
3859
3860static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04003861 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003863 int rc;
3864
3865 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3866 if (rc)
3867 return rc;
3868
3869 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870}
3871
3872static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3873 int size, int flags)
3874{
3875 return socket_has_perm(current, sock, SOCKET__READ);
3876}
3877
3878static int selinux_socket_getsockname(struct socket *sock)
3879{
3880 return socket_has_perm(current, sock, SOCKET__GETATTR);
3881}
3882
3883static int selinux_socket_getpeername(struct socket *sock)
3884{
3885 return socket_has_perm(current, sock, SOCKET__GETATTR);
3886}
3887
Eric Paris828dfe12008-04-17 13:17:49 -04003888static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889{
Paul Mooref8687af2006-10-30 15:22:15 -08003890 int err;
3891
3892 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3893 if (err)
3894 return err;
3895
3896 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897}
3898
3899static int selinux_socket_getsockopt(struct socket *sock, int level,
3900 int optname)
3901{
3902 return socket_has_perm(current, sock, SOCKET__GETOPT);
3903}
3904
3905static int selinux_socket_shutdown(struct socket *sock, int how)
3906{
3907 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3908}
3909
3910static int selinux_socket_unix_stream_connect(struct socket *sock,
3911 struct socket *other,
3912 struct sock *newsk)
3913{
3914 struct sk_security_struct *ssec;
3915 struct inode_security_struct *isec;
3916 struct inode_security_struct *other_isec;
3917 struct avc_audit_data ad;
3918 int err;
3919
3920 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3921 if (err)
3922 return err;
3923
3924 isec = SOCK_INODE(sock)->i_security;
3925 other_isec = SOCK_INODE(other)->i_security;
3926
Eric Paris828dfe12008-04-17 13:17:49 -04003927 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 ad.u.net.sk = other->sk;
3929
3930 err = avc_has_perm(isec->sid, other_isec->sid,
3931 isec->sclass,
3932 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3933 if (err)
3934 return err;
3935
3936 /* connecting socket */
3937 ssec = sock->sk->sk_security;
3938 ssec->peer_sid = other_isec->sid;
Eric Paris828dfe12008-04-17 13:17:49 -04003939
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 /* server child socket */
3941 ssec = newsk->sk_security;
3942 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003943 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3944
3945 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946}
3947
3948static int selinux_socket_unix_may_send(struct socket *sock,
3949 struct socket *other)
3950{
3951 struct inode_security_struct *isec;
3952 struct inode_security_struct *other_isec;
3953 struct avc_audit_data ad;
3954 int err;
3955
3956 isec = SOCK_INODE(sock)->i_security;
3957 other_isec = SOCK_INODE(other)->i_security;
3958
Eric Paris828dfe12008-04-17 13:17:49 -04003959 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 ad.u.net.sk = other->sk;
3961
3962 err = avc_has_perm(isec->sid, other_isec->sid,
3963 isec->sclass, SOCKET__SENDTO, &ad);
3964 if (err)
3965 return err;
3966
3967 return 0;
3968}
3969
Paul Mooreeffad8d2008-01-29 08:49:27 -05003970static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3971 u32 peer_sid,
3972 struct avc_audit_data *ad)
3973{
3974 int err;
3975 u32 if_sid;
3976 u32 node_sid;
3977
3978 err = sel_netif_sid(ifindex, &if_sid);
3979 if (err)
3980 return err;
3981 err = avc_has_perm(peer_sid, if_sid,
3982 SECCLASS_NETIF, NETIF__INGRESS, ad);
3983 if (err)
3984 return err;
3985
3986 err = sel_netnode_sid(addrp, family, &node_sid);
3987 if (err)
3988 return err;
3989 return avc_has_perm(peer_sid, node_sid,
3990 SECCLASS_NODE, NODE__RECVFROM, ad);
3991}
3992
Paul Moore220deb92008-01-29 08:38:23 -05003993static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3994 struct sk_buff *skb,
3995 struct avc_audit_data *ad,
3996 u16 family,
3997 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998{
Paul Moore220deb92008-01-29 08:38:23 -05003999 int err;
4000 struct sk_security_struct *sksec = sk->sk_security;
4001 u16 sk_class;
4002 u32 netif_perm, node_perm, recv_perm;
4003 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004004
Paul Moore220deb92008-01-29 08:38:23 -05004005 sk_sid = sksec->sid;
4006 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Paul Moore220deb92008-01-29 08:38:23 -05004008 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 case SECCLASS_UDP_SOCKET:
4010 netif_perm = NETIF__UDP_RECV;
4011 node_perm = NODE__UDP_RECV;
4012 recv_perm = UDP_SOCKET__RECV_MSG;
4013 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 case SECCLASS_TCP_SOCKET:
4015 netif_perm = NETIF__TCP_RECV;
4016 node_perm = NODE__TCP_RECV;
4017 recv_perm = TCP_SOCKET__RECV_MSG;
4018 break;
James Morris2ee92d42006-11-13 16:09:01 -08004019 case SECCLASS_DCCP_SOCKET:
4020 netif_perm = NETIF__DCCP_RECV;
4021 node_perm = NODE__DCCP_RECV;
4022 recv_perm = DCCP_SOCKET__RECV_MSG;
4023 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 default:
4025 netif_perm = NETIF__RAWIP_RECV;
4026 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05004027 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 break;
4029 }
4030
Paul Moore220deb92008-01-29 08:38:23 -05004031 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004033 return err;
4034 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4035 if (err)
4036 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004037
Paul Moore224dfbd2008-01-29 08:38:13 -05004038 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004040 return err;
4041 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004043 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
Paul Moore220deb92008-01-29 08:38:23 -05004045 if (!recv_perm)
4046 return 0;
Paul Moore3e112172008-04-10 10:48:14 -04004047 err = sel_netport_sid(sk->sk_protocol,
4048 ntohs(ad->u.net.sport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004049 if (unlikely(err)) {
4050 printk(KERN_WARNING
4051 "SELinux: failure in"
4052 " selinux_sock_rcv_skb_iptables_compat(),"
4053 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05004054 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004055 }
Paul Moore220deb92008-01-29 08:38:23 -05004056 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4057}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058
Paul Moore220deb92008-01-29 08:38:23 -05004059static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4060 struct avc_audit_data *ad,
4061 u16 family, char *addrp)
4062{
4063 int err;
4064 struct sk_security_struct *sksec = sk->sk_security;
4065 u32 peer_sid;
4066 u32 sk_sid = sksec->sid;
4067
4068 if (selinux_compat_net)
4069 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
4070 family, addrp);
4071 else
4072 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4073 PACKET__RECV, ad);
4074 if (err)
4075 return err;
4076
4077 if (selinux_policycap_netpeer) {
4078 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004080 return err;
4081 err = avc_has_perm(sk_sid, peer_sid,
4082 SECCLASS_PEER, PEER__RECV, ad);
4083 } else {
4084 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
4085 if (err)
4086 return err;
4087 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004089
James Morris4e5ab4c2006-06-09 00:33:33 -07004090 return err;
4091}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004092
James Morris4e5ab4c2006-06-09 00:33:33 -07004093static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4094{
Paul Moore220deb92008-01-29 08:38:23 -05004095 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004096 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004097 u16 family = sk->sk_family;
4098 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004099 struct avc_audit_data ad;
4100 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07004101
James Morris4e5ab4c2006-06-09 00:33:33 -07004102 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004103 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004104
4105 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004106 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004107 family = PF_INET;
4108
James Morris4e5ab4c2006-06-09 00:33:33 -07004109 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004110 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07004111 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004112 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004113 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004114 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004115
Paul Moore220deb92008-01-29 08:38:23 -05004116 /* If any sort of compatibility mode is enabled then handoff processing
4117 * to the selinux_sock_rcv_skb_compat() function to deal with the
4118 * special handling. We do this in an attempt to keep this function
4119 * as fast and as clean as possible. */
4120 if (selinux_compat_net || !selinux_policycap_netpeer)
4121 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4122 family, addrp);
4123
Paul Moored621d352008-01-29 08:43:36 -05004124 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4125 u32 peer_sid;
4126
4127 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4128 if (err)
4129 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004130 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4131 peer_sid, &ad);
4132 if (err)
4133 return err;
Paul Moored621d352008-01-29 08:43:36 -05004134 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4135 PEER__RECV, &ad);
4136 }
4137
Paul Mooreeffad8d2008-01-29 08:49:27 -05004138 if (selinux_secmark_enabled()) {
4139 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4140 PACKET__RECV, &ad);
4141 if (err)
4142 return err;
4143 }
4144
Paul Moored621d352008-01-29 08:43:36 -05004145 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146}
4147
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004148static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4149 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150{
4151 int err = 0;
4152 char *scontext;
4153 u32 scontext_len;
4154 struct sk_security_struct *ssec;
4155 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004156 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
4158 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004159
Paul Moore3de4bab2006-11-17 17:38:54 -05004160 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4161 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004162 ssec = sock->sk->sk_security;
4163 peer_sid = ssec->peer_sid;
4164 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004165 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 err = -ENOPROTOOPT;
4167 goto out;
4168 }
4169
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004170 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4171
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 if (err)
4173 goto out;
4174
4175 if (scontext_len > len) {
4176 err = -ERANGE;
4177 goto out_len;
4178 }
4179
4180 if (copy_to_user(optval, scontext, scontext_len))
4181 err = -EFAULT;
4182
4183out_len:
4184 if (put_user(scontext_len, optlen))
4185 err = -EFAULT;
4186
4187 kfree(scontext);
Eric Paris828dfe12008-04-17 13:17:49 -04004188out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 return err;
4190}
4191
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004192static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004193{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004194 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004195 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004196
Paul Moore75e22912008-01-29 08:38:04 -05004197 if (sock)
4198 family = sock->sk->sk_family;
4199 else if (skb && skb->sk)
4200 family = skb->sk->sk_family;
4201 else
4202 goto out;
4203
4204 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004205 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004206 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004207 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004208
Paul Moore75e22912008-01-29 08:38:04 -05004209out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004210 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004211 if (peer_secid == SECSID_NULL)
4212 return -EINVAL;
4213 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004214}
4215
Al Viro7d877f32005-10-21 03:20:43 -04004216static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217{
4218 return sk_alloc_security(sk, family, priority);
4219}
4220
4221static void selinux_sk_free_security(struct sock *sk)
4222{
4223 sk_free_security(sk);
4224}
4225
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004226static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4227{
4228 struct sk_security_struct *ssec = sk->sk_security;
4229 struct sk_security_struct *newssec = newsk->sk_security;
4230
4231 newssec->sid = ssec->sid;
4232 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004233 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004234
Paul Mooref74af6e2008-02-25 11:40:33 -05004235 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004236}
4237
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004238static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004239{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004240 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004241 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004242 else {
4243 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004244
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004245 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004246 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004247}
4248
Eric Paris828dfe12008-04-17 13:17:49 -04004249static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004250{
4251 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4252 struct sk_security_struct *sksec = sk->sk_security;
4253
David Woodhouse2148ccc2006-09-29 15:50:25 -07004254 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4255 sk->sk_family == PF_UNIX)
4256 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004257 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004258
4259 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004260}
4261
Adrian Bunk9a673e52006-08-15 00:03:53 -07004262static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4263 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004264{
4265 struct sk_security_struct *sksec = sk->sk_security;
4266 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004267 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004268 u32 peersid;
4269
Paul Moore220deb92008-01-29 08:38:23 -05004270 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4271 if (err)
4272 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004273 if (peersid == SECSID_NULL) {
4274 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004275 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004276 return 0;
4277 }
4278
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004279 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4280 if (err)
4281 return err;
4282
4283 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004284 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004285 return 0;
4286}
4287
Adrian Bunk9a673e52006-08-15 00:03:53 -07004288static void selinux_inet_csk_clone(struct sock *newsk,
4289 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004290{
4291 struct sk_security_struct *newsksec = newsk->sk_security;
4292
4293 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004294 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004295 /* NOTE: Ideally, we should also get the isec->sid for the
4296 new socket in sync, but we don't have the isec available yet.
4297 So we will wait until sock_graft to do it, by which
4298 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004299
Paul Moore9f2ad662006-11-17 17:38:53 -05004300 /* We don't need to take any sort of lock here as we are the only
4301 * thread with access to newsksec */
4302 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004303}
4304
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004305static void selinux_inet_conn_established(struct sock *sk,
4306 struct sk_buff *skb)
4307{
4308 struct sk_security_struct *sksec = sk->sk_security;
4309
Paul Moore220deb92008-01-29 08:38:23 -05004310 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004311}
4312
Adrian Bunk9a673e52006-08-15 00:03:53 -07004313static void selinux_req_classify_flow(const struct request_sock *req,
4314 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004315{
4316 fl->secid = req->secid;
4317}
4318
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4320{
4321 int err = 0;
4322 u32 perm;
4323 struct nlmsghdr *nlh;
4324 struct socket *sock = sk->sk_socket;
4325 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004326
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 if (skb->len < NLMSG_SPACE(0)) {
4328 err = -EINVAL;
4329 goto out;
4330 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004331 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4334 if (err) {
4335 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004336 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 "SELinux: unrecognized netlink message"
4338 " type=%hu for sclass=%hu\n",
4339 nlh->nlmsg_type, isec->sclass);
4340 if (!selinux_enforcing)
4341 err = 0;
4342 }
4343
4344 /* Ignore */
4345 if (err == -ENOENT)
4346 err = 0;
4347 goto out;
4348 }
4349
4350 err = socket_has_perm(current, sock, perm);
4351out:
4352 return err;
4353}
4354
4355#ifdef CONFIG_NETFILTER
4356
Paul Mooreeffad8d2008-01-29 08:49:27 -05004357static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4358 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004360 char *addrp;
4361 u32 peer_sid;
4362 struct avc_audit_data ad;
4363 u8 secmark_active;
4364 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004365
Paul Mooreeffad8d2008-01-29 08:49:27 -05004366 if (!selinux_policycap_netpeer)
4367 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004368
Paul Mooreeffad8d2008-01-29 08:49:27 -05004369 secmark_active = selinux_secmark_enabled();
4370 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4371 if (!secmark_active && !peerlbl_active)
4372 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004373
Paul Mooreeffad8d2008-01-29 08:49:27 -05004374 AVC_AUDIT_DATA_INIT(&ad, NET);
4375 ad.u.net.netif = ifindex;
4376 ad.u.net.family = family;
4377 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4378 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Paul Mooreeffad8d2008-01-29 08:49:27 -05004380 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4381 return NF_DROP;
4382
4383 if (peerlbl_active)
4384 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4385 peer_sid, &ad) != 0)
4386 return NF_DROP;
4387
4388 if (secmark_active)
4389 if (avc_has_perm(peer_sid, skb->secmark,
4390 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4391 return NF_DROP;
4392
4393 return NF_ACCEPT;
4394}
4395
4396static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4397 struct sk_buff *skb,
4398 const struct net_device *in,
4399 const struct net_device *out,
4400 int (*okfn)(struct sk_buff *))
4401{
4402 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4403}
4404
4405#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4406static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4407 struct sk_buff *skb,
4408 const struct net_device *in,
4409 const struct net_device *out,
4410 int (*okfn)(struct sk_buff *))
4411{
4412 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4413}
4414#endif /* IPV6 */
4415
4416static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4417 int ifindex,
4418 struct avc_audit_data *ad,
4419 u16 family, char *addrp)
4420{
4421 int err;
4422 struct sk_security_struct *sksec = sk->sk_security;
4423 u16 sk_class;
4424 u32 netif_perm, node_perm, send_perm;
4425 u32 port_sid, node_sid, if_sid, sk_sid;
4426
4427 sk_sid = sksec->sid;
4428 sk_class = sksec->sclass;
4429
4430 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 case SECCLASS_UDP_SOCKET:
4432 netif_perm = NETIF__UDP_SEND;
4433 node_perm = NODE__UDP_SEND;
4434 send_perm = UDP_SOCKET__SEND_MSG;
4435 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 case SECCLASS_TCP_SOCKET:
4437 netif_perm = NETIF__TCP_SEND;
4438 node_perm = NODE__TCP_SEND;
4439 send_perm = TCP_SOCKET__SEND_MSG;
4440 break;
James Morris2ee92d42006-11-13 16:09:01 -08004441 case SECCLASS_DCCP_SOCKET:
4442 netif_perm = NETIF__DCCP_SEND;
4443 node_perm = NODE__DCCP_SEND;
4444 send_perm = DCCP_SOCKET__SEND_MSG;
4445 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 default:
4447 netif_perm = NETIF__RAWIP_SEND;
4448 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004449 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450 break;
4451 }
4452
Paul Mooreeffad8d2008-01-29 08:49:27 -05004453 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004454 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004455 return err;
4456 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4457 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004458
Paul Moore224dfbd2008-01-29 08:38:13 -05004459 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004460 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004461 return err;
4462 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004463 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004464 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Paul Mooreeffad8d2008-01-29 08:49:27 -05004466 if (send_perm != 0)
4467 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Paul Moore3e112172008-04-10 10:48:14 -04004469 err = sel_netport_sid(sk->sk_protocol,
4470 ntohs(ad->u.net.dport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004471 if (unlikely(err)) {
4472 printk(KERN_WARNING
4473 "SELinux: failure in"
4474 " selinux_ip_postroute_iptables_compat(),"
4475 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004476 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004477 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004478 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004479}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Paul Mooreeffad8d2008-01-29 08:49:27 -05004481static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4482 int ifindex,
4483 struct avc_audit_data *ad,
4484 u16 family,
4485 char *addrp,
4486 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004487{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004488 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004489 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004490
Paul Mooreeffad8d2008-01-29 08:49:27 -05004491 if (sk == NULL)
4492 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004493 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004494
Paul Mooreeffad8d2008-01-29 08:49:27 -05004495 if (selinux_compat_net) {
4496 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4497 ad, family, addrp))
4498 return NF_DROP;
4499 } else {
4500 if (avc_has_perm(sksec->sid, skb->secmark,
4501 SECCLASS_PACKET, PACKET__SEND, ad))
4502 return NF_DROP;
4503 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004504
Paul Mooreeffad8d2008-01-29 08:49:27 -05004505 if (selinux_policycap_netpeer)
4506 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4507 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004508
Paul Mooreeffad8d2008-01-29 08:49:27 -05004509 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510}
4511
Paul Mooreeffad8d2008-01-29 08:49:27 -05004512static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4513 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004515 u32 secmark_perm;
4516 u32 peer_sid;
4517 struct sock *sk;
4518 struct avc_audit_data ad;
4519 char *addrp;
4520 u8 proto;
4521 u8 secmark_active;
4522 u8 peerlbl_active;
4523
4524 AVC_AUDIT_DATA_INIT(&ad, NET);
4525 ad.u.net.netif = ifindex;
4526 ad.u.net.family = family;
4527 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4528 return NF_DROP;
4529
4530 /* If any sort of compatibility mode is enabled then handoff processing
4531 * to the selinux_ip_postroute_compat() function to deal with the
4532 * special handling. We do this in an attempt to keep this function
4533 * as fast and as clean as possible. */
4534 if (selinux_compat_net || !selinux_policycap_netpeer)
4535 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4536 family, addrp, proto);
4537
4538 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4539 * packet transformation so allow the packet to pass without any checks
4540 * since we'll have another chance to perform access control checks
4541 * when the packet is on it's final way out.
4542 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4543 * is NULL, in this case go ahead and apply access control. */
4544 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4545 return NF_ACCEPT;
4546
4547 secmark_active = selinux_secmark_enabled();
4548 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4549 if (!secmark_active && !peerlbl_active)
4550 return NF_ACCEPT;
4551
4552 /* if the packet is locally generated (skb->sk != NULL) then use the
4553 * socket's label as the peer label, otherwise the packet is being
4554 * forwarded through this system and we need to fetch the peer label
4555 * directly from the packet */
4556 sk = skb->sk;
4557 if (sk) {
4558 struct sk_security_struct *sksec = sk->sk_security;
4559 peer_sid = sksec->sid;
4560 secmark_perm = PACKET__SEND;
4561 } else {
4562 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4563 return NF_DROP;
4564 secmark_perm = PACKET__FORWARD_OUT;
4565 }
4566
4567 if (secmark_active)
4568 if (avc_has_perm(peer_sid, skb->secmark,
4569 SECCLASS_PACKET, secmark_perm, &ad))
4570 return NF_DROP;
4571
4572 if (peerlbl_active) {
4573 u32 if_sid;
4574 u32 node_sid;
4575
4576 if (sel_netif_sid(ifindex, &if_sid))
4577 return NF_DROP;
4578 if (avc_has_perm(peer_sid, if_sid,
4579 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4580 return NF_DROP;
4581
4582 if (sel_netnode_sid(addrp, family, &node_sid))
4583 return NF_DROP;
4584 if (avc_has_perm(peer_sid, node_sid,
4585 SECCLASS_NODE, NODE__SENDTO, &ad))
4586 return NF_DROP;
4587 }
4588
4589 return NF_ACCEPT;
4590}
4591
4592static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4593 struct sk_buff *skb,
4594 const struct net_device *in,
4595 const struct net_device *out,
4596 int (*okfn)(struct sk_buff *))
4597{
4598 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599}
4600
4601#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004602static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4603 struct sk_buff *skb,
4604 const struct net_device *in,
4605 const struct net_device *out,
4606 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004608 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610#endif /* IPV6 */
4611
4612#endif /* CONFIG_NETFILTER */
4613
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4615{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 int err;
4617
4618 err = secondary_ops->netlink_send(sk, skb);
4619 if (err)
4620 return err;
4621
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4623 err = selinux_nlmsg_perm(sk, skb);
4624
4625 return err;
4626}
4627
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004628static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004630 int err;
4631 struct avc_audit_data ad;
4632
4633 err = secondary_ops->netlink_recv(skb, capability);
4634 if (err)
4635 return err;
4636
4637 AVC_AUDIT_DATA_INIT(&ad, CAP);
4638 ad.u.cap = capability;
4639
4640 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
Eric Paris828dfe12008-04-17 13:17:49 -04004641 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642}
4643
4644static int ipc_alloc_security(struct task_struct *task,
4645 struct kern_ipc_perm *perm,
4646 u16 sclass)
4647{
4648 struct task_security_struct *tsec = task->security;
4649 struct ipc_security_struct *isec;
4650
James Morris89d155e2005-10-30 14:59:21 -08004651 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 if (!isec)
4653 return -ENOMEM;
4654
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655 isec->sclass = sclass;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004656 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657 perm->security = isec;
4658
4659 return 0;
4660}
4661
4662static void ipc_free_security(struct kern_ipc_perm *perm)
4663{
4664 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 perm->security = NULL;
4666 kfree(isec);
4667}
4668
4669static int msg_msg_alloc_security(struct msg_msg *msg)
4670{
4671 struct msg_security_struct *msec;
4672
James Morris89d155e2005-10-30 14:59:21 -08004673 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674 if (!msec)
4675 return -ENOMEM;
4676
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 msec->sid = SECINITSID_UNLABELED;
4678 msg->security = msec;
4679
4680 return 0;
4681}
4682
4683static void msg_msg_free_security(struct msg_msg *msg)
4684{
4685 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686
4687 msg->security = NULL;
4688 kfree(msec);
4689}
4690
4691static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004692 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693{
4694 struct task_security_struct *tsec;
4695 struct ipc_security_struct *isec;
4696 struct avc_audit_data ad;
4697
4698 tsec = current->security;
4699 isec = ipc_perms->security;
4700
4701 AVC_AUDIT_DATA_INIT(&ad, IPC);
4702 ad.u.ipc_id = ipc_perms->key;
4703
Stephen Smalley6af963f2005-05-01 08:58:39 -07004704 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705}
4706
4707static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4708{
4709 return msg_msg_alloc_security(msg);
4710}
4711
4712static void selinux_msg_msg_free_security(struct msg_msg *msg)
4713{
4714 msg_msg_free_security(msg);
4715}
4716
4717/* message queue security operations */
4718static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4719{
4720 struct task_security_struct *tsec;
4721 struct ipc_security_struct *isec;
4722 struct avc_audit_data ad;
4723 int rc;
4724
4725 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4726 if (rc)
4727 return rc;
4728
4729 tsec = current->security;
4730 isec = msq->q_perm.security;
4731
4732 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004733 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734
4735 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4736 MSGQ__CREATE, &ad);
4737 if (rc) {
4738 ipc_free_security(&msq->q_perm);
4739 return rc;
4740 }
4741 return 0;
4742}
4743
4744static void selinux_msg_queue_free_security(struct msg_queue *msq)
4745{
4746 ipc_free_security(&msq->q_perm);
4747}
4748
4749static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4750{
4751 struct task_security_struct *tsec;
4752 struct ipc_security_struct *isec;
4753 struct avc_audit_data ad;
4754
4755 tsec = current->security;
4756 isec = msq->q_perm.security;
4757
4758 AVC_AUDIT_DATA_INIT(&ad, IPC);
4759 ad.u.ipc_id = msq->q_perm.key;
4760
4761 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4762 MSGQ__ASSOCIATE, &ad);
4763}
4764
4765static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4766{
4767 int err;
4768 int perms;
4769
Eric Paris828dfe12008-04-17 13:17:49 -04004770 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 case IPC_INFO:
4772 case MSG_INFO:
4773 /* No specific object, just general system-wide information. */
4774 return task_has_system(current, SYSTEM__IPC_INFO);
4775 case IPC_STAT:
4776 case MSG_STAT:
4777 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4778 break;
4779 case IPC_SET:
4780 perms = MSGQ__SETATTR;
4781 break;
4782 case IPC_RMID:
4783 perms = MSGQ__DESTROY;
4784 break;
4785 default:
4786 return 0;
4787 }
4788
Stephen Smalley6af963f2005-05-01 08:58:39 -07004789 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790 return err;
4791}
4792
4793static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
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 = current->security;
4802 isec = msq->q_perm.security;
4803 msec = msg->security;
4804
4805 /*
4806 * First time through, need to assign label to the message
4807 */
4808 if (msec->sid == SECINITSID_UNLABELED) {
4809 /*
4810 * Compute new sid based on current process and
4811 * message queue this message will be stored in
4812 */
4813 rc = security_transition_sid(tsec->sid,
4814 isec->sid,
4815 SECCLASS_MSG,
4816 &msec->sid);
4817 if (rc)
4818 return rc;
4819 }
4820
4821 AVC_AUDIT_DATA_INIT(&ad, IPC);
4822 ad.u.ipc_id = msq->q_perm.key;
4823
4824 /* Can this process write to the queue? */
4825 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4826 MSGQ__WRITE, &ad);
4827 if (!rc)
4828 /* Can this process send the message */
4829 rc = avc_has_perm(tsec->sid, msec->sid,
4830 SECCLASS_MSG, MSG__SEND, &ad);
4831 if (!rc)
4832 /* Can the message be put in the queue? */
4833 rc = avc_has_perm(msec->sid, isec->sid,
4834 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4835
4836 return rc;
4837}
4838
4839static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4840 struct task_struct *target,
4841 long type, int mode)
4842{
4843 struct task_security_struct *tsec;
4844 struct ipc_security_struct *isec;
4845 struct msg_security_struct *msec;
4846 struct avc_audit_data ad;
4847 int rc;
4848
4849 tsec = target->security;
4850 isec = msq->q_perm.security;
4851 msec = msg->security;
4852
4853 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004854 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855
4856 rc = avc_has_perm(tsec->sid, isec->sid,
4857 SECCLASS_MSGQ, MSGQ__READ, &ad);
4858 if (!rc)
4859 rc = avc_has_perm(tsec->sid, msec->sid,
4860 SECCLASS_MSG, MSG__RECEIVE, &ad);
4861 return rc;
4862}
4863
4864/* Shared Memory security operations */
4865static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4866{
4867 struct task_security_struct *tsec;
4868 struct ipc_security_struct *isec;
4869 struct avc_audit_data ad;
4870 int rc;
4871
4872 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4873 if (rc)
4874 return rc;
4875
4876 tsec = current->security;
4877 isec = shp->shm_perm.security;
4878
4879 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004880 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881
4882 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4883 SHM__CREATE, &ad);
4884 if (rc) {
4885 ipc_free_security(&shp->shm_perm);
4886 return rc;
4887 }
4888 return 0;
4889}
4890
4891static void selinux_shm_free_security(struct shmid_kernel *shp)
4892{
4893 ipc_free_security(&shp->shm_perm);
4894}
4895
4896static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4897{
4898 struct task_security_struct *tsec;
4899 struct ipc_security_struct *isec;
4900 struct avc_audit_data ad;
4901
4902 tsec = current->security;
4903 isec = shp->shm_perm.security;
4904
4905 AVC_AUDIT_DATA_INIT(&ad, IPC);
4906 ad.u.ipc_id = shp->shm_perm.key;
4907
4908 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4909 SHM__ASSOCIATE, &ad);
4910}
4911
4912/* Note, at this point, shp is locked down */
4913static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4914{
4915 int perms;
4916 int err;
4917
Eric Paris828dfe12008-04-17 13:17:49 -04004918 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919 case IPC_INFO:
4920 case SHM_INFO:
4921 /* No specific object, just general system-wide information. */
4922 return task_has_system(current, SYSTEM__IPC_INFO);
4923 case IPC_STAT:
4924 case SHM_STAT:
4925 perms = SHM__GETATTR | SHM__ASSOCIATE;
4926 break;
4927 case IPC_SET:
4928 perms = SHM__SETATTR;
4929 break;
4930 case SHM_LOCK:
4931 case SHM_UNLOCK:
4932 perms = SHM__LOCK;
4933 break;
4934 case IPC_RMID:
4935 perms = SHM__DESTROY;
4936 break;
4937 default:
4938 return 0;
4939 }
4940
Stephen Smalley6af963f2005-05-01 08:58:39 -07004941 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942 return err;
4943}
4944
4945static int selinux_shm_shmat(struct shmid_kernel *shp,
4946 char __user *shmaddr, int shmflg)
4947{
4948 u32 perms;
4949 int rc;
4950
4951 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4952 if (rc)
4953 return rc;
4954
4955 if (shmflg & SHM_RDONLY)
4956 perms = SHM__READ;
4957 else
4958 perms = SHM__READ | SHM__WRITE;
4959
Stephen Smalley6af963f2005-05-01 08:58:39 -07004960 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961}
4962
4963/* Semaphore security operations */
4964static int selinux_sem_alloc_security(struct sem_array *sma)
4965{
4966 struct task_security_struct *tsec;
4967 struct ipc_security_struct *isec;
4968 struct avc_audit_data ad;
4969 int rc;
4970
4971 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4972 if (rc)
4973 return rc;
4974
4975 tsec = current->security;
4976 isec = sma->sem_perm.security;
4977
4978 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004979 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980
4981 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4982 SEM__CREATE, &ad);
4983 if (rc) {
4984 ipc_free_security(&sma->sem_perm);
4985 return rc;
4986 }
4987 return 0;
4988}
4989
4990static void selinux_sem_free_security(struct sem_array *sma)
4991{
4992 ipc_free_security(&sma->sem_perm);
4993}
4994
4995static int selinux_sem_associate(struct sem_array *sma, int semflg)
4996{
4997 struct task_security_struct *tsec;
4998 struct ipc_security_struct *isec;
4999 struct avc_audit_data ad;
5000
5001 tsec = current->security;
5002 isec = sma->sem_perm.security;
5003
5004 AVC_AUDIT_DATA_INIT(&ad, IPC);
5005 ad.u.ipc_id = sma->sem_perm.key;
5006
5007 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
5008 SEM__ASSOCIATE, &ad);
5009}
5010
5011/* Note, at this point, sma is locked down */
5012static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5013{
5014 int err;
5015 u32 perms;
5016
Eric Paris828dfe12008-04-17 13:17:49 -04005017 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 case IPC_INFO:
5019 case SEM_INFO:
5020 /* No specific object, just general system-wide information. */
5021 return task_has_system(current, SYSTEM__IPC_INFO);
5022 case GETPID:
5023 case GETNCNT:
5024 case GETZCNT:
5025 perms = SEM__GETATTR;
5026 break;
5027 case GETVAL:
5028 case GETALL:
5029 perms = SEM__READ;
5030 break;
5031 case SETVAL:
5032 case SETALL:
5033 perms = SEM__WRITE;
5034 break;
5035 case IPC_RMID:
5036 perms = SEM__DESTROY;
5037 break;
5038 case IPC_SET:
5039 perms = SEM__SETATTR;
5040 break;
5041 case IPC_STAT:
5042 case SEM_STAT:
5043 perms = SEM__GETATTR | SEM__ASSOCIATE;
5044 break;
5045 default:
5046 return 0;
5047 }
5048
Stephen Smalley6af963f2005-05-01 08:58:39 -07005049 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 return err;
5051}
5052
5053static int selinux_sem_semop(struct sem_array *sma,
5054 struct sembuf *sops, unsigned nsops, int alter)
5055{
5056 u32 perms;
5057
5058 if (alter)
5059 perms = SEM__READ | SEM__WRITE;
5060 else
5061 perms = SEM__READ;
5062
Stephen Smalley6af963f2005-05-01 08:58:39 -07005063 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064}
5065
5066static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5067{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 u32 av = 0;
5069
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070 av = 0;
5071 if (flag & S_IRUGO)
5072 av |= IPC__UNIX_READ;
5073 if (flag & S_IWUGO)
5074 av |= IPC__UNIX_WRITE;
5075
5076 if (av == 0)
5077 return 0;
5078
Stephen Smalley6af963f2005-05-01 08:58:39 -07005079 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080}
5081
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005082static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5083{
5084 struct ipc_security_struct *isec = ipcp->security;
5085 *secid = isec->sid;
5086}
5087
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088/* module stacking operations */
Eric Paris828dfe12008-04-17 13:17:49 -04005089static int selinux_register_security(const char *name, struct security_operations *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090{
5091 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005092 printk(KERN_ERR "%s: There is already a secondary security "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005093 "module registered.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094 return -EINVAL;
Eric Paris828dfe12008-04-17 13:17:49 -04005095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096
5097 secondary_ops = ops;
5098
5099 printk(KERN_INFO "%s: Registering secondary module %s\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005100 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101 name);
5102
5103 return 0;
5104}
5105
Eric Paris828dfe12008-04-17 13:17:49 -04005106static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107{
5108 if (inode)
5109 inode_doinit_with_dentry(inode, dentry);
5110}
5111
5112static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005113 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114{
5115 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005116 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005118 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119
5120 if (current != p) {
5121 error = task_has_perm(current, p, PROCESS__GETATTR);
5122 if (error)
5123 return error;
5124 }
5125
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 tsec = p->security;
5127
5128 if (!strcmp(name, "current"))
5129 sid = tsec->sid;
5130 else if (!strcmp(name, "prev"))
5131 sid = tsec->osid;
5132 else if (!strcmp(name, "exec"))
5133 sid = tsec->exec_sid;
5134 else if (!strcmp(name, "fscreate"))
5135 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005136 else if (!strcmp(name, "keycreate"))
5137 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005138 else if (!strcmp(name, "sockcreate"))
5139 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140 else
5141 return -EINVAL;
5142
5143 if (!sid)
5144 return 0;
5145
Al Viro04ff9702007-03-12 16:17:58 +00005146 error = security_sid_to_context(sid, value, &len);
5147 if (error)
5148 return error;
5149 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150}
5151
5152static int selinux_setprocattr(struct task_struct *p,
5153 char *name, void *value, size_t size)
5154{
5155 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005156 struct task_struct *tracer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 u32 sid = 0;
5158 int error;
5159 char *str = value;
5160
5161 if (current != p) {
5162 /* SELinux only allows a process to change its own
5163 security attributes. */
5164 return -EACCES;
5165 }
5166
5167 /*
5168 * Basic control over ability to set these attributes at all.
5169 * current == p, but we'll pass them separately in case the
5170 * above restriction is ever removed.
5171 */
5172 if (!strcmp(name, "exec"))
5173 error = task_has_perm(current, p, PROCESS__SETEXEC);
5174 else if (!strcmp(name, "fscreate"))
5175 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005176 else if (!strcmp(name, "keycreate"))
5177 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005178 else if (!strcmp(name, "sockcreate"))
5179 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 else if (!strcmp(name, "current"))
5181 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5182 else
5183 error = -EINVAL;
5184 if (error)
5185 return error;
5186
5187 /* Obtain a SID for the context, if one was specified. */
5188 if (size && str[1] && str[1] != '\n') {
5189 if (str[size-1] == '\n') {
5190 str[size-1] = 0;
5191 size--;
5192 }
5193 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005194 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5195 if (!capable(CAP_MAC_ADMIN))
5196 return error;
5197 error = security_context_to_sid_force(value, size,
5198 &sid);
5199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 if (error)
5201 return error;
5202 }
5203
5204 /* Permission checking based on the specified context is
5205 performed during the actual operation (execve,
5206 open/mkdir/...), when we know the full context of the
5207 operation. See selinux_bprm_set_security for the execve
5208 checks and may_create for the file creation checks. The
5209 operation will then fail if the context is not permitted. */
5210 tsec = p->security;
5211 if (!strcmp(name, "exec"))
5212 tsec->exec_sid = sid;
5213 else if (!strcmp(name, "fscreate"))
5214 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005215 else if (!strcmp(name, "keycreate")) {
5216 error = may_create_key(sid, p);
5217 if (error)
5218 return error;
5219 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005220 } else if (!strcmp(name, "sockcreate"))
5221 tsec->sockcreate_sid = sid;
5222 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223 struct av_decision avd;
5224
5225 if (sid == 0)
5226 return -EINVAL;
5227
5228 /* Only allow single threaded processes to change context */
5229 if (atomic_read(&p->mm->mm_users) != 1) {
5230 struct task_struct *g, *t;
5231 struct mm_struct *mm = p->mm;
5232 read_lock(&tasklist_lock);
5233 do_each_thread(g, t)
5234 if (t->mm == mm && t != p) {
5235 read_unlock(&tasklist_lock);
5236 return -EPERM;
5237 }
5238 while_each_thread(g, t);
5239 read_unlock(&tasklist_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04005240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
5242 /* Check permissions for the transition. */
5243 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005244 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 if (error)
5246 return error;
5247
5248 /* Check for ptracing, and update the task SID if ok.
5249 Otherwise, leave SID unchanged and fail. */
5250 task_lock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005251 rcu_read_lock();
5252 tracer = task_tracer_task(p);
5253 if (tracer != NULL) {
5254 struct task_security_struct *ptsec = tracer->security;
5255 u32 ptsid = ptsec->sid;
5256 rcu_read_unlock();
5257 error = avc_has_perm_noaudit(ptsid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005259 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 if (!error)
5261 tsec->sid = sid;
5262 task_unlock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005263 avc_audit(ptsid, sid, SECCLASS_PROCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264 PROCESS__PTRACE, &avd, error, NULL);
5265 if (error)
5266 return error;
5267 } else {
Roland McGrath03563572008-03-26 15:46:39 -07005268 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 tsec->sid = sid;
5270 task_unlock(p);
5271 }
Eric Paris828dfe12008-04-17 13:17:49 -04005272 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273 return -EINVAL;
5274
5275 return size;
5276}
5277
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005278static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5279{
5280 return security_sid_to_context(secid, secdata, seclen);
5281}
5282
David Howells7bf570d2008-04-29 20:52:51 +01005283static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005284{
5285 return security_context_to_sid(secdata, seclen, secid);
5286}
5287
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005288static void selinux_release_secctx(char *secdata, u32 seclen)
5289{
Paul Moore088999e2007-08-01 11:12:58 -04005290 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005291}
5292
Michael LeMayd7200242006-06-22 14:47:17 -07005293#ifdef CONFIG_KEYS
5294
David Howells7e047ef2006-06-26 00:24:50 -07005295static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5296 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005297{
5298 struct task_security_struct *tsec = tsk->security;
5299 struct key_security_struct *ksec;
5300
5301 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5302 if (!ksec)
5303 return -ENOMEM;
5304
Michael LeMay4eb582c2006-06-26 00:24:57 -07005305 if (tsec->keycreate_sid)
5306 ksec->sid = tsec->keycreate_sid;
5307 else
5308 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005309 k->security = ksec;
5310
5311 return 0;
5312}
5313
5314static void selinux_key_free(struct key *k)
5315{
5316 struct key_security_struct *ksec = k->security;
5317
5318 k->security = NULL;
5319 kfree(ksec);
5320}
5321
5322static int selinux_key_permission(key_ref_t key_ref,
5323 struct task_struct *ctx,
5324 key_perm_t perm)
5325{
5326 struct key *key;
5327 struct task_security_struct *tsec;
5328 struct key_security_struct *ksec;
5329
5330 key = key_ref_to_ptr(key_ref);
5331
5332 tsec = ctx->security;
5333 ksec = key->security;
5334
5335 /* if no specific permissions are requested, we skip the
5336 permission check. No serious, additional covert channels
5337 appear to be created. */
5338 if (perm == 0)
5339 return 0;
5340
5341 return avc_has_perm(tsec->sid, ksec->sid,
5342 SECCLASS_KEY, perm, NULL);
5343}
5344
David Howells70a5bb72008-04-29 01:01:26 -07005345static int selinux_key_getsecurity(struct key *key, char **_buffer)
5346{
5347 struct key_security_struct *ksec = key->security;
5348 char *context = NULL;
5349 unsigned len;
5350 int rc;
5351
5352 rc = security_sid_to_context(ksec->sid, &context, &len);
5353 if (!rc)
5354 rc = len;
5355 *_buffer = context;
5356 return rc;
5357}
5358
Michael LeMayd7200242006-06-22 14:47:17 -07005359#endif
5360
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005362 .name = "selinux",
5363
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364 .ptrace = selinux_ptrace,
5365 .capget = selinux_capget,
5366 .capset_check = selinux_capset_check,
5367 .capset_set = selinux_capset_set,
5368 .sysctl = selinux_sysctl,
5369 .capable = selinux_capable,
5370 .quotactl = selinux_quotactl,
5371 .quota_on = selinux_quota_on,
5372 .syslog = selinux_syslog,
5373 .vm_enough_memory = selinux_vm_enough_memory,
5374
5375 .netlink_send = selinux_netlink_send,
Eric Paris828dfe12008-04-17 13:17:49 -04005376 .netlink_recv = selinux_netlink_recv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377
5378 .bprm_alloc_security = selinux_bprm_alloc_security,
5379 .bprm_free_security = selinux_bprm_free_security,
5380 .bprm_apply_creds = selinux_bprm_apply_creds,
5381 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5382 .bprm_set_security = selinux_bprm_set_security,
5383 .bprm_check_security = selinux_bprm_check_security,
5384 .bprm_secureexec = selinux_bprm_secureexec,
5385
5386 .sb_alloc_security = selinux_sb_alloc_security,
5387 .sb_free_security = selinux_sb_free_security,
5388 .sb_copy_data = selinux_sb_copy_data,
Eric Paris828dfe12008-04-17 13:17:49 -04005389 .sb_kern_mount = selinux_sb_kern_mount,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 .sb_statfs = selinux_sb_statfs,
5391 .sb_mount = selinux_mount,
5392 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005393 .sb_get_mnt_opts = selinux_get_mnt_opts,
5394 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005395 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005396 .sb_parse_opts_str = selinux_parse_opts_str,
5397
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
5399 .inode_alloc_security = selinux_inode_alloc_security,
5400 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005401 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404 .inode_unlink = selinux_inode_unlink,
5405 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407 .inode_rmdir = selinux_inode_rmdir,
5408 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410 .inode_readlink = selinux_inode_readlink,
5411 .inode_follow_link = selinux_inode_follow_link,
5412 .inode_permission = selinux_inode_permission,
5413 .inode_setattr = selinux_inode_setattr,
5414 .inode_getattr = selinux_inode_getattr,
5415 .inode_setxattr = selinux_inode_setxattr,
5416 .inode_post_setxattr = selinux_inode_post_setxattr,
5417 .inode_getxattr = selinux_inode_getxattr,
5418 .inode_listxattr = selinux_inode_listxattr,
5419 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005420 .inode_getsecurity = selinux_inode_getsecurity,
5421 .inode_setsecurity = selinux_inode_setsecurity,
5422 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005423 .inode_need_killpriv = selinux_inode_need_killpriv,
5424 .inode_killpriv = selinux_inode_killpriv,
Eric Parisf5269712008-05-14 11:27:45 -04005425 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426
5427 .file_permission = selinux_file_permission,
5428 .file_alloc_security = selinux_file_alloc_security,
5429 .file_free_security = selinux_file_free_security,
5430 .file_ioctl = selinux_file_ioctl,
5431 .file_mmap = selinux_file_mmap,
5432 .file_mprotect = selinux_file_mprotect,
5433 .file_lock = selinux_file_lock,
5434 .file_fcntl = selinux_file_fcntl,
5435 .file_set_fowner = selinux_file_set_fowner,
5436 .file_send_sigiotask = selinux_file_send_sigiotask,
5437 .file_receive = selinux_file_receive,
5438
Eric Paris828dfe12008-04-17 13:17:49 -04005439 .dentry_open = selinux_dentry_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005440
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441 .task_create = selinux_task_create,
5442 .task_alloc_security = selinux_task_alloc_security,
5443 .task_free_security = selinux_task_free_security,
5444 .task_setuid = selinux_task_setuid,
5445 .task_post_setuid = selinux_task_post_setuid,
5446 .task_setgid = selinux_task_setgid,
5447 .task_setpgid = selinux_task_setpgid,
5448 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005449 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005450 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 .task_setgroups = selinux_task_setgroups,
5452 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005453 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005454 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455 .task_setrlimit = selinux_task_setrlimit,
5456 .task_setscheduler = selinux_task_setscheduler,
5457 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005458 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459 .task_kill = selinux_task_kill,
5460 .task_wait = selinux_task_wait,
5461 .task_prctl = selinux_task_prctl,
5462 .task_reparent_to_init = selinux_task_reparent_to_init,
Eric Paris828dfe12008-04-17 13:17:49 -04005463 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464
5465 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005466 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
5468 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5469 .msg_msg_free_security = selinux_msg_msg_free_security,
5470
5471 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5472 .msg_queue_free_security = selinux_msg_queue_free_security,
5473 .msg_queue_associate = selinux_msg_queue_associate,
5474 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5475 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5476 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5477
5478 .shm_alloc_security = selinux_shm_alloc_security,
5479 .shm_free_security = selinux_shm_free_security,
5480 .shm_associate = selinux_shm_associate,
5481 .shm_shmctl = selinux_shm_shmctl,
5482 .shm_shmat = selinux_shm_shmat,
5483
Eric Paris828dfe12008-04-17 13:17:49 -04005484 .sem_alloc_security = selinux_sem_alloc_security,
5485 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486 .sem_associate = selinux_sem_associate,
5487 .sem_semctl = selinux_sem_semctl,
5488 .sem_semop = selinux_sem_semop,
5489
5490 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491
Eric Paris828dfe12008-04-17 13:17:49 -04005492 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493
Eric Paris828dfe12008-04-17 13:17:49 -04005494 .getprocattr = selinux_getprocattr,
5495 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005496
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005497 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005498 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005499 .release_secctx = selinux_release_secctx,
5500
Eric Paris828dfe12008-04-17 13:17:49 -04005501 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502 .unix_may_send = selinux_socket_unix_may_send,
5503
5504 .socket_create = selinux_socket_create,
5505 .socket_post_create = selinux_socket_post_create,
5506 .socket_bind = selinux_socket_bind,
5507 .socket_connect = selinux_socket_connect,
5508 .socket_listen = selinux_socket_listen,
5509 .socket_accept = selinux_socket_accept,
5510 .socket_sendmsg = selinux_socket_sendmsg,
5511 .socket_recvmsg = selinux_socket_recvmsg,
5512 .socket_getsockname = selinux_socket_getsockname,
5513 .socket_getpeername = selinux_socket_getpeername,
5514 .socket_getsockopt = selinux_socket_getsockopt,
5515 .socket_setsockopt = selinux_socket_setsockopt,
5516 .socket_shutdown = selinux_socket_shutdown,
5517 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005518 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5519 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520 .sk_alloc_security = selinux_sk_alloc_security,
5521 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005522 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005523 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005524 .sock_graft = selinux_sock_graft,
5525 .inet_conn_request = selinux_inet_conn_request,
5526 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005527 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005528 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005529
5530#ifdef CONFIG_SECURITY_NETWORK_XFRM
5531 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5532 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5533 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005534 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005535 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5536 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005537 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005538 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005539 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005540 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005542
5543#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005544 .key_alloc = selinux_key_alloc,
5545 .key_free = selinux_key_free,
5546 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005547 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005548#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005549
5550#ifdef CONFIG_AUDIT
5551 .audit_rule_init = selinux_audit_rule_init,
5552 .audit_rule_known = selinux_audit_rule_known,
5553 .audit_rule_match = selinux_audit_rule_match,
5554 .audit_rule_free = selinux_audit_rule_free,
5555#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556};
5557
5558static __init int selinux_init(void)
5559{
5560 struct task_security_struct *tsec;
5561
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005562 if (!security_module_enable(&selinux_ops)) {
5563 selinux_enabled = 0;
5564 return 0;
5565 }
5566
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567 if (!selinux_enabled) {
5568 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5569 return 0;
5570 }
5571
5572 printk(KERN_INFO "SELinux: Initializing.\n");
5573
5574 /* Set the security state for the initial task. */
5575 if (task_alloc_security(current))
5576 panic("SELinux: Failed to initialize initial task.\n");
5577 tsec = current->security;
5578 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5579
James Morris7cae7e22006-03-22 00:09:22 -08005580 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5581 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005582 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583 avc_init();
5584
5585 original_ops = secondary_ops = security_ops;
5586 if (!secondary_ops)
Eric Paris828dfe12008-04-17 13:17:49 -04005587 panic("SELinux: No initial security operations\n");
5588 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589 panic("SELinux: Unable to register with kernel.\n");
5590
Eric Paris828dfe12008-04-17 13:17:49 -04005591 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005592 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005593 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005594 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005595
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 return 0;
5597}
5598
5599void selinux_complete_init(void)
5600{
Eric Parisfadcdb42007-02-22 18:11:31 -05005601 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602
5603 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005604 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005605 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606 spin_lock(&sb_security_lock);
5607next_sb:
5608 if (!list_empty(&superblock_security_head)) {
5609 struct superblock_security_struct *sbsec =
5610 list_entry(superblock_security_head.next,
Eric Paris828dfe12008-04-17 13:17:49 -04005611 struct superblock_security_struct,
5612 list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005616 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 down_read(&sb->s_umount);
5618 if (sb->s_root)
5619 superblock_doinit(sb, NULL);
5620 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005621 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622 spin_lock(&sb_security_lock);
5623 list_del_init(&sbsec->list);
5624 goto next_sb;
5625 }
5626 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005627 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005628}
5629
5630/* SELinux requires early initialization in order to label
5631 all processes and objects when they are created. */
5632security_initcall(selinux_init);
5633
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005634#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
Paul Mooreeffad8d2008-01-29 08:49:27 -05005636static struct nf_hook_ops selinux_ipv4_ops[] = {
5637 {
5638 .hook = selinux_ipv4_postroute,
5639 .owner = THIS_MODULE,
5640 .pf = PF_INET,
5641 .hooknum = NF_INET_POST_ROUTING,
5642 .priority = NF_IP_PRI_SELINUX_LAST,
5643 },
5644 {
5645 .hook = selinux_ipv4_forward,
5646 .owner = THIS_MODULE,
5647 .pf = PF_INET,
5648 .hooknum = NF_INET_FORWARD,
5649 .priority = NF_IP_PRI_SELINUX_FIRST,
5650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651};
5652
5653#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5654
Paul Mooreeffad8d2008-01-29 08:49:27 -05005655static struct nf_hook_ops selinux_ipv6_ops[] = {
5656 {
5657 .hook = selinux_ipv6_postroute,
5658 .owner = THIS_MODULE,
5659 .pf = PF_INET6,
5660 .hooknum = NF_INET_POST_ROUTING,
5661 .priority = NF_IP6_PRI_SELINUX_LAST,
5662 },
5663 {
5664 .hook = selinux_ipv6_forward,
5665 .owner = THIS_MODULE,
5666 .pf = PF_INET6,
5667 .hooknum = NF_INET_FORWARD,
5668 .priority = NF_IP6_PRI_SELINUX_FIRST,
5669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670};
5671
5672#endif /* IPV6 */
5673
5674static int __init selinux_nf_ip_init(void)
5675{
5676 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005677 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678
5679 if (!selinux_enabled)
5680 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005681
5682 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5683
Paul Mooreeffad8d2008-01-29 08:49:27 -05005684 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5685 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5686 if (err)
5687 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5688 err);
5689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690
5691#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005692 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5693 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5694 if (err)
5695 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5696 err);
5697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005699
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700out:
5701 return err;
5702}
5703
5704__initcall(selinux_nf_ip_init);
5705
5706#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5707static void selinux_nf_ip_exit(void)
5708{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005709 u32 iter;
5710
Eric Parisfadcdb42007-02-22 18:11:31 -05005711 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712
Paul Mooreeffad8d2008-01-29 08:49:27 -05005713 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5714 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005716 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5717 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718#endif /* IPV6 */
5719}
5720#endif
5721
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005722#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723
5724#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5725#define selinux_nf_ip_exit()
5726#endif
5727
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005728#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
5730#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005731static int selinux_disabled;
5732
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733int selinux_disable(void)
5734{
5735 extern void exit_sel_fs(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736
5737 if (ss_initialized) {
5738 /* Not permitted after initial policy load. */
5739 return -EINVAL;
5740 }
5741
5742 if (selinux_disabled) {
5743 /* Only do this once. */
5744 return -EINVAL;
5745 }
5746
5747 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5748
5749 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005750 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751
5752 /* Reset security_ops to the secondary module, dummy or capability. */
5753 security_ops = secondary_ops;
5754
5755 /* Unregister netfilter hooks. */
5756 selinux_nf_ip_exit();
5757
5758 /* Unregister selinuxfs. */
5759 exit_sel_fs();
5760
5761 return 0;
5762}
5763#endif