blob: eca70f42e678c67df6c524b973733917c32bff1b [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
1689static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1690{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 int rc;
1692
Eric Paris828dfe12008-04-17 13:17:49 -04001693 rc = secondary_ops->ptrace(parent, child);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 if (rc)
1695 return rc;
1696
Roland McGrath03563572008-03-26 15:46:39 -07001697 return task_has_perm(parent, child, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698}
1699
1700static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001701 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
1703 int error;
1704
1705 error = task_has_perm(current, target, PROCESS__GETCAP);
1706 if (error)
1707 return error;
1708
1709 return secondary_ops->capget(target, effective, inheritable, permitted);
1710}
1711
1712static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001713 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714{
1715 int error;
1716
1717 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1718 if (error)
1719 return error;
1720
1721 return task_has_perm(current, target, PROCESS__SETCAP);
1722}
1723
1724static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001725 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
1727 secondary_ops->capset_set(target, effective, inheritable, permitted);
1728}
1729
1730static int selinux_capable(struct task_struct *tsk, int cap)
1731{
1732 int rc;
1733
1734 rc = secondary_ops->capable(tsk, cap);
1735 if (rc)
1736 return rc;
1737
Eric Paris828dfe12008-04-17 13:17:49 -04001738 return task_has_capability(tsk, cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739}
1740
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001741static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1742{
1743 int buflen, rc;
1744 char *buffer, *path, *end;
1745
1746 rc = -ENOMEM;
Eric Paris828dfe12008-04-17 13:17:49 -04001747 buffer = (char *)__get_free_page(GFP_KERNEL);
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001748 if (!buffer)
1749 goto out;
1750
1751 buflen = PAGE_SIZE;
1752 end = buffer+buflen;
1753 *--end = '\0';
1754 buflen--;
1755 path = end-1;
1756 *path = '/';
1757 while (table) {
1758 const char *name = table->procname;
1759 size_t namelen = strlen(name);
1760 buflen -= namelen + 1;
1761 if (buflen < 0)
1762 goto out_free;
1763 end -= namelen;
1764 memcpy(end, name, namelen);
1765 *--end = '/';
1766 path = end;
1767 table = table->parent;
1768 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001769 buflen -= 4;
1770 if (buflen < 0)
1771 goto out_free;
1772 end -= 4;
1773 memcpy(end, "/sys", 4);
1774 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001775 rc = security_genfs_sid("proc", path, tclass, sid);
1776out_free:
1777 free_page((unsigned long)buffer);
1778out:
1779 return rc;
1780}
1781
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782static int selinux_sysctl(ctl_table *table, int op)
1783{
1784 int error = 0;
1785 u32 av;
1786 struct task_security_struct *tsec;
1787 u32 tsid;
1788 int rc;
1789
1790 rc = secondary_ops->sysctl(table, op);
1791 if (rc)
1792 return rc;
1793
1794 tsec = current->security;
1795
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001796 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1797 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 if (rc) {
1799 /* Default to the well-defined sysctl SID. */
1800 tsid = SECINITSID_SYSCTL;
1801 }
1802
1803 /* The op values are "defined" in sysctl.c, thereby creating
1804 * a bad coupling between this module and sysctl.c */
Eric Paris828dfe12008-04-17 13:17:49 -04001805 if (op == 001) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 error = avc_has_perm(tsec->sid, tsid,
1807 SECCLASS_DIR, DIR__SEARCH, NULL);
1808 } else {
1809 av = 0;
1810 if (op & 004)
1811 av |= FILE__READ;
1812 if (op & 002)
1813 av |= FILE__WRITE;
1814 if (av)
1815 error = avc_has_perm(tsec->sid, tsid,
1816 SECCLASS_FILE, av, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
1819 return error;
1820}
1821
1822static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1823{
1824 int rc = 0;
1825
1826 if (!sb)
1827 return 0;
1828
1829 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001830 case Q_SYNC:
1831 case Q_QUOTAON:
1832 case Q_QUOTAOFF:
1833 case Q_SETINFO:
1834 case Q_SETQUOTA:
1835 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
1836 NULL);
1837 break;
1838 case Q_GETFMT:
1839 case Q_GETINFO:
1840 case Q_GETQUOTA:
1841 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
1842 NULL);
1843 break;
1844 default:
1845 rc = 0; /* let the kernel handle invalid cmds */
1846 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 }
1848 return rc;
1849}
1850
1851static int selinux_quota_on(struct dentry *dentry)
1852{
1853 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1854}
1855
1856static int selinux_syslog(int type)
1857{
1858 int rc;
1859
1860 rc = secondary_ops->syslog(type);
1861 if (rc)
1862 return rc;
1863
1864 switch (type) {
Eric Paris828dfe12008-04-17 13:17:49 -04001865 case 3: /* Read last kernel messages */
1866 case 10: /* Return size of the log buffer */
1867 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1868 break;
1869 case 6: /* Disable logging to console */
1870 case 7: /* Enable logging to console */
1871 case 8: /* Set level of messages printed to console */
1872 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1873 break;
1874 case 0: /* Close log */
1875 case 1: /* Open log */
1876 case 2: /* Read from log */
1877 case 4: /* Read/clear last kernel messages */
1878 case 5: /* Clear ring buffer */
1879 default:
1880 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1881 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 }
1883 return rc;
1884}
1885
1886/*
1887 * Check that a process has enough memory to allocate a new virtual
1888 * mapping. 0 means there is enough memory for the allocation to
1889 * succeed and -ENOMEM implies there is not.
1890 *
1891 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1892 * if the capability is granted, but __vm_enough_memory requires 1 if
1893 * the capability is granted.
1894 *
1895 * Do not audit the selinux permission check, as this is applied to all
1896 * processes that allocate mappings.
1897 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001898static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
1900 int rc, cap_sys_admin = 0;
1901 struct task_security_struct *tsec = current->security;
1902
1903 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1904 if (rc == 0)
1905 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04001906 SECCLASS_CAPABILITY,
1907 CAP_TO_MASK(CAP_SYS_ADMIN),
1908 0,
1909 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
1911 if (rc == 0)
1912 cap_sys_admin = 1;
1913
Alan Cox34b4e4a2007-08-22 14:01:28 -07001914 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915}
1916
Roland McGrath03563572008-03-26 15:46:39 -07001917/**
1918 * task_tracer_task - return the task that is tracing the given task
1919 * @task: task to consider
1920 *
1921 * Returns NULL if noone is tracing @task, or the &struct task_struct
1922 * pointer to its tracer.
1923 *
1924 * Must be called under rcu_read_lock().
1925 */
1926static struct task_struct *task_tracer_task(struct task_struct *task)
1927{
1928 if (task->ptrace & PT_PTRACED)
1929 return rcu_dereference(task->parent);
1930 return NULL;
1931}
1932
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933/* binprm security operations */
1934
1935static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1936{
1937 struct bprm_security_struct *bsec;
1938
James Morris89d155e2005-10-30 14:59:21 -08001939 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 if (!bsec)
1941 return -ENOMEM;
1942
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 bsec->sid = SECINITSID_UNLABELED;
1944 bsec->set = 0;
1945
1946 bprm->security = bsec;
1947 return 0;
1948}
1949
1950static int selinux_bprm_set_security(struct linux_binprm *bprm)
1951{
1952 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08001953 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 struct inode_security_struct *isec;
1955 struct bprm_security_struct *bsec;
1956 u32 newsid;
1957 struct avc_audit_data ad;
1958 int rc;
1959
1960 rc = secondary_ops->bprm_set_security(bprm);
1961 if (rc)
1962 return rc;
1963
1964 bsec = bprm->security;
1965
1966 if (bsec->set)
1967 return 0;
1968
1969 tsec = current->security;
1970 isec = inode->i_security;
1971
1972 /* Default to the current task SID. */
1973 bsec->sid = tsec->sid;
1974
Michael LeMay28eba5b2006-06-27 02:53:42 -07001975 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07001977 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07001978 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
1980 if (tsec->exec_sid) {
1981 newsid = tsec->exec_sid;
1982 /* Reset exec SID on execve. */
1983 tsec->exec_sid = 0;
1984 } else {
1985 /* Check for a default transition on this program. */
1986 rc = security_transition_sid(tsec->sid, isec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04001987 SECCLASS_PROCESS, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 if (rc)
1989 return rc;
1990 }
1991
1992 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001993 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Josef Sipek3d5ff522006-12-08 02:37:38 -08001995 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 newsid = tsec->sid;
1997
Eric Paris828dfe12008-04-17 13:17:49 -04001998 if (tsec->sid == newsid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 rc = avc_has_perm(tsec->sid, isec->sid,
2000 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2001 if (rc)
2002 return rc;
2003 } else {
2004 /* Check permissions for the transition. */
2005 rc = avc_has_perm(tsec->sid, newsid,
2006 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2007 if (rc)
2008 return rc;
2009
2010 rc = avc_has_perm(newsid, isec->sid,
2011 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2012 if (rc)
2013 return rc;
2014
2015 /* Clear any possibly unsafe personality bits on exec: */
2016 current->personality &= ~PER_CLEAR_ON_SETID;
2017
2018 /* Set the security field to the new SID. */
2019 bsec->sid = newsid;
2020 }
2021
2022 bsec->set = 1;
2023 return 0;
2024}
2025
Eric Paris828dfe12008-04-17 13:17:49 -04002026static int selinux_bprm_check_security(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027{
2028 return secondary_ops->bprm_check_security(bprm);
2029}
2030
2031
Eric Paris828dfe12008-04-17 13:17:49 -04002032static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033{
2034 struct task_security_struct *tsec = current->security;
2035 int atsecure = 0;
2036
2037 if (tsec->osid != tsec->sid) {
2038 /* Enable secure mode for SIDs transitions unless
2039 the noatsecure permission is granted between
2040 the two SIDs, i.e. ahp returns 0. */
2041 atsecure = avc_has_perm(tsec->osid, tsec->sid,
2042 SECCLASS_PROCESS,
2043 PROCESS__NOATSECURE, NULL);
2044 }
2045
2046 return (atsecure || secondary_ops->bprm_secureexec(bprm));
2047}
2048
2049static void selinux_bprm_free_security(struct linux_binprm *bprm)
2050{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07002051 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053}
2054
2055extern struct vfsmount *selinuxfs_mount;
2056extern struct dentry *selinux_null;
2057
2058/* Derived from fs/exec.c:flush_old_files. */
Eric Paris828dfe12008-04-17 13:17:49 -04002059static inline void flush_unauthorized_files(struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060{
2061 struct avc_audit_data ad;
2062 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002063 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002064 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002066 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002068 mutex_lock(&tty_mutex);
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002069 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 if (tty) {
2071 file_list_lock();
Eric Dumazet2f512012005-10-30 15:02:16 -08002072 file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 if (file) {
2074 /* Revalidate access to controlling tty.
2075 Use inode_has_perm on the tty inode directly rather
2076 than using file_has_perm, as this particular open
2077 file may belong to another process and we are only
2078 interested in the inode-based check here. */
Josef Sipek3d5ff522006-12-08 02:37:38 -08002079 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if (inode_has_perm(current, inode,
2081 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002082 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 }
2084 }
2085 file_list_unlock();
2086 }
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002087 mutex_unlock(&tty_mutex);
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002088 /* Reset controlling tty. */
2089 if (drop_tty)
2090 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
2092 /* Revalidate access to inherited open files. */
2093
Eric Paris828dfe12008-04-17 13:17:49 -04002094 AVC_AUDIT_DATA_INIT(&ad, FS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
2096 spin_lock(&files->file_lock);
2097 for (;;) {
2098 unsigned long set, i;
2099 int fd;
2100
2101 j++;
2102 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002103 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002104 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002106 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (!set)
2108 continue;
2109 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002110 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 if (set & 1) {
2112 file = fget(i);
2113 if (!file)
2114 continue;
2115 if (file_has_perm(current,
2116 file,
2117 file_to_av(file))) {
2118 sys_close(i);
2119 fd = get_unused_fd();
2120 if (fd != i) {
2121 if (fd >= 0)
2122 put_unused_fd(fd);
2123 fput(file);
2124 continue;
2125 }
2126 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002127 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 } else {
2129 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002130 if (IS_ERR(devnull)) {
2131 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 put_unused_fd(fd);
2133 fput(file);
2134 continue;
2135 }
2136 }
2137 fd_install(fd, devnull);
2138 }
2139 fput(file);
2140 }
2141 }
2142 spin_lock(&files->file_lock);
2143
2144 }
2145 spin_unlock(&files->file_lock);
2146}
2147
2148static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2149{
2150 struct task_security_struct *tsec;
2151 struct bprm_security_struct *bsec;
2152 u32 sid;
2153 int rc;
2154
2155 secondary_ops->bprm_apply_creds(bprm, unsafe);
2156
2157 tsec = current->security;
2158
2159 bsec = bprm->security;
2160 sid = bsec->sid;
2161
2162 tsec->osid = tsec->sid;
2163 bsec->unsafe = 0;
2164 if (tsec->sid != sid) {
2165 /* Check for shared state. If not ok, leave SID
2166 unchanged and kill. */
2167 if (unsafe & LSM_UNSAFE_SHARE) {
2168 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2169 PROCESS__SHARE, NULL);
2170 if (rc) {
2171 bsec->unsafe = 1;
2172 return;
2173 }
2174 }
2175
2176 /* Check for ptracing, and update the task SID if ok.
2177 Otherwise, leave SID unchanged and kill. */
2178 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Roland McGrath03563572008-03-26 15:46:39 -07002179 struct task_struct *tracer;
2180 struct task_security_struct *sec;
2181 u32 ptsid = 0;
2182
2183 rcu_read_lock();
2184 tracer = task_tracer_task(current);
2185 if (likely(tracer != NULL)) {
2186 sec = tracer->security;
2187 ptsid = sec->sid;
2188 }
2189 rcu_read_unlock();
2190
2191 if (ptsid != 0) {
2192 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
2193 PROCESS__PTRACE, NULL);
2194 if (rc) {
2195 bsec->unsafe = 1;
2196 return;
2197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 }
2199 }
2200 tsec->sid = sid;
2201 }
2202}
2203
2204/*
2205 * called after apply_creds without the task lock held
2206 */
2207static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2208{
2209 struct task_security_struct *tsec;
2210 struct rlimit *rlim, *initrlim;
2211 struct itimerval itimer;
2212 struct bprm_security_struct *bsec;
2213 int rc, i;
2214
2215 tsec = current->security;
2216 bsec = bprm->security;
2217
2218 if (bsec->unsafe) {
2219 force_sig_specific(SIGKILL, current);
2220 return;
2221 }
2222 if (tsec->osid == tsec->sid)
2223 return;
2224
2225 /* Close files for which the new task SID is not authorized. */
2226 flush_unauthorized_files(current->files);
2227
2228 /* Check whether the new SID can inherit signal state
2229 from the old SID. If not, clear itimers to avoid
2230 subsequent signal generation and flush and unblock
2231 signals. This must occur _after_ the task SID has
2232 been updated so that any kill done after the flush
2233 will be checked against the new SID. */
2234 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2235 PROCESS__SIGINH, NULL);
2236 if (rc) {
2237 memset(&itimer, 0, sizeof itimer);
2238 for (i = 0; i < 3; i++)
2239 do_setitimer(i, &itimer, NULL);
2240 flush_signals(current);
2241 spin_lock_irq(&current->sighand->siglock);
2242 flush_signal_handlers(current, 1);
2243 sigemptyset(&current->blocked);
2244 recalc_sigpending();
2245 spin_unlock_irq(&current->sighand->siglock);
2246 }
2247
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002248 /* Always clear parent death signal on SID transitions. */
2249 current->pdeath_signal = 0;
2250
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 /* Check whether the new SID can inherit resource limits
2252 from the old SID. If not, reset all soft limits to
2253 the lower of the current task's hard limit and the init
2254 task's soft limit. Note that the setting of hard limits
2255 (even to lower them) can be controlled by the setrlimit
2256 check. The inclusion of the init task's soft limit into
2257 the computation is to avoid resetting soft limits higher
2258 than the default soft limit for cases where the default
2259 is lower than the hard limit, e.g. RLIMIT_CORE or
2260 RLIMIT_STACK.*/
2261 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2262 PROCESS__RLIMITINH, NULL);
2263 if (rc) {
2264 for (i = 0; i < RLIM_NLIMITS; i++) {
2265 rlim = current->signal->rlim + i;
2266 initrlim = init_task.signal->rlim+i;
Eric Paris828dfe12008-04-17 13:17:49 -04002267 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 }
2269 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
2270 /*
2271 * This will cause RLIMIT_CPU calculations
2272 * to be refigured.
2273 */
2274 current->it_prof_expires = jiffies_to_cputime(1);
2275 }
2276 }
2277
2278 /* Wake up the parent if it is waiting so that it can
2279 recheck wait permission to the new task SID. */
2280 wake_up_interruptible(&current->parent->signal->wait_chldexit);
2281}
2282
2283/* superblock security operations */
2284
2285static int selinux_sb_alloc_security(struct super_block *sb)
2286{
2287 return superblock_alloc_security(sb);
2288}
2289
2290static void selinux_sb_free_security(struct super_block *sb)
2291{
2292 superblock_free_security(sb);
2293}
2294
2295static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2296{
2297 if (plen > olen)
2298 return 0;
2299
2300 return !memcmp(prefix, option, plen);
2301}
2302
2303static inline int selinux_option(char *option, int len)
2304{
Eric Paris832cbd92008-04-01 13:24:09 -04002305 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2306 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2307 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2308 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309}
2310
2311static inline void take_option(char **to, char *from, int *first, int len)
2312{
2313 if (!*first) {
2314 **to = ',';
2315 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002316 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 *first = 0;
2318 memcpy(*to, from, len);
2319 *to += len;
2320}
2321
Eric Paris828dfe12008-04-17 13:17:49 -04002322static inline void take_selinux_option(char **to, char *from, int *first,
2323 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002324{
2325 int current_size = 0;
2326
2327 if (!*first) {
2328 **to = '|';
2329 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002330 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002331 *first = 0;
2332
2333 while (current_size < len) {
2334 if (*from != '"') {
2335 **to = *from;
2336 *to += 1;
2337 }
2338 from += 1;
2339 current_size += 1;
2340 }
2341}
2342
Eric Parise0007522008-03-05 10:31:54 -05002343static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344{
2345 int fnosec, fsec, rc = 0;
2346 char *in_save, *in_curr, *in_end;
2347 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002348 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
2350 in_curr = orig;
2351 sec_curr = copy;
2352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2354 if (!nosec) {
2355 rc = -ENOMEM;
2356 goto out;
2357 }
2358
2359 nosec_save = nosec;
2360 fnosec = fsec = 1;
2361 in_save = in_end = orig;
2362
2363 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002364 if (*in_end == '"')
2365 open_quote = !open_quote;
2366 if ((*in_end == ',' && open_quote == 0) ||
2367 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 int len = in_end - in_curr;
2369
2370 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002371 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 else
2373 take_option(&nosec, in_curr, &fnosec, len);
2374
2375 in_curr = in_end + 1;
2376 }
2377 } while (*in_end++);
2378
Eric Paris6931dfc2005-06-30 02:58:51 -07002379 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002380 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381out:
2382 return rc;
2383}
2384
2385static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2386{
2387 struct avc_audit_data ad;
2388 int rc;
2389
2390 rc = superblock_doinit(sb, data);
2391 if (rc)
2392 return rc;
2393
Eric Paris828dfe12008-04-17 13:17:49 -04002394 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002395 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2397}
2398
David Howells726c3342006-06-23 02:02:58 -07002399static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
2401 struct avc_audit_data ad;
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 = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002405 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406}
2407
Eric Paris828dfe12008-04-17 13:17:49 -04002408static int selinux_mount(char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002409 struct path *path,
Eric Paris828dfe12008-04-17 13:17:49 -04002410 char *type,
2411 unsigned long flags,
2412 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413{
2414 int rc;
2415
Al Virob5266eb2008-03-22 17:48:24 -04002416 rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 if (rc)
2418 return rc;
2419
2420 if (flags & MS_REMOUNT)
Al Virob5266eb2008-03-22 17:48:24 -04002421 return superblock_has_perm(current, path->mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002422 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 else
Al Virob5266eb2008-03-22 17:48:24 -04002424 return dentry_has_perm(current, path->mnt, path->dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002425 FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426}
2427
2428static int selinux_umount(struct vfsmount *mnt, int flags)
2429{
2430 int rc;
2431
2432 rc = secondary_ops->sb_umount(mnt, flags);
2433 if (rc)
2434 return rc;
2435
Eric Paris828dfe12008-04-17 13:17:49 -04002436 return superblock_has_perm(current, mnt->mnt_sb,
2437 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438}
2439
2440/* inode security operations */
2441
2442static int selinux_inode_alloc_security(struct inode *inode)
2443{
2444 return inode_alloc_security(inode);
2445}
2446
2447static void selinux_inode_free_security(struct inode *inode)
2448{
2449 inode_free_security(inode);
2450}
2451
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002452static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2453 char **name, void **value,
2454 size_t *len)
2455{
2456 struct task_security_struct *tsec;
2457 struct inode_security_struct *dsec;
2458 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002459 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002460 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002461 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002462
2463 tsec = current->security;
2464 dsec = dir->i_security;
2465 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002466
2467 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2468 newsid = tsec->create_sid;
2469 } else {
2470 rc = security_transition_sid(tsec->sid, dsec->sid,
2471 inode_mode_to_security_class(inode->i_mode),
2472 &newsid);
2473 if (rc) {
2474 printk(KERN_WARNING "%s: "
2475 "security_transition_sid failed, rc=%d (dev=%s "
2476 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002477 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002478 -rc, inode->i_sb->s_id, inode->i_ino);
2479 return rc;
2480 }
2481 }
2482
Eric Paris296fddf2006-09-25 23:32:00 -07002483 /* Possibly defer initialization to selinux_complete_init. */
2484 if (sbsec->initialized) {
2485 struct inode_security_struct *isec = inode->i_security;
2486 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2487 isec->sid = newsid;
2488 isec->initialized = 1;
2489 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002490
Stephen Smalley8aad3872006-03-22 00:09:13 -08002491 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002492 return -EOPNOTSUPP;
2493
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002494 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002495 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002496 if (!namep)
2497 return -ENOMEM;
2498 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002499 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002500
2501 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002502 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002503 if (rc) {
2504 kfree(namep);
2505 return rc;
2506 }
2507 *value = context;
2508 *len = clen;
2509 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002510
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002511 return 0;
2512}
2513
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2515{
2516 return may_create(dir, dentry, SECCLASS_FILE);
2517}
2518
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2520{
2521 int rc;
2522
Eric Paris828dfe12008-04-17 13:17:49 -04002523 rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 if (rc)
2525 return rc;
2526 return may_link(dir, old_dentry, MAY_LINK);
2527}
2528
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2530{
2531 int rc;
2532
2533 rc = secondary_ops->inode_unlink(dir, dentry);
2534 if (rc)
2535 return rc;
2536 return may_link(dir, dentry, MAY_UNLINK);
2537}
2538
2539static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2540{
2541 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2542}
2543
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2545{
2546 return may_create(dir, dentry, SECCLASS_DIR);
2547}
2548
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2550{
2551 return may_link(dir, dentry, MAY_RMDIR);
2552}
2553
2554static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2555{
2556 int rc;
2557
2558 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2559 if (rc)
2560 return rc;
2561
2562 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2563}
2564
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002566 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567{
2568 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2569}
2570
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571static int selinux_inode_readlink(struct dentry *dentry)
2572{
2573 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2574}
2575
2576static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2577{
2578 int rc;
2579
Eric Paris828dfe12008-04-17 13:17:49 -04002580 rc = secondary_ops->inode_follow_link(dentry, nameidata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 if (rc)
2582 return rc;
2583 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2584}
2585
2586static int selinux_inode_permission(struct inode *inode, int mask,
2587 struct nameidata *nd)
2588{
2589 int rc;
2590
2591 rc = secondary_ops->inode_permission(inode, mask, nd);
2592 if (rc)
2593 return rc;
2594
2595 if (!mask) {
2596 /* No permission to check. Existence test. */
2597 return 0;
2598 }
2599
2600 return inode_has_perm(current, inode,
Eric Parisb0c636b2008-02-28 12:58:40 -05002601 open_file_mask_to_av(inode->i_mode, mask), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602}
2603
2604static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2605{
2606 int rc;
2607
2608 rc = secondary_ops->inode_setattr(dentry, iattr);
2609 if (rc)
2610 return rc;
2611
2612 if (iattr->ia_valid & ATTR_FORCE)
2613 return 0;
2614
2615 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2616 ATTR_ATIME_SET | ATTR_MTIME_SET))
2617 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2618
2619 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2620}
2621
2622static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2623{
2624 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2625}
2626
David Howells8f0cfa52008-04-29 00:59:41 -07002627static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002628{
2629 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2630 sizeof XATTR_SECURITY_PREFIX - 1)) {
2631 if (!strcmp(name, XATTR_NAME_CAPS)) {
2632 if (!capable(CAP_SETFCAP))
2633 return -EPERM;
2634 } else if (!capable(CAP_SYS_ADMIN)) {
2635 /* A different attribute in the security namespace.
2636 Restrict to administrator. */
2637 return -EPERM;
2638 }
2639 }
2640
2641 /* Not an attribute we recognize, so just check the
2642 ordinary setattr permission. */
2643 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2644}
2645
David Howells8f0cfa52008-04-29 00:59:41 -07002646static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2647 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648{
2649 struct task_security_struct *tsec = current->security;
2650 struct inode *inode = dentry->d_inode;
2651 struct inode_security_struct *isec = inode->i_security;
2652 struct superblock_security_struct *sbsec;
2653 struct avc_audit_data ad;
2654 u32 newsid;
2655 int rc = 0;
2656
Serge E. Hallynb5376772007-10-16 23:31:36 -07002657 if (strcmp(name, XATTR_NAME_SELINUX))
2658 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
2660 sbsec = inode->i_sb->s_security;
2661 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2662 return -EOPNOTSUPP;
2663
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302664 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 return -EPERM;
2666
Eric Paris828dfe12008-04-17 13:17:49 -04002667 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002668 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
2670 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2671 FILE__RELABELFROM, &ad);
2672 if (rc)
2673 return rc;
2674
2675 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002676 if (rc == -EINVAL) {
2677 if (!capable(CAP_MAC_ADMIN))
2678 return rc;
2679 rc = security_context_to_sid_force(value, size, &newsid);
2680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 if (rc)
2682 return rc;
2683
2684 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2685 FILE__RELABELTO, &ad);
2686 if (rc)
2687 return rc;
2688
2689 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002690 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if (rc)
2692 return rc;
2693
2694 return avc_has_perm(newsid,
2695 sbsec->sid,
2696 SECCLASS_FILESYSTEM,
2697 FILESYSTEM__ASSOCIATE,
2698 &ad);
2699}
2700
David Howells8f0cfa52008-04-29 00:59:41 -07002701static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002702 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002703 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704{
2705 struct inode *inode = dentry->d_inode;
2706 struct inode_security_struct *isec = inode->i_security;
2707 u32 newsid;
2708 int rc;
2709
2710 if (strcmp(name, XATTR_NAME_SELINUX)) {
2711 /* Not an attribute we recognize, so nothing to do. */
2712 return;
2713 }
2714
Stephen Smalley12b29f32008-05-07 13:03:20 -04002715 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002717 printk(KERN_ERR "SELinux: unable to map context to SID"
2718 "for (%s, %lu), rc=%d\n",
2719 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 return;
2721 }
2722
2723 isec->sid = newsid;
2724 return;
2725}
2726
David Howells8f0cfa52008-04-29 00:59:41 -07002727static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2730}
2731
Eric Paris828dfe12008-04-17 13:17:49 -04002732static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
2734 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2735}
2736
David Howells8f0cfa52008-04-29 00:59:41 -07002737static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002739 if (strcmp(name, XATTR_NAME_SELINUX))
2740 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741
2742 /* No one is allowed to remove a SELinux security label.
2743 You can change the label, but all data must be labeled. */
2744 return -EACCES;
2745}
2746
James Morrisd381d8a2005-10-30 14:59:22 -08002747/*
2748 * Copy the in-core inode security context value to the user. If the
2749 * getxattr() prior to this succeeded, check to see if we need to
2750 * canonicalize the value to be finally returned to the user.
2751 *
2752 * Permission check is handled by selinux_inode_getxattr hook.
2753 */
David P. Quigley42492592008-02-04 22:29:39 -08002754static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755{
David P. Quigley42492592008-02-04 22:29:39 -08002756 u32 size;
2757 int error;
2758 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002761 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2762 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
David P. Quigley42492592008-02-04 22:29:39 -08002764 error = security_sid_to_context(isec->sid, &context, &size);
2765 if (error)
2766 return error;
2767 error = size;
2768 if (alloc) {
2769 *buffer = context;
2770 goto out_nofree;
2771 }
2772 kfree(context);
2773out_nofree:
2774 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775}
2776
2777static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002778 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779{
2780 struct inode_security_struct *isec = inode->i_security;
2781 u32 newsid;
2782 int rc;
2783
2784 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2785 return -EOPNOTSUPP;
2786
2787 if (!value || !size)
2788 return -EACCES;
2789
Eric Paris828dfe12008-04-17 13:17:49 -04002790 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 if (rc)
2792 return rc;
2793
2794 isec->sid = newsid;
2795 return 0;
2796}
2797
2798static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2799{
2800 const int len = sizeof(XATTR_NAME_SELINUX);
2801 if (buffer && len <= buffer_size)
2802 memcpy(buffer, XATTR_NAME_SELINUX, len);
2803 return len;
2804}
2805
Serge E. Hallynb5376772007-10-16 23:31:36 -07002806static int selinux_inode_need_killpriv(struct dentry *dentry)
2807{
2808 return secondary_ops->inode_need_killpriv(dentry);
2809}
2810
2811static int selinux_inode_killpriv(struct dentry *dentry)
2812{
2813 return secondary_ops->inode_killpriv(dentry);
2814}
2815
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02002816static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2817{
2818 struct inode_security_struct *isec = inode->i_security;
2819 *secid = isec->sid;
2820}
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822/* file security operations */
2823
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002824static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002826 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002827 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828
2829 if (!mask) {
2830 /* No permission to check. Existence test. */
2831 return 0;
2832 }
2833
2834 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2835 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2836 mask |= MAY_APPEND;
2837
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002838 rc = file_has_perm(current, file,
2839 file_mask_to_av(inode->i_mode, mask));
2840 if (rc)
2841 return rc;
2842
2843 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844}
2845
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002846static int selinux_file_permission(struct file *file, int mask)
2847{
2848 struct inode *inode = file->f_path.dentry->d_inode;
2849 struct task_security_struct *tsec = current->security;
2850 struct file_security_struct *fsec = file->f_security;
2851 struct inode_security_struct *isec = inode->i_security;
2852
2853 if (!mask) {
2854 /* No permission to check. Existence test. */
2855 return 0;
2856 }
2857
2858 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2859 && fsec->pseqno == avc_policy_seqno())
2860 return selinux_netlbl_inode_permission(inode, mask);
2861
2862 return selinux_revalidate_file_permission(file, mask);
2863}
2864
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865static int selinux_file_alloc_security(struct file *file)
2866{
2867 return file_alloc_security(file);
2868}
2869
2870static void selinux_file_free_security(struct file *file)
2871{
2872 file_free_security(file);
2873}
2874
2875static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2876 unsigned long arg)
2877{
2878 int error = 0;
2879
2880 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04002881 case FIONREAD:
2882 /* fall through */
2883 case FIBMAP:
2884 /* fall through */
2885 case FIGETBSZ:
2886 /* fall through */
2887 case EXT2_IOC_GETFLAGS:
2888 /* fall through */
2889 case EXT2_IOC_GETVERSION:
2890 error = file_has_perm(current, file, FILE__GETATTR);
2891 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892
Eric Paris828dfe12008-04-17 13:17:49 -04002893 case EXT2_IOC_SETFLAGS:
2894 /* fall through */
2895 case EXT2_IOC_SETVERSION:
2896 error = file_has_perm(current, file, FILE__SETATTR);
2897 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898
Eric Paris828dfe12008-04-17 13:17:49 -04002899 /* sys_ioctl() checks */
2900 case FIONBIO:
2901 /* fall through */
2902 case FIOASYNC:
2903 error = file_has_perm(current, file, 0);
2904 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
Eric Paris828dfe12008-04-17 13:17:49 -04002906 case KDSKBENT:
2907 case KDSKBSENT:
2908 error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
2909 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Eric Paris828dfe12008-04-17 13:17:49 -04002911 /* default case assumes that the command will go
2912 * to the file's ioctl() function.
2913 */
2914 default:
2915 error = file_has_perm(current, file, FILE__IOCTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 }
2917 return error;
2918}
2919
2920static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2921{
2922#ifndef CONFIG_PPC32
2923 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2924 /*
2925 * We are making executable an anonymous mapping or a
2926 * private file mapping that will also be writable.
2927 * This has an additional check.
2928 */
2929 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2930 if (rc)
2931 return rc;
2932 }
2933#endif
2934
2935 if (file) {
2936 /* read access is always possible with a mapping */
2937 u32 av = FILE__READ;
2938
2939 /* write access only matters if the mapping is shared */
2940 if (shared && (prot & PROT_WRITE))
2941 av |= FILE__WRITE;
2942
2943 if (prot & PROT_EXEC)
2944 av |= FILE__EXECUTE;
2945
2946 return file_has_perm(current, file, av);
2947 }
2948 return 0;
2949}
2950
2951static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002952 unsigned long prot, unsigned long flags,
2953 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
Eric Parised032182007-06-28 15:55:21 -04002955 int rc = 0;
Eric Paris828dfe12008-04-17 13:17:49 -04002956 u32 sid = ((struct task_security_struct *)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957
Eric Parised032182007-06-28 15:55:21 -04002958 if (addr < mmap_min_addr)
2959 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2960 MEMPROTECT__MMAP_ZERO, NULL);
2961 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 return rc;
2963
2964 if (selinux_checkreqprot)
2965 prot = reqprot;
2966
2967 return file_map_prot_check(file, prot,
2968 (flags & MAP_TYPE) == MAP_SHARED);
2969}
2970
2971static int selinux_file_mprotect(struct vm_area_struct *vma,
2972 unsigned long reqprot,
2973 unsigned long prot)
2974{
2975 int rc;
2976
2977 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2978 if (rc)
2979 return rc;
2980
2981 if (selinux_checkreqprot)
2982 prot = reqprot;
2983
2984#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08002985 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
2986 rc = 0;
2987 if (vma->vm_start >= vma->vm_mm->start_brk &&
2988 vma->vm_end <= vma->vm_mm->brk) {
2989 rc = task_has_perm(current, current,
2990 PROCESS__EXECHEAP);
2991 } else if (!vma->vm_file &&
2992 vma->vm_start <= vma->vm_mm->start_stack &&
2993 vma->vm_end >= vma->vm_mm->start_stack) {
2994 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
2995 } else if (vma->vm_file && vma->anon_vma) {
2996 /*
2997 * We are making executable a file mapping that has
2998 * had some COW done. Since pages might have been
2999 * written, check ability to execute the possibly
3000 * modified content. This typically should only
3001 * occur for text relocations.
3002 */
3003 rc = file_has_perm(current, vma->vm_file,
3004 FILE__EXECMOD);
3005 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003006 if (rc)
3007 return rc;
3008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009#endif
3010
3011 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3012}
3013
3014static int selinux_file_lock(struct file *file, unsigned int cmd)
3015{
3016 return file_has_perm(current, file, FILE__LOCK);
3017}
3018
3019static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3020 unsigned long arg)
3021{
3022 int err = 0;
3023
3024 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003025 case F_SETFL:
3026 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3027 err = -EINVAL;
3028 break;
3029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Eric Paris828dfe12008-04-17 13:17:49 -04003031 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
3032 err = file_has_perm(current, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003034 }
3035 /* fall through */
3036 case F_SETOWN:
3037 case F_SETSIG:
3038 case F_GETFL:
3039 case F_GETOWN:
3040 case F_GETSIG:
3041 /* Just check FD__USE permission */
3042 err = file_has_perm(current, file, 0);
3043 break;
3044 case F_GETLK:
3045 case F_SETLK:
3046 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003048 case F_GETLK64:
3049 case F_SETLK64:
3050 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003052 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3053 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003055 }
3056 err = file_has_perm(current, file, FILE__LOCK);
3057 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 }
3059
3060 return err;
3061}
3062
3063static int selinux_file_set_fowner(struct file *file)
3064{
3065 struct task_security_struct *tsec;
3066 struct file_security_struct *fsec;
3067
3068 tsec = current->security;
3069 fsec = file->f_security;
3070 fsec->fown_sid = tsec->sid;
3071
3072 return 0;
3073}
3074
3075static int selinux_file_send_sigiotask(struct task_struct *tsk,
3076 struct fown_struct *fown, int signum)
3077{
Eric Paris828dfe12008-04-17 13:17:49 -04003078 struct file *file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 u32 perm;
3080 struct task_security_struct *tsec;
3081 struct file_security_struct *fsec;
3082
3083 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003084 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
3086 tsec = tsk->security;
3087 fsec = file->f_security;
3088
3089 if (!signum)
3090 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3091 else
3092 perm = signal_to_av(signum);
3093
3094 return avc_has_perm(fsec->fown_sid, tsec->sid,
3095 SECCLASS_PROCESS, perm, NULL);
3096}
3097
3098static int selinux_file_receive(struct file *file)
3099{
3100 return file_has_perm(current, file, file_to_av(file));
3101}
3102
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003103static int selinux_dentry_open(struct file *file)
3104{
3105 struct file_security_struct *fsec;
3106 struct inode *inode;
3107 struct inode_security_struct *isec;
3108 inode = file->f_path.dentry->d_inode;
3109 fsec = file->f_security;
3110 isec = inode->i_security;
3111 /*
3112 * Save inode label and policy sequence number
3113 * at open-time so that selinux_file_permission
3114 * can determine whether revalidation is necessary.
3115 * Task label is already saved in the file security
3116 * struct as its SID.
3117 */
3118 fsec->isid = isec->sid;
3119 fsec->pseqno = avc_policy_seqno();
3120 /*
3121 * Since the inode label or policy seqno may have changed
3122 * between the selinux_inode_permission check and the saving
3123 * of state above, recheck that access is still permitted.
3124 * Otherwise, access might never be revalidated against the
3125 * new inode label or new policy.
3126 * This check is not redundant - do not remove.
3127 */
3128 return inode_has_perm(current, inode, file_to_av(file), NULL);
3129}
3130
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131/* task security operations */
3132
3133static int selinux_task_create(unsigned long clone_flags)
3134{
3135 int rc;
3136
3137 rc = secondary_ops->task_create(clone_flags);
3138 if (rc)
3139 return rc;
3140
3141 return task_has_perm(current, current, PROCESS__FORK);
3142}
3143
3144static int selinux_task_alloc_security(struct task_struct *tsk)
3145{
3146 struct task_security_struct *tsec1, *tsec2;
3147 int rc;
3148
3149 tsec1 = current->security;
3150
3151 rc = task_alloc_security(tsk);
3152 if (rc)
3153 return rc;
3154 tsec2 = tsk->security;
3155
3156 tsec2->osid = tsec1->osid;
3157 tsec2->sid = tsec1->sid;
3158
Michael LeMay28eba5b2006-06-27 02:53:42 -07003159 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 tsec2->exec_sid = tsec1->exec_sid;
3161 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003162 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003163 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 return 0;
3166}
3167
3168static void selinux_task_free_security(struct task_struct *tsk)
3169{
3170 task_free_security(tsk);
3171}
3172
3173static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3174{
3175 /* Since setuid only affects the current process, and
3176 since the SELinux controls are not based on the Linux
3177 identity attributes, SELinux does not need to control
3178 this operation. However, SELinux does control the use
3179 of the CAP_SETUID and CAP_SETGID capabilities using the
3180 capable hook. */
3181 return 0;
3182}
3183
3184static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3185{
Eric Paris828dfe12008-04-17 13:17:49 -04003186 return secondary_ops->task_post_setuid(id0, id1, id2, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187}
3188
3189static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3190{
3191 /* See the comment for setuid above. */
3192 return 0;
3193}
3194
3195static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3196{
3197 return task_has_perm(current, p, PROCESS__SETPGID);
3198}
3199
3200static int selinux_task_getpgid(struct task_struct *p)
3201{
3202 return task_has_perm(current, p, PROCESS__GETPGID);
3203}
3204
3205static int selinux_task_getsid(struct task_struct *p)
3206{
3207 return task_has_perm(current, p, PROCESS__GETSESSION);
3208}
3209
David Quigleyf9008e42006-06-30 01:55:46 -07003210static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3211{
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003212 struct task_security_struct *tsec = p->security;
3213 *secid = tsec->sid;
David Quigleyf9008e42006-06-30 01:55:46 -07003214}
3215
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216static int selinux_task_setgroups(struct group_info *group_info)
3217{
3218 /* See the comment for setuid above. */
3219 return 0;
3220}
3221
3222static int selinux_task_setnice(struct task_struct *p, int nice)
3223{
3224 int rc;
3225
3226 rc = secondary_ops->task_setnice(p, nice);
3227 if (rc)
3228 return rc;
3229
Eric Paris828dfe12008-04-17 13:17:49 -04003230 return task_has_perm(current, p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231}
3232
James Morris03e68062006-06-23 02:03:58 -07003233static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3234{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003235 int rc;
3236
3237 rc = secondary_ops->task_setioprio(p, ioprio);
3238 if (rc)
3239 return rc;
3240
James Morris03e68062006-06-23 02:03:58 -07003241 return task_has_perm(current, p, PROCESS__SETSCHED);
3242}
3243
David Quigleya1836a42006-06-30 01:55:49 -07003244static int selinux_task_getioprio(struct task_struct *p)
3245{
3246 return task_has_perm(current, p, PROCESS__GETSCHED);
3247}
3248
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3250{
3251 struct rlimit *old_rlim = current->signal->rlim + resource;
3252 int rc;
3253
3254 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3255 if (rc)
3256 return rc;
3257
3258 /* Control the ability to change the hard limit (whether
3259 lowering or raising it), so that the hard limit can
3260 later be used as a safe reset point for the soft limit
3261 upon context transitions. See selinux_bprm_apply_creds. */
3262 if (old_rlim->rlim_max != new_rlim->rlim_max)
3263 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3264
3265 return 0;
3266}
3267
3268static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3269{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003270 int rc;
3271
3272 rc = secondary_ops->task_setscheduler(p, policy, lp);
3273 if (rc)
3274 return rc;
3275
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 return task_has_perm(current, p, PROCESS__SETSCHED);
3277}
3278
3279static int selinux_task_getscheduler(struct task_struct *p)
3280{
3281 return task_has_perm(current, p, PROCESS__GETSCHED);
3282}
3283
David Quigley35601542006-06-23 02:04:01 -07003284static int selinux_task_movememory(struct task_struct *p)
3285{
3286 return task_has_perm(current, p, PROCESS__SETSCHED);
3287}
3288
David Quigleyf9008e42006-06-30 01:55:46 -07003289static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3290 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291{
3292 u32 perm;
3293 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003294 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295
David Quigleyf9008e42006-06-30 01:55:46 -07003296 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 if (rc)
3298 return rc;
3299
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 if (!sig)
3301 perm = PROCESS__SIGNULL; /* null signal; existence test */
3302 else
3303 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003304 tsec = p->security;
3305 if (secid)
3306 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3307 else
3308 rc = task_has_perm(current, p, perm);
3309 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310}
3311
3312static int selinux_task_prctl(int option,
3313 unsigned long arg2,
3314 unsigned long arg3,
3315 unsigned long arg4,
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003316 unsigned long arg5,
3317 long *rc_p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318{
3319 /* The current prctl operations do not appear to require
3320 any SELinux controls since they merely observe or modify
3321 the state of the current process. */
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003322 return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323}
3324
3325static int selinux_task_wait(struct task_struct *p)
3326{
Eric Paris8a535142007-10-22 16:10:31 -04003327 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328}
3329
3330static void selinux_task_reparent_to_init(struct task_struct *p)
3331{
Eric Paris828dfe12008-04-17 13:17:49 -04003332 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
3334 secondary_ops->task_reparent_to_init(p);
3335
3336 tsec = p->security;
3337 tsec->osid = tsec->sid;
3338 tsec->sid = SECINITSID_KERNEL;
3339 return;
3340}
3341
3342static void selinux_task_to_inode(struct task_struct *p,
3343 struct inode *inode)
3344{
3345 struct task_security_struct *tsec = p->security;
3346 struct inode_security_struct *isec = inode->i_security;
3347
3348 isec->sid = tsec->sid;
3349 isec->initialized = 1;
3350 return;
3351}
3352
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003354static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3355 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356{
3357 int offset, ihlen, ret = -EINVAL;
3358 struct iphdr _iph, *ih;
3359
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003360 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3362 if (ih == NULL)
3363 goto out;
3364
3365 ihlen = ih->ihl * 4;
3366 if (ihlen < sizeof(_iph))
3367 goto out;
3368
3369 ad->u.net.v4info.saddr = ih->saddr;
3370 ad->u.net.v4info.daddr = ih->daddr;
3371 ret = 0;
3372
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003373 if (proto)
3374 *proto = ih->protocol;
3375
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003377 case IPPROTO_TCP: {
3378 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Eric Paris828dfe12008-04-17 13:17:49 -04003380 if (ntohs(ih->frag_off) & IP_OFFSET)
3381 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382
3383 offset += ihlen;
3384 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3385 if (th == NULL)
3386 break;
3387
3388 ad->u.net.sport = th->source;
3389 ad->u.net.dport = th->dest;
3390 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
Eric Paris828dfe12008-04-17 13:17:49 -04003393 case IPPROTO_UDP: {
3394 struct udphdr _udph, *uh;
3395
3396 if (ntohs(ih->frag_off) & IP_OFFSET)
3397 break;
3398
3399 offset += ihlen;
3400 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3401 if (uh == NULL)
3402 break;
3403
3404 ad->u.net.sport = uh->source;
3405 ad->u.net.dport = uh->dest;
3406 break;
3407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
James Morris2ee92d42006-11-13 16:09:01 -08003409 case IPPROTO_DCCP: {
3410 struct dccp_hdr _dccph, *dh;
3411
3412 if (ntohs(ih->frag_off) & IP_OFFSET)
3413 break;
3414
3415 offset += ihlen;
3416 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3417 if (dh == NULL)
3418 break;
3419
3420 ad->u.net.sport = dh->dccph_sport;
3421 ad->u.net.dport = dh->dccph_dport;
3422 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003423 }
James Morris2ee92d42006-11-13 16:09:01 -08003424
Eric Paris828dfe12008-04-17 13:17:49 -04003425 default:
3426 break;
3427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428out:
3429 return ret;
3430}
3431
3432#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3433
3434/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003435static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3436 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437{
3438 u8 nexthdr;
3439 int ret = -EINVAL, offset;
3440 struct ipv6hdr _ipv6h, *ip6;
3441
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003442 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3444 if (ip6 == NULL)
3445 goto out;
3446
3447 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3448 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3449 ret = 0;
3450
3451 nexthdr = ip6->nexthdr;
3452 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003453 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 if (offset < 0)
3455 goto out;
3456
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003457 if (proto)
3458 *proto = nexthdr;
3459
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 switch (nexthdr) {
3461 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003462 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463
3464 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3465 if (th == NULL)
3466 break;
3467
3468 ad->u.net.sport = th->source;
3469 ad->u.net.dport = th->dest;
3470 break;
3471 }
3472
3473 case IPPROTO_UDP: {
3474 struct udphdr _udph, *uh;
3475
3476 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3477 if (uh == NULL)
3478 break;
3479
3480 ad->u.net.sport = uh->source;
3481 ad->u.net.dport = uh->dest;
3482 break;
3483 }
3484
James Morris2ee92d42006-11-13 16:09:01 -08003485 case IPPROTO_DCCP: {
3486 struct dccp_hdr _dccph, *dh;
3487
3488 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3489 if (dh == NULL)
3490 break;
3491
3492 ad->u.net.sport = dh->dccph_sport;
3493 ad->u.net.dport = dh->dccph_dport;
3494 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003495 }
James Morris2ee92d42006-11-13 16:09:01 -08003496
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 /* includes fragments */
3498 default:
3499 break;
3500 }
3501out:
3502 return ret;
3503}
3504
3505#endif /* IPV6 */
3506
3507static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
Paul Moore224dfbd2008-01-29 08:38:13 -05003508 char **addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509{
3510 int ret = 0;
3511
3512 switch (ad->u.net.family) {
3513 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003514 ret = selinux_parse_skb_ipv4(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 if (ret || !addrp)
3516 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3518 &ad->u.net.v4info.daddr);
3519 break;
3520
3521#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3522 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003523 ret = selinux_parse_skb_ipv6(skb, ad, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 if (ret || !addrp)
3525 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3527 &ad->u.net.v6info.daddr);
3528 break;
3529#endif /* IPV6 */
3530 default:
3531 break;
3532 }
3533
Paul Moore71f1cb02008-01-29 08:51:16 -05003534 if (unlikely(ret))
3535 printk(KERN_WARNING
3536 "SELinux: failure in selinux_parse_skb(),"
3537 " unable to parse packet\n");
3538
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 return ret;
3540}
3541
Paul Moore4f6a9932007-03-01 14:35:22 -05003542/**
Paul Moore220deb92008-01-29 08:38:23 -05003543 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003544 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003545 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003546 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003547 *
3548 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003549 * Check the various different forms of network peer labeling and determine
3550 * the peer label/SID for the packet; most of the magic actually occurs in
3551 * the security server function security_net_peersid_cmp(). The function
3552 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3553 * or -EACCES if @sid is invalid due to inconsistencies with the different
3554 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003555 *
3556 */
Paul Moore220deb92008-01-29 08:38:23 -05003557static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003558{
Paul Moore71f1cb02008-01-29 08:51:16 -05003559 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003560 u32 xfrm_sid;
3561 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003562 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003563
3564 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003565 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003566
Paul Moore71f1cb02008-01-29 08:51:16 -05003567 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3568 if (unlikely(err)) {
3569 printk(KERN_WARNING
3570 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3571 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003572 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003573 }
Paul Moore220deb92008-01-29 08:38:23 -05003574
3575 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003576}
3577
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578/* socket security operations */
3579static int socket_has_perm(struct task_struct *task, struct socket *sock,
3580 u32 perms)
3581{
3582 struct inode_security_struct *isec;
3583 struct task_security_struct *tsec;
3584 struct avc_audit_data ad;
3585 int err = 0;
3586
3587 tsec = task->security;
3588 isec = SOCK_INODE(sock)->i_security;
3589
3590 if (isec->sid == SECINITSID_KERNEL)
3591 goto out;
3592
Eric Paris828dfe12008-04-17 13:17:49 -04003593 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 ad.u.net.sk = sock->sk;
3595 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3596
3597out:
3598 return err;
3599}
3600
3601static int selinux_socket_create(int family, int type,
3602 int protocol, int kern)
3603{
3604 int err = 0;
3605 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003606 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607
3608 if (kern)
3609 goto out;
3610
3611 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003612 newsid = tsec->sockcreate_sid ? : tsec->sid;
3613 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 socket_type_to_security_class(family, type,
3615 protocol), SOCKET__CREATE, NULL);
3616
3617out:
3618 return err;
3619}
3620
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003621static int selinux_socket_post_create(struct socket *sock, int family,
3622 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003624 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 struct inode_security_struct *isec;
3626 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003627 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003628 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
3630 isec = SOCK_INODE(sock)->i_security;
3631
3632 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003633 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003635 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 isec->initialized = 1;
3637
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003638 if (sock->sk) {
3639 sksec = sock->sk->sk_security;
3640 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003641 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003642 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003643 }
3644
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003645 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646}
3647
3648/* Range of port numbers used to automatically bind.
3649 Need to determine whether we should perform a name_bind
3650 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
3652static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3653{
3654 u16 family;
3655 int err;
3656
3657 err = socket_has_perm(current, sock, SOCKET__BIND);
3658 if (err)
3659 goto out;
3660
3661 /*
3662 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003663 * Multiple address binding for SCTP is not supported yet: we just
3664 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 */
3666 family = sock->sk->sk_family;
3667 if (family == PF_INET || family == PF_INET6) {
3668 char *addrp;
3669 struct inode_security_struct *isec;
3670 struct task_security_struct *tsec;
3671 struct avc_audit_data ad;
3672 struct sockaddr_in *addr4 = NULL;
3673 struct sockaddr_in6 *addr6 = NULL;
3674 unsigned short snum;
3675 struct sock *sk = sock->sk;
3676 u32 sid, node_perm, addrlen;
3677
3678 tsec = current->security;
3679 isec = SOCK_INODE(sock)->i_security;
3680
3681 if (family == PF_INET) {
3682 addr4 = (struct sockaddr_in *)address;
3683 snum = ntohs(addr4->sin_port);
3684 addrlen = sizeof(addr4->sin_addr.s_addr);
3685 addrp = (char *)&addr4->sin_addr.s_addr;
3686 } else {
3687 addr6 = (struct sockaddr_in6 *)address;
3688 snum = ntohs(addr6->sin6_port);
3689 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3690 addrp = (char *)&addr6->sin6_addr.s6_addr;
3691 }
3692
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003693 if (snum) {
3694 int low, high;
3695
3696 inet_get_local_port_range(&low, &high);
3697
3698 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003699 err = sel_netport_sid(sk->sk_protocol,
3700 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003701 if (err)
3702 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003703 AVC_AUDIT_DATA_INIT(&ad, NET);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003704 ad.u.net.sport = htons(snum);
3705 ad.u.net.family = family;
3706 err = avc_has_perm(isec->sid, sid,
3707 isec->sclass,
3708 SOCKET__NAME_BIND, &ad);
3709 if (err)
3710 goto out;
3711 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 }
Eric Paris828dfe12008-04-17 13:17:49 -04003713
3714 switch (isec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003715 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 node_perm = TCP_SOCKET__NODE_BIND;
3717 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003718
James Morris13402582005-09-30 14:24:34 -04003719 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 node_perm = UDP_SOCKET__NODE_BIND;
3721 break;
James Morris2ee92d42006-11-13 16:09:01 -08003722
3723 case SECCLASS_DCCP_SOCKET:
3724 node_perm = DCCP_SOCKET__NODE_BIND;
3725 break;
3726
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 default:
3728 node_perm = RAWIP_SOCKET__NODE_BIND;
3729 break;
3730 }
Eric Paris828dfe12008-04-17 13:17:49 -04003731
Paul Moore224dfbd2008-01-29 08:38:13 -05003732 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 if (err)
3734 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003735
3736 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 ad.u.net.sport = htons(snum);
3738 ad.u.net.family = family;
3739
3740 if (family == PF_INET)
3741 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3742 else
3743 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3744
3745 err = avc_has_perm(isec->sid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003746 isec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 if (err)
3748 goto out;
3749 }
3750out:
3751 return err;
3752}
3753
3754static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3755{
3756 struct inode_security_struct *isec;
3757 int err;
3758
3759 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3760 if (err)
3761 return err;
3762
3763 /*
James Morris2ee92d42006-11-13 16:09:01 -08003764 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 */
3766 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003767 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3768 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 struct sock *sk = sock->sk;
3770 struct avc_audit_data ad;
3771 struct sockaddr_in *addr4 = NULL;
3772 struct sockaddr_in6 *addr6 = NULL;
3773 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003774 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
3776 if (sk->sk_family == PF_INET) {
3777 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003778 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 return -EINVAL;
3780 snum = ntohs(addr4->sin_port);
3781 } else {
3782 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003783 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 return -EINVAL;
3785 snum = ntohs(addr6->sin6_port);
3786 }
3787
Paul Moore3e112172008-04-10 10:48:14 -04003788 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 if (err)
3790 goto out;
3791
James Morris2ee92d42006-11-13 16:09:01 -08003792 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3793 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3794
Eric Paris828dfe12008-04-17 13:17:49 -04003795 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 ad.u.net.dport = htons(snum);
3797 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003798 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 if (err)
3800 goto out;
3801 }
3802
3803out:
3804 return err;
3805}
3806
3807static int selinux_socket_listen(struct socket *sock, int backlog)
3808{
3809 return socket_has_perm(current, sock, SOCKET__LISTEN);
3810}
3811
3812static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3813{
3814 int err;
3815 struct inode_security_struct *isec;
3816 struct inode_security_struct *newisec;
3817
3818 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3819 if (err)
3820 return err;
3821
3822 newisec = SOCK_INODE(newsock)->i_security;
3823
3824 isec = SOCK_INODE(sock)->i_security;
3825 newisec->sclass = isec->sclass;
3826 newisec->sid = isec->sid;
3827 newisec->initialized = 1;
3828
3829 return 0;
3830}
3831
3832static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04003833 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003835 int rc;
3836
3837 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3838 if (rc)
3839 return rc;
3840
3841 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842}
3843
3844static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3845 int size, int flags)
3846{
3847 return socket_has_perm(current, sock, SOCKET__READ);
3848}
3849
3850static int selinux_socket_getsockname(struct socket *sock)
3851{
3852 return socket_has_perm(current, sock, SOCKET__GETATTR);
3853}
3854
3855static int selinux_socket_getpeername(struct socket *sock)
3856{
3857 return socket_has_perm(current, sock, SOCKET__GETATTR);
3858}
3859
Eric Paris828dfe12008-04-17 13:17:49 -04003860static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861{
Paul Mooref8687af2006-10-30 15:22:15 -08003862 int err;
3863
3864 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3865 if (err)
3866 return err;
3867
3868 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869}
3870
3871static int selinux_socket_getsockopt(struct socket *sock, int level,
3872 int optname)
3873{
3874 return socket_has_perm(current, sock, SOCKET__GETOPT);
3875}
3876
3877static int selinux_socket_shutdown(struct socket *sock, int how)
3878{
3879 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3880}
3881
3882static int selinux_socket_unix_stream_connect(struct socket *sock,
3883 struct socket *other,
3884 struct sock *newsk)
3885{
3886 struct sk_security_struct *ssec;
3887 struct inode_security_struct *isec;
3888 struct inode_security_struct *other_isec;
3889 struct avc_audit_data ad;
3890 int err;
3891
3892 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3893 if (err)
3894 return err;
3895
3896 isec = SOCK_INODE(sock)->i_security;
3897 other_isec = SOCK_INODE(other)->i_security;
3898
Eric Paris828dfe12008-04-17 13:17:49 -04003899 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 ad.u.net.sk = other->sk;
3901
3902 err = avc_has_perm(isec->sid, other_isec->sid,
3903 isec->sclass,
3904 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3905 if (err)
3906 return err;
3907
3908 /* connecting socket */
3909 ssec = sock->sk->sk_security;
3910 ssec->peer_sid = other_isec->sid;
Eric Paris828dfe12008-04-17 13:17:49 -04003911
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 /* server child socket */
3913 ssec = newsk->sk_security;
3914 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003915 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3916
3917 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918}
3919
3920static int selinux_socket_unix_may_send(struct socket *sock,
3921 struct socket *other)
3922{
3923 struct inode_security_struct *isec;
3924 struct inode_security_struct *other_isec;
3925 struct avc_audit_data ad;
3926 int err;
3927
3928 isec = SOCK_INODE(sock)->i_security;
3929 other_isec = SOCK_INODE(other)->i_security;
3930
Eric Paris828dfe12008-04-17 13:17:49 -04003931 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 ad.u.net.sk = other->sk;
3933
3934 err = avc_has_perm(isec->sid, other_isec->sid,
3935 isec->sclass, SOCKET__SENDTO, &ad);
3936 if (err)
3937 return err;
3938
3939 return 0;
3940}
3941
Paul Mooreeffad8d2008-01-29 08:49:27 -05003942static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3943 u32 peer_sid,
3944 struct avc_audit_data *ad)
3945{
3946 int err;
3947 u32 if_sid;
3948 u32 node_sid;
3949
3950 err = sel_netif_sid(ifindex, &if_sid);
3951 if (err)
3952 return err;
3953 err = avc_has_perm(peer_sid, if_sid,
3954 SECCLASS_NETIF, NETIF__INGRESS, ad);
3955 if (err)
3956 return err;
3957
3958 err = sel_netnode_sid(addrp, family, &node_sid);
3959 if (err)
3960 return err;
3961 return avc_has_perm(peer_sid, node_sid,
3962 SECCLASS_NODE, NODE__RECVFROM, ad);
3963}
3964
Paul Moore220deb92008-01-29 08:38:23 -05003965static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3966 struct sk_buff *skb,
3967 struct avc_audit_data *ad,
3968 u16 family,
3969 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970{
Paul Moore220deb92008-01-29 08:38:23 -05003971 int err;
3972 struct sk_security_struct *sksec = sk->sk_security;
3973 u16 sk_class;
3974 u32 netif_perm, node_perm, recv_perm;
3975 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003976
Paul Moore220deb92008-01-29 08:38:23 -05003977 sk_sid = sksec->sid;
3978 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979
Paul Moore220deb92008-01-29 08:38:23 -05003980 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 case SECCLASS_UDP_SOCKET:
3982 netif_perm = NETIF__UDP_RECV;
3983 node_perm = NODE__UDP_RECV;
3984 recv_perm = UDP_SOCKET__RECV_MSG;
3985 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 case SECCLASS_TCP_SOCKET:
3987 netif_perm = NETIF__TCP_RECV;
3988 node_perm = NODE__TCP_RECV;
3989 recv_perm = TCP_SOCKET__RECV_MSG;
3990 break;
James Morris2ee92d42006-11-13 16:09:01 -08003991 case SECCLASS_DCCP_SOCKET:
3992 netif_perm = NETIF__DCCP_RECV;
3993 node_perm = NODE__DCCP_RECV;
3994 recv_perm = DCCP_SOCKET__RECV_MSG;
3995 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 default:
3997 netif_perm = NETIF__RAWIP_RECV;
3998 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05003999 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 break;
4001 }
4002
Paul Moore220deb92008-01-29 08:38:23 -05004003 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004005 return err;
4006 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4007 if (err)
4008 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004009
Paul Moore224dfbd2008-01-29 08:38:13 -05004010 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004012 return err;
4013 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004015 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
Paul Moore220deb92008-01-29 08:38:23 -05004017 if (!recv_perm)
4018 return 0;
Paul Moore3e112172008-04-10 10:48:14 -04004019 err = sel_netport_sid(sk->sk_protocol,
4020 ntohs(ad->u.net.sport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004021 if (unlikely(err)) {
4022 printk(KERN_WARNING
4023 "SELinux: failure in"
4024 " selinux_sock_rcv_skb_iptables_compat(),"
4025 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05004026 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004027 }
Paul Moore220deb92008-01-29 08:38:23 -05004028 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4029}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
Paul Moore220deb92008-01-29 08:38:23 -05004031static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4032 struct avc_audit_data *ad,
4033 u16 family, char *addrp)
4034{
4035 int err;
4036 struct sk_security_struct *sksec = sk->sk_security;
4037 u32 peer_sid;
4038 u32 sk_sid = sksec->sid;
4039
4040 if (selinux_compat_net)
4041 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
4042 family, addrp);
4043 else
4044 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4045 PACKET__RECV, ad);
4046 if (err)
4047 return err;
4048
4049 if (selinux_policycap_netpeer) {
4050 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004052 return err;
4053 err = avc_has_perm(sk_sid, peer_sid,
4054 SECCLASS_PEER, PEER__RECV, ad);
4055 } else {
4056 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
4057 if (err)
4058 return err;
4059 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004061
James Morris4e5ab4c2006-06-09 00:33:33 -07004062 return err;
4063}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004064
James Morris4e5ab4c2006-06-09 00:33:33 -07004065static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4066{
Paul Moore220deb92008-01-29 08:38:23 -05004067 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004068 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004069 u16 family = sk->sk_family;
4070 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004071 struct avc_audit_data ad;
4072 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07004073
James Morris4e5ab4c2006-06-09 00:33:33 -07004074 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004075 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004076
4077 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004078 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004079 family = PF_INET;
4080
James Morris4e5ab4c2006-06-09 00:33:33 -07004081 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004082 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07004083 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004084 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004085 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004086 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004087
Paul Moore220deb92008-01-29 08:38:23 -05004088 /* If any sort of compatibility mode is enabled then handoff processing
4089 * to the selinux_sock_rcv_skb_compat() function to deal with the
4090 * special handling. We do this in an attempt to keep this function
4091 * as fast and as clean as possible. */
4092 if (selinux_compat_net || !selinux_policycap_netpeer)
4093 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4094 family, addrp);
4095
Paul Moored621d352008-01-29 08:43:36 -05004096 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4097 u32 peer_sid;
4098
4099 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4100 if (err)
4101 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004102 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4103 peer_sid, &ad);
4104 if (err)
4105 return err;
Paul Moored621d352008-01-29 08:43:36 -05004106 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4107 PEER__RECV, &ad);
4108 }
4109
Paul Mooreeffad8d2008-01-29 08:49:27 -05004110 if (selinux_secmark_enabled()) {
4111 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4112 PACKET__RECV, &ad);
4113 if (err)
4114 return err;
4115 }
4116
Paul Moored621d352008-01-29 08:43:36 -05004117 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118}
4119
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004120static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4121 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122{
4123 int err = 0;
4124 char *scontext;
4125 u32 scontext_len;
4126 struct sk_security_struct *ssec;
4127 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004128 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004131
Paul Moore3de4bab2006-11-17 17:38:54 -05004132 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4133 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004134 ssec = sock->sk->sk_security;
4135 peer_sid = ssec->peer_sid;
4136 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004137 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 err = -ENOPROTOOPT;
4139 goto out;
4140 }
4141
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004142 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4143
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (err)
4145 goto out;
4146
4147 if (scontext_len > len) {
4148 err = -ERANGE;
4149 goto out_len;
4150 }
4151
4152 if (copy_to_user(optval, scontext, scontext_len))
4153 err = -EFAULT;
4154
4155out_len:
4156 if (put_user(scontext_len, optlen))
4157 err = -EFAULT;
4158
4159 kfree(scontext);
Eric Paris828dfe12008-04-17 13:17:49 -04004160out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 return err;
4162}
4163
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004164static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004165{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004166 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004167 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004168
Paul Moore75e22912008-01-29 08:38:04 -05004169 if (sock)
4170 family = sock->sk->sk_family;
4171 else if (skb && skb->sk)
4172 family = skb->sk->sk_family;
4173 else
4174 goto out;
4175
4176 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004177 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004178 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004179 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004180
Paul Moore75e22912008-01-29 08:38:04 -05004181out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004182 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004183 if (peer_secid == SECSID_NULL)
4184 return -EINVAL;
4185 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004186}
4187
Al Viro7d877f32005-10-21 03:20:43 -04004188static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189{
4190 return sk_alloc_security(sk, family, priority);
4191}
4192
4193static void selinux_sk_free_security(struct sock *sk)
4194{
4195 sk_free_security(sk);
4196}
4197
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004198static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4199{
4200 struct sk_security_struct *ssec = sk->sk_security;
4201 struct sk_security_struct *newssec = newsk->sk_security;
4202
4203 newssec->sid = ssec->sid;
4204 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004205 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004206
Paul Mooref74af6e2008-02-25 11:40:33 -05004207 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004208}
4209
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004210static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004211{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004212 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004213 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004214 else {
4215 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004216
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004217 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004218 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004219}
4220
Eric Paris828dfe12008-04-17 13:17:49 -04004221static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004222{
4223 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4224 struct sk_security_struct *sksec = sk->sk_security;
4225
David Woodhouse2148ccc2006-09-29 15:50:25 -07004226 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4227 sk->sk_family == PF_UNIX)
4228 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004229 sksec->sclass = isec->sclass;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004230
4231 selinux_netlbl_sock_graft(sk, parent);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004232}
4233
Adrian Bunk9a673e52006-08-15 00:03:53 -07004234static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4235 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004236{
4237 struct sk_security_struct *sksec = sk->sk_security;
4238 int err;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004239 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004240 u32 peersid;
4241
Paul Moore220deb92008-01-29 08:38:23 -05004242 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4243 if (err)
4244 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004245 if (peersid == SECSID_NULL) {
4246 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004247 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004248 return 0;
4249 }
4250
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004251 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4252 if (err)
4253 return err;
4254
4255 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004256 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004257 return 0;
4258}
4259
Adrian Bunk9a673e52006-08-15 00:03:53 -07004260static void selinux_inet_csk_clone(struct sock *newsk,
4261 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004262{
4263 struct sk_security_struct *newsksec = newsk->sk_security;
4264
4265 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004266 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004267 /* NOTE: Ideally, we should also get the isec->sid for the
4268 new socket in sync, but we don't have the isec available yet.
4269 So we will wait until sock_graft to do it, by which
4270 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004271
Paul Moore9f2ad662006-11-17 17:38:53 -05004272 /* We don't need to take any sort of lock here as we are the only
4273 * thread with access to newsksec */
4274 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004275}
4276
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004277static void selinux_inet_conn_established(struct sock *sk,
4278 struct sk_buff *skb)
4279{
4280 struct sk_security_struct *sksec = sk->sk_security;
4281
Paul Moore220deb92008-01-29 08:38:23 -05004282 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004283}
4284
Adrian Bunk9a673e52006-08-15 00:03:53 -07004285static void selinux_req_classify_flow(const struct request_sock *req,
4286 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004287{
4288 fl->secid = req->secid;
4289}
4290
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4292{
4293 int err = 0;
4294 u32 perm;
4295 struct nlmsghdr *nlh;
4296 struct socket *sock = sk->sk_socket;
4297 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004298
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 if (skb->len < NLMSG_SPACE(0)) {
4300 err = -EINVAL;
4301 goto out;
4302 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004303 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004304
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4306 if (err) {
4307 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004308 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 "SELinux: unrecognized netlink message"
4310 " type=%hu for sclass=%hu\n",
4311 nlh->nlmsg_type, isec->sclass);
4312 if (!selinux_enforcing)
4313 err = 0;
4314 }
4315
4316 /* Ignore */
4317 if (err == -ENOENT)
4318 err = 0;
4319 goto out;
4320 }
4321
4322 err = socket_has_perm(current, sock, perm);
4323out:
4324 return err;
4325}
4326
4327#ifdef CONFIG_NETFILTER
4328
Paul Mooreeffad8d2008-01-29 08:49:27 -05004329static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4330 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004332 char *addrp;
4333 u32 peer_sid;
4334 struct avc_audit_data ad;
4335 u8 secmark_active;
4336 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004337
Paul Mooreeffad8d2008-01-29 08:49:27 -05004338 if (!selinux_policycap_netpeer)
4339 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004340
Paul Mooreeffad8d2008-01-29 08:49:27 -05004341 secmark_active = selinux_secmark_enabled();
4342 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4343 if (!secmark_active && !peerlbl_active)
4344 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004345
Paul Mooreeffad8d2008-01-29 08:49:27 -05004346 AVC_AUDIT_DATA_INIT(&ad, NET);
4347 ad.u.net.netif = ifindex;
4348 ad.u.net.family = family;
4349 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4350 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
Paul Mooreeffad8d2008-01-29 08:49:27 -05004352 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4353 return NF_DROP;
4354
4355 if (peerlbl_active)
4356 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4357 peer_sid, &ad) != 0)
4358 return NF_DROP;
4359
4360 if (secmark_active)
4361 if (avc_has_perm(peer_sid, skb->secmark,
4362 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4363 return NF_DROP;
4364
4365 return NF_ACCEPT;
4366}
4367
4368static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4369 struct sk_buff *skb,
4370 const struct net_device *in,
4371 const struct net_device *out,
4372 int (*okfn)(struct sk_buff *))
4373{
4374 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4375}
4376
4377#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4378static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4379 struct sk_buff *skb,
4380 const struct net_device *in,
4381 const struct net_device *out,
4382 int (*okfn)(struct sk_buff *))
4383{
4384 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4385}
4386#endif /* IPV6 */
4387
4388static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4389 int ifindex,
4390 struct avc_audit_data *ad,
4391 u16 family, char *addrp)
4392{
4393 int err;
4394 struct sk_security_struct *sksec = sk->sk_security;
4395 u16 sk_class;
4396 u32 netif_perm, node_perm, send_perm;
4397 u32 port_sid, node_sid, if_sid, sk_sid;
4398
4399 sk_sid = sksec->sid;
4400 sk_class = sksec->sclass;
4401
4402 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 case SECCLASS_UDP_SOCKET:
4404 netif_perm = NETIF__UDP_SEND;
4405 node_perm = NODE__UDP_SEND;
4406 send_perm = UDP_SOCKET__SEND_MSG;
4407 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408 case SECCLASS_TCP_SOCKET:
4409 netif_perm = NETIF__TCP_SEND;
4410 node_perm = NODE__TCP_SEND;
4411 send_perm = TCP_SOCKET__SEND_MSG;
4412 break;
James Morris2ee92d42006-11-13 16:09:01 -08004413 case SECCLASS_DCCP_SOCKET:
4414 netif_perm = NETIF__DCCP_SEND;
4415 node_perm = NODE__DCCP_SEND;
4416 send_perm = DCCP_SOCKET__SEND_MSG;
4417 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 default:
4419 netif_perm = NETIF__RAWIP_SEND;
4420 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004421 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 break;
4423 }
4424
Paul Mooreeffad8d2008-01-29 08:49:27 -05004425 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004426 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004427 return err;
4428 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4429 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004430
Paul Moore224dfbd2008-01-29 08:38:13 -05004431 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004432 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004433 return err;
4434 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004435 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004436 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Paul Mooreeffad8d2008-01-29 08:49:27 -05004438 if (send_perm != 0)
4439 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Paul Moore3e112172008-04-10 10:48:14 -04004441 err = sel_netport_sid(sk->sk_protocol,
4442 ntohs(ad->u.net.dport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004443 if (unlikely(err)) {
4444 printk(KERN_WARNING
4445 "SELinux: failure in"
4446 " selinux_ip_postroute_iptables_compat(),"
4447 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004448 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004449 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004450 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004451}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Paul Mooreeffad8d2008-01-29 08:49:27 -05004453static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4454 int ifindex,
4455 struct avc_audit_data *ad,
4456 u16 family,
4457 char *addrp,
4458 u8 proto)
James Morris4e5ab4c2006-06-09 00:33:33 -07004459{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004460 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004461 struct sk_security_struct *sksec;
James Morris4e5ab4c2006-06-09 00:33:33 -07004462
Paul Mooreeffad8d2008-01-29 08:49:27 -05004463 if (sk == NULL)
4464 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004465 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004466
Paul Mooreeffad8d2008-01-29 08:49:27 -05004467 if (selinux_compat_net) {
4468 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4469 ad, family, addrp))
4470 return NF_DROP;
4471 } else {
4472 if (avc_has_perm(sksec->sid, skb->secmark,
4473 SECCLASS_PACKET, PACKET__SEND, ad))
4474 return NF_DROP;
4475 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004476
Paul Mooreeffad8d2008-01-29 08:49:27 -05004477 if (selinux_policycap_netpeer)
4478 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4479 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004480
Paul Mooreeffad8d2008-01-29 08:49:27 -05004481 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482}
4483
Paul Mooreeffad8d2008-01-29 08:49:27 -05004484static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4485 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004487 u32 secmark_perm;
4488 u32 peer_sid;
4489 struct sock *sk;
4490 struct avc_audit_data ad;
4491 char *addrp;
4492 u8 proto;
4493 u8 secmark_active;
4494 u8 peerlbl_active;
4495
4496 AVC_AUDIT_DATA_INIT(&ad, NET);
4497 ad.u.net.netif = ifindex;
4498 ad.u.net.family = family;
4499 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4500 return NF_DROP;
4501
4502 /* If any sort of compatibility mode is enabled then handoff processing
4503 * to the selinux_ip_postroute_compat() function to deal with the
4504 * special handling. We do this in an attempt to keep this function
4505 * as fast and as clean as possible. */
4506 if (selinux_compat_net || !selinux_policycap_netpeer)
4507 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4508 family, addrp, proto);
4509
4510 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4511 * packet transformation so allow the packet to pass without any checks
4512 * since we'll have another chance to perform access control checks
4513 * when the packet is on it's final way out.
4514 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4515 * is NULL, in this case go ahead and apply access control. */
4516 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4517 return NF_ACCEPT;
4518
4519 secmark_active = selinux_secmark_enabled();
4520 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4521 if (!secmark_active && !peerlbl_active)
4522 return NF_ACCEPT;
4523
4524 /* if the packet is locally generated (skb->sk != NULL) then use the
4525 * socket's label as the peer label, otherwise the packet is being
4526 * forwarded through this system and we need to fetch the peer label
4527 * directly from the packet */
4528 sk = skb->sk;
4529 if (sk) {
4530 struct sk_security_struct *sksec = sk->sk_security;
4531 peer_sid = sksec->sid;
4532 secmark_perm = PACKET__SEND;
4533 } else {
4534 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4535 return NF_DROP;
4536 secmark_perm = PACKET__FORWARD_OUT;
4537 }
4538
4539 if (secmark_active)
4540 if (avc_has_perm(peer_sid, skb->secmark,
4541 SECCLASS_PACKET, secmark_perm, &ad))
4542 return NF_DROP;
4543
4544 if (peerlbl_active) {
4545 u32 if_sid;
4546 u32 node_sid;
4547
4548 if (sel_netif_sid(ifindex, &if_sid))
4549 return NF_DROP;
4550 if (avc_has_perm(peer_sid, if_sid,
4551 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4552 return NF_DROP;
4553
4554 if (sel_netnode_sid(addrp, family, &node_sid))
4555 return NF_DROP;
4556 if (avc_has_perm(peer_sid, node_sid,
4557 SECCLASS_NODE, NODE__SENDTO, &ad))
4558 return NF_DROP;
4559 }
4560
4561 return NF_ACCEPT;
4562}
4563
4564static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4565 struct sk_buff *skb,
4566 const struct net_device *in,
4567 const struct net_device *out,
4568 int (*okfn)(struct sk_buff *))
4569{
4570 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571}
4572
4573#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004574static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4575 struct sk_buff *skb,
4576 const struct net_device *in,
4577 const struct net_device *out,
4578 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004580 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582#endif /* IPV6 */
4583
4584#endif /* CONFIG_NETFILTER */
4585
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4587{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 int err;
4589
4590 err = secondary_ops->netlink_send(sk, skb);
4591 if (err)
4592 return err;
4593
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4595 err = selinux_nlmsg_perm(sk, skb);
4596
4597 return err;
4598}
4599
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004600static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004602 int err;
4603 struct avc_audit_data ad;
4604
4605 err = secondary_ops->netlink_recv(skb, capability);
4606 if (err)
4607 return err;
4608
4609 AVC_AUDIT_DATA_INIT(&ad, CAP);
4610 ad.u.cap = capability;
4611
4612 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
Eric Paris828dfe12008-04-17 13:17:49 -04004613 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614}
4615
4616static int ipc_alloc_security(struct task_struct *task,
4617 struct kern_ipc_perm *perm,
4618 u16 sclass)
4619{
4620 struct task_security_struct *tsec = task->security;
4621 struct ipc_security_struct *isec;
4622
James Morris89d155e2005-10-30 14:59:21 -08004623 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624 if (!isec)
4625 return -ENOMEM;
4626
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 isec->sclass = sclass;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004628 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 perm->security = isec;
4630
4631 return 0;
4632}
4633
4634static void ipc_free_security(struct kern_ipc_perm *perm)
4635{
4636 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 perm->security = NULL;
4638 kfree(isec);
4639}
4640
4641static int msg_msg_alloc_security(struct msg_msg *msg)
4642{
4643 struct msg_security_struct *msec;
4644
James Morris89d155e2005-10-30 14:59:21 -08004645 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004646 if (!msec)
4647 return -ENOMEM;
4648
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 msec->sid = SECINITSID_UNLABELED;
4650 msg->security = msec;
4651
4652 return 0;
4653}
4654
4655static void msg_msg_free_security(struct msg_msg *msg)
4656{
4657 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658
4659 msg->security = NULL;
4660 kfree(msec);
4661}
4662
4663static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004664 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665{
4666 struct task_security_struct *tsec;
4667 struct ipc_security_struct *isec;
4668 struct avc_audit_data ad;
4669
4670 tsec = current->security;
4671 isec = ipc_perms->security;
4672
4673 AVC_AUDIT_DATA_INIT(&ad, IPC);
4674 ad.u.ipc_id = ipc_perms->key;
4675
Stephen Smalley6af963f2005-05-01 08:58:39 -07004676 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677}
4678
4679static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4680{
4681 return msg_msg_alloc_security(msg);
4682}
4683
4684static void selinux_msg_msg_free_security(struct msg_msg *msg)
4685{
4686 msg_msg_free_security(msg);
4687}
4688
4689/* message queue security operations */
4690static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4691{
4692 struct task_security_struct *tsec;
4693 struct ipc_security_struct *isec;
4694 struct avc_audit_data ad;
4695 int rc;
4696
4697 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4698 if (rc)
4699 return rc;
4700
4701 tsec = current->security;
4702 isec = msq->q_perm.security;
4703
4704 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004705 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706
4707 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4708 MSGQ__CREATE, &ad);
4709 if (rc) {
4710 ipc_free_security(&msq->q_perm);
4711 return rc;
4712 }
4713 return 0;
4714}
4715
4716static void selinux_msg_queue_free_security(struct msg_queue *msq)
4717{
4718 ipc_free_security(&msq->q_perm);
4719}
4720
4721static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4722{
4723 struct task_security_struct *tsec;
4724 struct ipc_security_struct *isec;
4725 struct avc_audit_data ad;
4726
4727 tsec = current->security;
4728 isec = msq->q_perm.security;
4729
4730 AVC_AUDIT_DATA_INIT(&ad, IPC);
4731 ad.u.ipc_id = msq->q_perm.key;
4732
4733 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4734 MSGQ__ASSOCIATE, &ad);
4735}
4736
4737static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4738{
4739 int err;
4740 int perms;
4741
Eric Paris828dfe12008-04-17 13:17:49 -04004742 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743 case IPC_INFO:
4744 case MSG_INFO:
4745 /* No specific object, just general system-wide information. */
4746 return task_has_system(current, SYSTEM__IPC_INFO);
4747 case IPC_STAT:
4748 case MSG_STAT:
4749 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4750 break;
4751 case IPC_SET:
4752 perms = MSGQ__SETATTR;
4753 break;
4754 case IPC_RMID:
4755 perms = MSGQ__DESTROY;
4756 break;
4757 default:
4758 return 0;
4759 }
4760
Stephen Smalley6af963f2005-05-01 08:58:39 -07004761 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 return err;
4763}
4764
4765static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4766{
4767 struct task_security_struct *tsec;
4768 struct ipc_security_struct *isec;
4769 struct msg_security_struct *msec;
4770 struct avc_audit_data ad;
4771 int rc;
4772
4773 tsec = current->security;
4774 isec = msq->q_perm.security;
4775 msec = msg->security;
4776
4777 /*
4778 * First time through, need to assign label to the message
4779 */
4780 if (msec->sid == SECINITSID_UNLABELED) {
4781 /*
4782 * Compute new sid based on current process and
4783 * message queue this message will be stored in
4784 */
4785 rc = security_transition_sid(tsec->sid,
4786 isec->sid,
4787 SECCLASS_MSG,
4788 &msec->sid);
4789 if (rc)
4790 return rc;
4791 }
4792
4793 AVC_AUDIT_DATA_INIT(&ad, IPC);
4794 ad.u.ipc_id = msq->q_perm.key;
4795
4796 /* Can this process write to the queue? */
4797 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4798 MSGQ__WRITE, &ad);
4799 if (!rc)
4800 /* Can this process send the message */
4801 rc = avc_has_perm(tsec->sid, msec->sid,
4802 SECCLASS_MSG, MSG__SEND, &ad);
4803 if (!rc)
4804 /* Can the message be put in the queue? */
4805 rc = avc_has_perm(msec->sid, isec->sid,
4806 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4807
4808 return rc;
4809}
4810
4811static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4812 struct task_struct *target,
4813 long type, int mode)
4814{
4815 struct task_security_struct *tsec;
4816 struct ipc_security_struct *isec;
4817 struct msg_security_struct *msec;
4818 struct avc_audit_data ad;
4819 int rc;
4820
4821 tsec = target->security;
4822 isec = msq->q_perm.security;
4823 msec = msg->security;
4824
4825 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004826 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827
4828 rc = avc_has_perm(tsec->sid, isec->sid,
4829 SECCLASS_MSGQ, MSGQ__READ, &ad);
4830 if (!rc)
4831 rc = avc_has_perm(tsec->sid, msec->sid,
4832 SECCLASS_MSG, MSG__RECEIVE, &ad);
4833 return rc;
4834}
4835
4836/* Shared Memory security operations */
4837static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4838{
4839 struct task_security_struct *tsec;
4840 struct ipc_security_struct *isec;
4841 struct avc_audit_data ad;
4842 int rc;
4843
4844 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4845 if (rc)
4846 return rc;
4847
4848 tsec = current->security;
4849 isec = shp->shm_perm.security;
4850
4851 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004852 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853
4854 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4855 SHM__CREATE, &ad);
4856 if (rc) {
4857 ipc_free_security(&shp->shm_perm);
4858 return rc;
4859 }
4860 return 0;
4861}
4862
4863static void selinux_shm_free_security(struct shmid_kernel *shp)
4864{
4865 ipc_free_security(&shp->shm_perm);
4866}
4867
4868static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
4869{
4870 struct task_security_struct *tsec;
4871 struct ipc_security_struct *isec;
4872 struct avc_audit_data ad;
4873
4874 tsec = current->security;
4875 isec = shp->shm_perm.security;
4876
4877 AVC_AUDIT_DATA_INIT(&ad, IPC);
4878 ad.u.ipc_id = shp->shm_perm.key;
4879
4880 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
4881 SHM__ASSOCIATE, &ad);
4882}
4883
4884/* Note, at this point, shp is locked down */
4885static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
4886{
4887 int perms;
4888 int err;
4889
Eric Paris828dfe12008-04-17 13:17:49 -04004890 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891 case IPC_INFO:
4892 case SHM_INFO:
4893 /* No specific object, just general system-wide information. */
4894 return task_has_system(current, SYSTEM__IPC_INFO);
4895 case IPC_STAT:
4896 case SHM_STAT:
4897 perms = SHM__GETATTR | SHM__ASSOCIATE;
4898 break;
4899 case IPC_SET:
4900 perms = SHM__SETATTR;
4901 break;
4902 case SHM_LOCK:
4903 case SHM_UNLOCK:
4904 perms = SHM__LOCK;
4905 break;
4906 case IPC_RMID:
4907 perms = SHM__DESTROY;
4908 break;
4909 default:
4910 return 0;
4911 }
4912
Stephen Smalley6af963f2005-05-01 08:58:39 -07004913 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914 return err;
4915}
4916
4917static int selinux_shm_shmat(struct shmid_kernel *shp,
4918 char __user *shmaddr, int shmflg)
4919{
4920 u32 perms;
4921 int rc;
4922
4923 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
4924 if (rc)
4925 return rc;
4926
4927 if (shmflg & SHM_RDONLY)
4928 perms = SHM__READ;
4929 else
4930 perms = SHM__READ | SHM__WRITE;
4931
Stephen Smalley6af963f2005-05-01 08:58:39 -07004932 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933}
4934
4935/* Semaphore security operations */
4936static int selinux_sem_alloc_security(struct sem_array *sma)
4937{
4938 struct task_security_struct *tsec;
4939 struct ipc_security_struct *isec;
4940 struct avc_audit_data ad;
4941 int rc;
4942
4943 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
4944 if (rc)
4945 return rc;
4946
4947 tsec = current->security;
4948 isec = sma->sem_perm.security;
4949
4950 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004951 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952
4953 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4954 SEM__CREATE, &ad);
4955 if (rc) {
4956 ipc_free_security(&sma->sem_perm);
4957 return rc;
4958 }
4959 return 0;
4960}
4961
4962static void selinux_sem_free_security(struct sem_array *sma)
4963{
4964 ipc_free_security(&sma->sem_perm);
4965}
4966
4967static int selinux_sem_associate(struct sem_array *sma, int semflg)
4968{
4969 struct task_security_struct *tsec;
4970 struct ipc_security_struct *isec;
4971 struct avc_audit_data ad;
4972
4973 tsec = current->security;
4974 isec = sma->sem_perm.security;
4975
4976 AVC_AUDIT_DATA_INIT(&ad, IPC);
4977 ad.u.ipc_id = sma->sem_perm.key;
4978
4979 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
4980 SEM__ASSOCIATE, &ad);
4981}
4982
4983/* Note, at this point, sma is locked down */
4984static int selinux_sem_semctl(struct sem_array *sma, int cmd)
4985{
4986 int err;
4987 u32 perms;
4988
Eric Paris828dfe12008-04-17 13:17:49 -04004989 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990 case IPC_INFO:
4991 case SEM_INFO:
4992 /* No specific object, just general system-wide information. */
4993 return task_has_system(current, SYSTEM__IPC_INFO);
4994 case GETPID:
4995 case GETNCNT:
4996 case GETZCNT:
4997 perms = SEM__GETATTR;
4998 break;
4999 case GETVAL:
5000 case GETALL:
5001 perms = SEM__READ;
5002 break;
5003 case SETVAL:
5004 case SETALL:
5005 perms = SEM__WRITE;
5006 break;
5007 case IPC_RMID:
5008 perms = SEM__DESTROY;
5009 break;
5010 case IPC_SET:
5011 perms = SEM__SETATTR;
5012 break;
5013 case IPC_STAT:
5014 case SEM_STAT:
5015 perms = SEM__GETATTR | SEM__ASSOCIATE;
5016 break;
5017 default:
5018 return 0;
5019 }
5020
Stephen Smalley6af963f2005-05-01 08:58:39 -07005021 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 return err;
5023}
5024
5025static int selinux_sem_semop(struct sem_array *sma,
5026 struct sembuf *sops, unsigned nsops, int alter)
5027{
5028 u32 perms;
5029
5030 if (alter)
5031 perms = SEM__READ | SEM__WRITE;
5032 else
5033 perms = SEM__READ;
5034
Stephen Smalley6af963f2005-05-01 08:58:39 -07005035 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036}
5037
5038static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5039{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 u32 av = 0;
5041
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042 av = 0;
5043 if (flag & S_IRUGO)
5044 av |= IPC__UNIX_READ;
5045 if (flag & S_IWUGO)
5046 av |= IPC__UNIX_WRITE;
5047
5048 if (av == 0)
5049 return 0;
5050
Stephen Smalley6af963f2005-05-01 08:58:39 -07005051 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052}
5053
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005054static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5055{
5056 struct ipc_security_struct *isec = ipcp->security;
5057 *secid = isec->sid;
5058}
5059
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060/* module stacking operations */
Eric Paris828dfe12008-04-17 13:17:49 -04005061static int selinux_register_security(const char *name, struct security_operations *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062{
5063 if (secondary_ops != original_ops) {
Eric Parisfadcdb42007-02-22 18:11:31 -05005064 printk(KERN_ERR "%s: There is already a secondary security "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005065 "module registered.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 return -EINVAL;
Eric Paris828dfe12008-04-17 13:17:49 -04005067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068
5069 secondary_ops = ops;
5070
5071 printk(KERN_INFO "%s: Registering secondary module %s\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11005072 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073 name);
5074
5075 return 0;
5076}
5077
Eric Paris828dfe12008-04-17 13:17:49 -04005078static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079{
5080 if (inode)
5081 inode_doinit_with_dentry(inode, dentry);
5082}
5083
5084static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005085 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086{
5087 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005088 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005090 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091
5092 if (current != p) {
5093 error = task_has_perm(current, p, PROCESS__GETATTR);
5094 if (error)
5095 return error;
5096 }
5097
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 tsec = p->security;
5099
5100 if (!strcmp(name, "current"))
5101 sid = tsec->sid;
5102 else if (!strcmp(name, "prev"))
5103 sid = tsec->osid;
5104 else if (!strcmp(name, "exec"))
5105 sid = tsec->exec_sid;
5106 else if (!strcmp(name, "fscreate"))
5107 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005108 else if (!strcmp(name, "keycreate"))
5109 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005110 else if (!strcmp(name, "sockcreate"))
5111 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 else
5113 return -EINVAL;
5114
5115 if (!sid)
5116 return 0;
5117
Al Viro04ff9702007-03-12 16:17:58 +00005118 error = security_sid_to_context(sid, value, &len);
5119 if (error)
5120 return error;
5121 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122}
5123
5124static int selinux_setprocattr(struct task_struct *p,
5125 char *name, void *value, size_t size)
5126{
5127 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005128 struct task_struct *tracer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129 u32 sid = 0;
5130 int error;
5131 char *str = value;
5132
5133 if (current != p) {
5134 /* SELinux only allows a process to change its own
5135 security attributes. */
5136 return -EACCES;
5137 }
5138
5139 /*
5140 * Basic control over ability to set these attributes at all.
5141 * current == p, but we'll pass them separately in case the
5142 * above restriction is ever removed.
5143 */
5144 if (!strcmp(name, "exec"))
5145 error = task_has_perm(current, p, PROCESS__SETEXEC);
5146 else if (!strcmp(name, "fscreate"))
5147 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005148 else if (!strcmp(name, "keycreate"))
5149 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005150 else if (!strcmp(name, "sockcreate"))
5151 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152 else if (!strcmp(name, "current"))
5153 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5154 else
5155 error = -EINVAL;
5156 if (error)
5157 return error;
5158
5159 /* Obtain a SID for the context, if one was specified. */
5160 if (size && str[1] && str[1] != '\n') {
5161 if (str[size-1] == '\n') {
5162 str[size-1] = 0;
5163 size--;
5164 }
5165 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005166 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5167 if (!capable(CAP_MAC_ADMIN))
5168 return error;
5169 error = security_context_to_sid_force(value, size,
5170 &sid);
5171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 if (error)
5173 return error;
5174 }
5175
5176 /* Permission checking based on the specified context is
5177 performed during the actual operation (execve,
5178 open/mkdir/...), when we know the full context of the
5179 operation. See selinux_bprm_set_security for the execve
5180 checks and may_create for the file creation checks. The
5181 operation will then fail if the context is not permitted. */
5182 tsec = p->security;
5183 if (!strcmp(name, "exec"))
5184 tsec->exec_sid = sid;
5185 else if (!strcmp(name, "fscreate"))
5186 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005187 else if (!strcmp(name, "keycreate")) {
5188 error = may_create_key(sid, p);
5189 if (error)
5190 return error;
5191 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005192 } else if (!strcmp(name, "sockcreate"))
5193 tsec->sockcreate_sid = sid;
5194 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195 struct av_decision avd;
5196
5197 if (sid == 0)
5198 return -EINVAL;
5199
5200 /* Only allow single threaded processes to change context */
5201 if (atomic_read(&p->mm->mm_users) != 1) {
5202 struct task_struct *g, *t;
5203 struct mm_struct *mm = p->mm;
5204 read_lock(&tasklist_lock);
5205 do_each_thread(g, t)
5206 if (t->mm == mm && t != p) {
5207 read_unlock(&tasklist_lock);
5208 return -EPERM;
5209 }
5210 while_each_thread(g, t);
5211 read_unlock(&tasklist_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04005212 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213
5214 /* Check permissions for the transition. */
5215 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005216 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 if (error)
5218 return error;
5219
5220 /* Check for ptracing, and update the task SID if ok.
5221 Otherwise, leave SID unchanged and fail. */
5222 task_lock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005223 rcu_read_lock();
5224 tracer = task_tracer_task(p);
5225 if (tracer != NULL) {
5226 struct task_security_struct *ptsec = tracer->security;
5227 u32 ptsid = ptsec->sid;
5228 rcu_read_unlock();
5229 error = avc_has_perm_noaudit(ptsid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005231 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232 if (!error)
5233 tsec->sid = sid;
5234 task_unlock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005235 avc_audit(ptsid, sid, SECCLASS_PROCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 PROCESS__PTRACE, &avd, error, NULL);
5237 if (error)
5238 return error;
5239 } else {
Roland McGrath03563572008-03-26 15:46:39 -07005240 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 tsec->sid = sid;
5242 task_unlock(p);
5243 }
Eric Paris828dfe12008-04-17 13:17:49 -04005244 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 return -EINVAL;
5246
5247 return size;
5248}
5249
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005250static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5251{
5252 return security_sid_to_context(secid, secdata, seclen);
5253}
5254
David Howells7bf570d2008-04-29 20:52:51 +01005255static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005256{
5257 return security_context_to_sid(secdata, seclen, secid);
5258}
5259
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005260static void selinux_release_secctx(char *secdata, u32 seclen)
5261{
Paul Moore088999e2007-08-01 11:12:58 -04005262 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005263}
5264
Michael LeMayd7200242006-06-22 14:47:17 -07005265#ifdef CONFIG_KEYS
5266
David Howells7e047ef2006-06-26 00:24:50 -07005267static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5268 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005269{
5270 struct task_security_struct *tsec = tsk->security;
5271 struct key_security_struct *ksec;
5272
5273 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5274 if (!ksec)
5275 return -ENOMEM;
5276
Michael LeMay4eb582c2006-06-26 00:24:57 -07005277 if (tsec->keycreate_sid)
5278 ksec->sid = tsec->keycreate_sid;
5279 else
5280 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005281 k->security = ksec;
5282
5283 return 0;
5284}
5285
5286static void selinux_key_free(struct key *k)
5287{
5288 struct key_security_struct *ksec = k->security;
5289
5290 k->security = NULL;
5291 kfree(ksec);
5292}
5293
5294static int selinux_key_permission(key_ref_t key_ref,
5295 struct task_struct *ctx,
5296 key_perm_t perm)
5297{
5298 struct key *key;
5299 struct task_security_struct *tsec;
5300 struct key_security_struct *ksec;
5301
5302 key = key_ref_to_ptr(key_ref);
5303
5304 tsec = ctx->security;
5305 ksec = key->security;
5306
5307 /* if no specific permissions are requested, we skip the
5308 permission check. No serious, additional covert channels
5309 appear to be created. */
5310 if (perm == 0)
5311 return 0;
5312
5313 return avc_has_perm(tsec->sid, ksec->sid,
5314 SECCLASS_KEY, perm, NULL);
5315}
5316
David Howells70a5bb72008-04-29 01:01:26 -07005317static int selinux_key_getsecurity(struct key *key, char **_buffer)
5318{
5319 struct key_security_struct *ksec = key->security;
5320 char *context = NULL;
5321 unsigned len;
5322 int rc;
5323
5324 rc = security_sid_to_context(ksec->sid, &context, &len);
5325 if (!rc)
5326 rc = len;
5327 *_buffer = context;
5328 return rc;
5329}
5330
Michael LeMayd7200242006-06-22 14:47:17 -07005331#endif
5332
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005334 .name = "selinux",
5335
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 .ptrace = selinux_ptrace,
5337 .capget = selinux_capget,
5338 .capset_check = selinux_capset_check,
5339 .capset_set = selinux_capset_set,
5340 .sysctl = selinux_sysctl,
5341 .capable = selinux_capable,
5342 .quotactl = selinux_quotactl,
5343 .quota_on = selinux_quota_on,
5344 .syslog = selinux_syslog,
5345 .vm_enough_memory = selinux_vm_enough_memory,
5346
5347 .netlink_send = selinux_netlink_send,
Eric Paris828dfe12008-04-17 13:17:49 -04005348 .netlink_recv = selinux_netlink_recv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
5350 .bprm_alloc_security = selinux_bprm_alloc_security,
5351 .bprm_free_security = selinux_bprm_free_security,
5352 .bprm_apply_creds = selinux_bprm_apply_creds,
5353 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5354 .bprm_set_security = selinux_bprm_set_security,
5355 .bprm_check_security = selinux_bprm_check_security,
5356 .bprm_secureexec = selinux_bprm_secureexec,
5357
5358 .sb_alloc_security = selinux_sb_alloc_security,
5359 .sb_free_security = selinux_sb_free_security,
5360 .sb_copy_data = selinux_sb_copy_data,
Eric Paris828dfe12008-04-17 13:17:49 -04005361 .sb_kern_mount = selinux_sb_kern_mount,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362 .sb_statfs = selinux_sb_statfs,
5363 .sb_mount = selinux_mount,
5364 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005365 .sb_get_mnt_opts = selinux_get_mnt_opts,
5366 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005367 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005368 .sb_parse_opts_str = selinux_parse_opts_str,
5369
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370
5371 .inode_alloc_security = selinux_inode_alloc_security,
5372 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005373 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 .inode_unlink = selinux_inode_unlink,
5377 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 .inode_rmdir = selinux_inode_rmdir,
5380 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 .inode_readlink = selinux_inode_readlink,
5383 .inode_follow_link = selinux_inode_follow_link,
5384 .inode_permission = selinux_inode_permission,
5385 .inode_setattr = selinux_inode_setattr,
5386 .inode_getattr = selinux_inode_getattr,
5387 .inode_setxattr = selinux_inode_setxattr,
5388 .inode_post_setxattr = selinux_inode_post_setxattr,
5389 .inode_getxattr = selinux_inode_getxattr,
5390 .inode_listxattr = selinux_inode_listxattr,
5391 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005392 .inode_getsecurity = selinux_inode_getsecurity,
5393 .inode_setsecurity = selinux_inode_setsecurity,
5394 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005395 .inode_need_killpriv = selinux_inode_need_killpriv,
5396 .inode_killpriv = selinux_inode_killpriv,
Eric Parisf5269712008-05-14 11:27:45 -04005397 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
5399 .file_permission = selinux_file_permission,
5400 .file_alloc_security = selinux_file_alloc_security,
5401 .file_free_security = selinux_file_free_security,
5402 .file_ioctl = selinux_file_ioctl,
5403 .file_mmap = selinux_file_mmap,
5404 .file_mprotect = selinux_file_mprotect,
5405 .file_lock = selinux_file_lock,
5406 .file_fcntl = selinux_file_fcntl,
5407 .file_set_fowner = selinux_file_set_fowner,
5408 .file_send_sigiotask = selinux_file_send_sigiotask,
5409 .file_receive = selinux_file_receive,
5410
Eric Paris828dfe12008-04-17 13:17:49 -04005411 .dentry_open = selinux_dentry_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005412
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413 .task_create = selinux_task_create,
5414 .task_alloc_security = selinux_task_alloc_security,
5415 .task_free_security = selinux_task_free_security,
5416 .task_setuid = selinux_task_setuid,
5417 .task_post_setuid = selinux_task_post_setuid,
5418 .task_setgid = selinux_task_setgid,
5419 .task_setpgid = selinux_task_setpgid,
5420 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005421 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005422 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423 .task_setgroups = selinux_task_setgroups,
5424 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005425 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005426 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 .task_setrlimit = selinux_task_setrlimit,
5428 .task_setscheduler = selinux_task_setscheduler,
5429 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005430 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 .task_kill = selinux_task_kill,
5432 .task_wait = selinux_task_wait,
5433 .task_prctl = selinux_task_prctl,
5434 .task_reparent_to_init = selinux_task_reparent_to_init,
Eric Paris828dfe12008-04-17 13:17:49 -04005435 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436
5437 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005438 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439
5440 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5441 .msg_msg_free_security = selinux_msg_msg_free_security,
5442
5443 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5444 .msg_queue_free_security = selinux_msg_queue_free_security,
5445 .msg_queue_associate = selinux_msg_queue_associate,
5446 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5447 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5448 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5449
5450 .shm_alloc_security = selinux_shm_alloc_security,
5451 .shm_free_security = selinux_shm_free_security,
5452 .shm_associate = selinux_shm_associate,
5453 .shm_shmctl = selinux_shm_shmctl,
5454 .shm_shmat = selinux_shm_shmat,
5455
Eric Paris828dfe12008-04-17 13:17:49 -04005456 .sem_alloc_security = selinux_sem_alloc_security,
5457 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458 .sem_associate = selinux_sem_associate,
5459 .sem_semctl = selinux_sem_semctl,
5460 .sem_semop = selinux_sem_semop,
5461
5462 .register_security = selinux_register_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463
Eric Paris828dfe12008-04-17 13:17:49 -04005464 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465
Eric Paris828dfe12008-04-17 13:17:49 -04005466 .getprocattr = selinux_getprocattr,
5467 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005469 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005470 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005471 .release_secctx = selinux_release_secctx,
5472
Eric Paris828dfe12008-04-17 13:17:49 -04005473 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474 .unix_may_send = selinux_socket_unix_may_send,
5475
5476 .socket_create = selinux_socket_create,
5477 .socket_post_create = selinux_socket_post_create,
5478 .socket_bind = selinux_socket_bind,
5479 .socket_connect = selinux_socket_connect,
5480 .socket_listen = selinux_socket_listen,
5481 .socket_accept = selinux_socket_accept,
5482 .socket_sendmsg = selinux_socket_sendmsg,
5483 .socket_recvmsg = selinux_socket_recvmsg,
5484 .socket_getsockname = selinux_socket_getsockname,
5485 .socket_getpeername = selinux_socket_getpeername,
5486 .socket_getsockopt = selinux_socket_getsockopt,
5487 .socket_setsockopt = selinux_socket_setsockopt,
5488 .socket_shutdown = selinux_socket_shutdown,
5489 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005490 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5491 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492 .sk_alloc_security = selinux_sk_alloc_security,
5493 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005494 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005495 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005496 .sock_graft = selinux_sock_graft,
5497 .inet_conn_request = selinux_inet_conn_request,
5498 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005499 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005500 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005501
5502#ifdef CONFIG_SECURITY_NETWORK_XFRM
5503 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5504 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5505 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005506 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005507 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5508 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005509 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005510 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005511 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005512 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005514
5515#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005516 .key_alloc = selinux_key_alloc,
5517 .key_free = selinux_key_free,
5518 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005519 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005520#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005521
5522#ifdef CONFIG_AUDIT
5523 .audit_rule_init = selinux_audit_rule_init,
5524 .audit_rule_known = selinux_audit_rule_known,
5525 .audit_rule_match = selinux_audit_rule_match,
5526 .audit_rule_free = selinux_audit_rule_free,
5527#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528};
5529
5530static __init int selinux_init(void)
5531{
5532 struct task_security_struct *tsec;
5533
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005534 if (!security_module_enable(&selinux_ops)) {
5535 selinux_enabled = 0;
5536 return 0;
5537 }
5538
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539 if (!selinux_enabled) {
5540 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5541 return 0;
5542 }
5543
5544 printk(KERN_INFO "SELinux: Initializing.\n");
5545
5546 /* Set the security state for the initial task. */
5547 if (task_alloc_security(current))
5548 panic("SELinux: Failed to initialize initial task.\n");
5549 tsec = current->security;
5550 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5551
James Morris7cae7e22006-03-22 00:09:22 -08005552 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5553 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005554 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 avc_init();
5556
5557 original_ops = secondary_ops = security_ops;
5558 if (!secondary_ops)
Eric Paris828dfe12008-04-17 13:17:49 -04005559 panic("SELinux: No initial security operations\n");
5560 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561 panic("SELinux: Unable to register with kernel.\n");
5562
Eric Paris828dfe12008-04-17 13:17:49 -04005563 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005564 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005565 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005566 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005567
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 return 0;
5569}
5570
5571void selinux_complete_init(void)
5572{
Eric Parisfadcdb42007-02-22 18:11:31 -05005573 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
5575 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005576 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005577 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 spin_lock(&sb_security_lock);
5579next_sb:
5580 if (!list_empty(&superblock_security_head)) {
5581 struct superblock_security_struct *sbsec =
5582 list_entry(superblock_security_head.next,
Eric Paris828dfe12008-04-17 13:17:49 -04005583 struct superblock_security_struct,
5584 list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005588 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589 down_read(&sb->s_umount);
5590 if (sb->s_root)
5591 superblock_doinit(sb, NULL);
5592 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005593 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594 spin_lock(&sb_security_lock);
5595 list_del_init(&sbsec->list);
5596 goto next_sb;
5597 }
5598 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005599 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600}
5601
5602/* SELinux requires early initialization in order to label
5603 all processes and objects when they are created. */
5604security_initcall(selinux_init);
5605
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005606#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607
Paul Mooreeffad8d2008-01-29 08:49:27 -05005608static struct nf_hook_ops selinux_ipv4_ops[] = {
5609 {
5610 .hook = selinux_ipv4_postroute,
5611 .owner = THIS_MODULE,
5612 .pf = PF_INET,
5613 .hooknum = NF_INET_POST_ROUTING,
5614 .priority = NF_IP_PRI_SELINUX_LAST,
5615 },
5616 {
5617 .hook = selinux_ipv4_forward,
5618 .owner = THIS_MODULE,
5619 .pf = PF_INET,
5620 .hooknum = NF_INET_FORWARD,
5621 .priority = NF_IP_PRI_SELINUX_FIRST,
5622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623};
5624
5625#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5626
Paul Mooreeffad8d2008-01-29 08:49:27 -05005627static struct nf_hook_ops selinux_ipv6_ops[] = {
5628 {
5629 .hook = selinux_ipv6_postroute,
5630 .owner = THIS_MODULE,
5631 .pf = PF_INET6,
5632 .hooknum = NF_INET_POST_ROUTING,
5633 .priority = NF_IP6_PRI_SELINUX_LAST,
5634 },
5635 {
5636 .hook = selinux_ipv6_forward,
5637 .owner = THIS_MODULE,
5638 .pf = PF_INET6,
5639 .hooknum = NF_INET_FORWARD,
5640 .priority = NF_IP6_PRI_SELINUX_FIRST,
5641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642};
5643
5644#endif /* IPV6 */
5645
5646static int __init selinux_nf_ip_init(void)
5647{
5648 int err = 0;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005649 u32 iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650
5651 if (!selinux_enabled)
5652 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005653
5654 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5655
Paul Mooreeffad8d2008-01-29 08:49:27 -05005656 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5657 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5658 if (err)
5659 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5660 err);
5661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662
5663#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005664 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5665 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5666 if (err)
5667 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5668 err);
5669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005671
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672out:
5673 return err;
5674}
5675
5676__initcall(selinux_nf_ip_init);
5677
5678#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5679static void selinux_nf_ip_exit(void)
5680{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005681 u32 iter;
5682
Eric Parisfadcdb42007-02-22 18:11:31 -05005683 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684
Paul Mooreeffad8d2008-01-29 08:49:27 -05005685 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5686 nf_unregister_hook(&selinux_ipv4_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005687#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005688 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5689 nf_unregister_hook(&selinux_ipv6_ops[iter]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690#endif /* IPV6 */
5691}
5692#endif
5693
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005694#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695
5696#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5697#define selinux_nf_ip_exit()
5698#endif
5699
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005700#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
5702#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005703static int selinux_disabled;
5704
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705int selinux_disable(void)
5706{
5707 extern void exit_sel_fs(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
5709 if (ss_initialized) {
5710 /* Not permitted after initial policy load. */
5711 return -EINVAL;
5712 }
5713
5714 if (selinux_disabled) {
5715 /* Only do this once. */
5716 return -EINVAL;
5717 }
5718
5719 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5720
5721 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005722 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723
5724 /* Reset security_ops to the secondary module, dummy or capability. */
5725 security_ops = secondary_ops;
5726
5727 /* Unregister netfilter hooks. */
5728 selinux_nf_ip_exit();
5729
5730 /* Unregister selinuxfs. */
5731 exit_sel_fs();
5732
5733 return 0;
5734}
5735#endif