blob: df9986940e9cffae0f020d3487559c21cecd7c5b [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.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreeffad8d2008-01-29 08:49:27 -050016 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
Eric Paris828dfe12008-04-17 13:17:49 -040017 * Paul Moore <paul.moore@hp.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070028#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/errno.h>
30#include <linux/sched.h>
31#include <linux/security.h>
32#include <linux/xattr.h>
33#include <linux/capability.h>
34#include <linux/unistd.h>
35#include <linux/mm.h>
36#include <linux/mman.h>
37#include <linux/slab.h>
38#include <linux/pagemap.h>
39#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/spinlock.h>
41#include <linux/syscalls.h>
42#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040043#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/namei.h>
45#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/netfilter_ipv4.h>
48#include <linux/netfilter_ipv6.h>
49#include <linux/tty.h>
50#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070051#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050053#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050054#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040055#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <asm/ioctls.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <asm/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#include <linux/bitops.h>
59#include <linux/interrupt.h>
60#include <linux/netdevice.h> /* for network interface checks */
61#include <linux/netlink.h>
62#include <linux/tcp.h>
63#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080064#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/quota.h>
66#include <linux/un.h> /* for Unix socket types */
67#include <net/af_unix.h> /* for Unix socket types */
68#include <linux/parser.h>
69#include <linux/nfs_mount.h>
70#include <net/ipv6.h>
71#include <linux/hugetlb.h>
72#include <linux/personality.h>
73#include <linux/sysctl.h>
74#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070075#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070076#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070077#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070078#include <linux/posix-timers.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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
James Morris6f0f0fd2008-07-10 17:02:07 +0900131/*
132 * Minimal support for a secondary security module,
133 * just to allow the use of the capability module.
134 */
Eric Paris828dfe12008-04-17 13:17:49 -0400135static struct security_operations *secondary_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137/* Lists of inode and superblock security structures initialized
138 before the policy was loaded. */
139static LIST_HEAD(superblock_security_head);
140static DEFINE_SPINLOCK(sb_security_lock);
141
Christoph Lametere18b8902006-12-06 20:33:20 -0800142static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800143
Paul Moored621d352008-01-29 08:43:36 -0500144/**
145 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
146 *
147 * Description:
148 * This function checks the SECMARK reference counter to see if any SECMARK
149 * targets are currently configured, if the reference counter is greater than
150 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
151 * enabled, false (0) if SECMARK is disabled.
152 *
153 */
154static int selinux_secmark_enabled(void)
155{
156 return (atomic_read(&selinux_secmark_refcount) > 0);
157}
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159/* Allocate and free functions for each kind of security blob. */
160
161static int task_alloc_security(struct task_struct *task)
162{
163 struct task_security_struct *tsec;
164
James Morris89d155e2005-10-30 14:59:21 -0800165 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 if (!tsec)
167 return -ENOMEM;
168
Roland McGrath03563572008-03-26 15:46:39 -0700169 tsec->osid = tsec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 task->security = tsec;
171
172 return 0;
173}
174
175static void task_free_security(struct task_struct *task)
176{
177 struct task_security_struct *tsec = task->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 task->security = NULL;
179 kfree(tsec);
180}
181
182static int inode_alloc_security(struct inode *inode)
183{
184 struct task_security_struct *tsec = current->security;
185 struct inode_security_struct *isec;
186
Josef Bacika02fe132008-04-04 09:35:05 +1100187 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 if (!isec)
189 return -ENOMEM;
190
Eric Paris23970742006-09-25 23:32:01 -0700191 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 isec->inode = inode;
194 isec->sid = SECINITSID_UNLABELED;
195 isec->sclass = SECCLASS_FILE;
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800196 isec->task_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 inode->i_security = isec;
198
199 return 0;
200}
201
202static void inode_free_security(struct inode *inode)
203{
204 struct inode_security_struct *isec = inode->i_security;
205 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
206
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 spin_lock(&sbsec->isec_lock);
208 if (!list_empty(&isec->list))
209 list_del_init(&isec->list);
210 spin_unlock(&sbsec->isec_lock);
211
212 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800213 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214}
215
216static int file_alloc_security(struct file *file)
217{
218 struct task_security_struct *tsec = current->security;
219 struct file_security_struct *fsec;
220
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800221 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 if (!fsec)
223 return -ENOMEM;
224
Stephen Smalley9ac49d22006-02-01 03:05:56 -0800225 fsec->sid = tsec->sid;
226 fsec->fown_sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 file->f_security = fsec;
228
229 return 0;
230}
231
232static void file_free_security(struct file *file)
233{
234 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 file->f_security = NULL;
236 kfree(fsec);
237}
238
239static int superblock_alloc_security(struct super_block *sb)
240{
241 struct superblock_security_struct *sbsec;
242
James Morris89d155e2005-10-30 14:59:21 -0800243 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (!sbsec)
245 return -ENOMEM;
246
Eric Parisbc7e9822006-09-25 23:32:02 -0700247 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 INIT_LIST_HEAD(&sbsec->list);
249 INIT_LIST_HEAD(&sbsec->isec_head);
250 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 sbsec->sb = sb;
252 sbsec->sid = SECINITSID_UNLABELED;
253 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700254 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 sb->s_security = sbsec;
256
257 return 0;
258}
259
260static void superblock_free_security(struct super_block *sb)
261{
262 struct superblock_security_struct *sbsec = sb->s_security;
263
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 spin_lock(&sb_security_lock);
265 if (!list_empty(&sbsec->list))
266 list_del_init(&sbsec->list);
267 spin_unlock(&sb_security_lock);
268
269 sb->s_security = NULL;
270 kfree(sbsec);
271}
272
Al Viro7d877f32005-10-21 03:20:43 -0400273static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274{
275 struct sk_security_struct *ssec;
276
James Morris89d155e2005-10-30 14:59:21 -0800277 ssec = kzalloc(sizeof(*ssec), priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 if (!ssec)
279 return -ENOMEM;
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 ssec->peer_sid = SECINITSID_UNLABELED;
Venkat Yekkirala892c1412006-08-04 23:08:56 -0700282 ssec->sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 sk->sk_security = ssec;
284
Paul Mooref74af6e2008-02-25 11:40:33 -0500285 selinux_netlbl_sk_security_reset(ssec, family);
Paul Moore99f59ed2006-08-29 17:53:48 -0700286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 return 0;
288}
289
290static void sk_free_security(struct sock *sk)
291{
292 struct sk_security_struct *ssec = sk->sk_security;
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 sk->sk_security = NULL;
Paul Moore6c5b3fc2008-10-10 10:16:33 -0400295 selinux_netlbl_sk_security_free(ssec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 kfree(ssec);
297}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299/* The security server must be initialized before
300 any labeling or access decisions can be provided. */
301extern int ss_initialized;
302
303/* The file system's label must be initialized prior to use. */
304
305static char *labeling_behaviors[6] = {
306 "uses xattr",
307 "uses transition SIDs",
308 "uses task SIDs",
309 "uses genfs_contexts",
310 "not configured for labeling",
311 "uses mountpoint labeling",
312};
313
314static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
315
316static inline int inode_doinit(struct inode *inode)
317{
318 return inode_doinit_with_dentry(inode, NULL);
319}
320
321enum {
Eric Paris31e87932007-09-19 17:19:12 -0400322 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 Opt_context = 1,
324 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500325 Opt_defcontext = 3,
326 Opt_rootcontext = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327};
328
Steven Whitehousea447c092008-10-13 10:46:57 +0100329static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400330 {Opt_context, CONTEXT_STR "%s"},
331 {Opt_fscontext, FSCONTEXT_STR "%s"},
332 {Opt_defcontext, DEFCONTEXT_STR "%s"},
333 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
Eric Paris31e87932007-09-19 17:19:12 -0400334 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335};
336
337#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
338
Eric Parisc312feb2006-07-10 04:43:53 -0700339static int may_context_mount_sb_relabel(u32 sid,
340 struct superblock_security_struct *sbsec,
341 struct task_security_struct *tsec)
342{
343 int rc;
344
345 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
346 FILESYSTEM__RELABELFROM, NULL);
347 if (rc)
348 return rc;
349
350 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
351 FILESYSTEM__RELABELTO, NULL);
352 return rc;
353}
354
Eric Paris08089252006-07-10 04:43:55 -0700355static int may_context_mount_inode_relabel(u32 sid,
356 struct superblock_security_struct *sbsec,
357 struct task_security_struct *tsec)
358{
359 int rc;
360 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
361 FILESYSTEM__RELABELFROM, NULL);
362 if (rc)
363 return rc;
364
365 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
366 FILESYSTEM__ASSOCIATE, NULL);
367 return rc;
368}
369
Eric Parisc9180a52007-11-30 13:00:35 -0500370static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371{
372 struct superblock_security_struct *sbsec = sb->s_security;
373 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500374 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 int rc = 0;
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
378 /* Make sure that the xattr handler exists and that no
379 error other than -ENODATA is returned by getxattr on
380 the root directory. -ENODATA is ok, as this may be
381 the first boot of the SELinux kernel before we have
382 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500383 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
385 "xattr support\n", sb->s_id, sb->s_type->name);
386 rc = -EOPNOTSUPP;
387 goto out;
388 }
Eric Parisc9180a52007-11-30 13:00:35 -0500389 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 if (rc < 0 && rc != -ENODATA) {
391 if (rc == -EOPNOTSUPP)
392 printk(KERN_WARNING "SELinux: (dev %s, type "
393 "%s) has no security xattr handler\n",
394 sb->s_id, sb->s_type->name);
395 else
396 printk(KERN_WARNING "SELinux: (dev %s, type "
397 "%s) getxattr errno %d\n", sb->s_id,
398 sb->s_type->name, -rc);
399 goto out;
400 }
401 }
402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 sbsec->initialized = 1;
404
Eric Parisc9180a52007-11-30 13:00:35 -0500405 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500406 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500408 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500409 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 sb->s_id, sb->s_type->name,
411 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
413 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500414 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 /* Initialize any other inodes associated with the superblock, e.g.
417 inodes created prior to initial policy load or inodes created
418 during get_sb by a pseudo filesystem that directly
419 populates itself. */
420 spin_lock(&sbsec->isec_lock);
421next_inode:
422 if (!list_empty(&sbsec->isec_head)) {
423 struct inode_security_struct *isec =
424 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500425 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 struct inode *inode = isec->inode;
427 spin_unlock(&sbsec->isec_lock);
428 inode = igrab(inode);
429 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500430 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 inode_doinit(inode);
432 iput(inode);
433 }
434 spin_lock(&sbsec->isec_lock);
435 list_del_init(&isec->list);
436 goto next_inode;
437 }
438 spin_unlock(&sbsec->isec_lock);
439out:
Eric Parisc9180a52007-11-30 13:00:35 -0500440 return rc;
441}
442
443/*
444 * This function should allow an FS to ask what it's mount security
445 * options were so it can use those later for submounts, displaying
446 * mount options, or whatever.
447 */
448static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500449 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500450{
451 int rc = 0, i;
452 struct superblock_security_struct *sbsec = sb->s_security;
453 char *context = NULL;
454 u32 len;
455 char tmp;
456
Eric Parise0007522008-03-05 10:31:54 -0500457 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500458
459 if (!sbsec->initialized)
460 return -EINVAL;
461
462 if (!ss_initialized)
463 return -EINVAL;
464
465 /*
466 * if we ever use sbsec flags for anything other than tracking mount
467 * settings this is going to need a mask
468 */
469 tmp = sbsec->flags;
470 /* count the number of mount options for this sb */
471 for (i = 0; i < 8; i++) {
472 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500473 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500474 tmp >>= 1;
475 }
476
Eric Parise0007522008-03-05 10:31:54 -0500477 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
478 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500479 rc = -ENOMEM;
480 goto out_free;
481 }
482
Eric Parise0007522008-03-05 10:31:54 -0500483 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
484 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500485 rc = -ENOMEM;
486 goto out_free;
487 }
488
489 i = 0;
490 if (sbsec->flags & FSCONTEXT_MNT) {
491 rc = security_sid_to_context(sbsec->sid, &context, &len);
492 if (rc)
493 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500494 opts->mnt_opts[i] = context;
495 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500496 }
497 if (sbsec->flags & CONTEXT_MNT) {
498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
499 if (rc)
500 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500501 opts->mnt_opts[i] = context;
502 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500503 }
504 if (sbsec->flags & DEFCONTEXT_MNT) {
505 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
506 if (rc)
507 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500508 opts->mnt_opts[i] = context;
509 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500510 }
511 if (sbsec->flags & ROOTCONTEXT_MNT) {
512 struct inode *root = sbsec->sb->s_root->d_inode;
513 struct inode_security_struct *isec = root->i_security;
514
515 rc = security_sid_to_context(isec->sid, &context, &len);
516 if (rc)
517 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500518 opts->mnt_opts[i] = context;
519 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500520 }
521
Eric Parise0007522008-03-05 10:31:54 -0500522 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500523
524 return 0;
525
526out_free:
Eric Parise0007522008-03-05 10:31:54 -0500527 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500528 return rc;
529}
530
531static int bad_option(struct superblock_security_struct *sbsec, char flag,
532 u32 old_sid, u32 new_sid)
533{
534 /* check if the old mount command had the same options */
535 if (sbsec->initialized)
536 if (!(sbsec->flags & flag) ||
537 (old_sid != new_sid))
538 return 1;
539
540 /* check if we were passed the same options twice,
541 * aka someone passed context=a,context=b
542 */
543 if (!sbsec->initialized)
544 if (sbsec->flags & flag)
545 return 1;
546 return 0;
547}
Eric Parise0007522008-03-05 10:31:54 -0500548
Eric Parisc9180a52007-11-30 13:00:35 -0500549/*
550 * Allow filesystems with binary mount data to explicitly set mount point
551 * labeling information.
552 */
Eric Parise0007522008-03-05 10:31:54 -0500553static int selinux_set_mnt_opts(struct super_block *sb,
554 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500555{
556 int rc = 0, i;
557 struct task_security_struct *tsec = current->security;
558 struct superblock_security_struct *sbsec = sb->s_security;
559 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000560 struct inode *inode = sbsec->sb->s_root->d_inode;
561 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500562 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
563 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500564 char **mount_options = opts->mnt_opts;
565 int *flags = opts->mnt_opts_flags;
566 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500567
568 mutex_lock(&sbsec->lock);
569
570 if (!ss_initialized) {
571 if (!num_opts) {
572 /* Defer initialization until selinux_complete_init,
573 after the initial policy is loaded and the security
574 server is ready to handle calls. */
575 spin_lock(&sb_security_lock);
576 if (list_empty(&sbsec->list))
577 list_add(&sbsec->list, &superblock_security_head);
578 spin_unlock(&sb_security_lock);
579 goto out;
580 }
581 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400582 printk(KERN_WARNING "SELinux: Unable to set superblock options "
583 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500584 goto out;
585 }
586
587 /*
Eric Parise0007522008-03-05 10:31:54 -0500588 * Binary mount data FS will come through this function twice. Once
589 * from an explicit call and once from the generic calls from the vfs.
590 * Since the generic VFS calls will not contain any security mount data
591 * we need to skip the double mount verification.
592 *
593 * This does open a hole in which we will not notice if the first
594 * mount using this sb set explict options and a second mount using
595 * this sb does not set any security options. (The first options
596 * will be used for both mounts)
597 */
598 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
599 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400600 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500601
602 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500603 * parse the mount options, check if they are valid sids.
604 * also check if someone is trying to mount the same sb more
605 * than once with different security options.
606 */
607 for (i = 0; i < num_opts; i++) {
608 u32 sid;
609 rc = security_context_to_sid(mount_options[i],
610 strlen(mount_options[i]), &sid);
611 if (rc) {
612 printk(KERN_WARNING "SELinux: security_context_to_sid"
613 "(%s) failed for (dev %s, type %s) errno=%d\n",
614 mount_options[i], sb->s_id, name, rc);
615 goto out;
616 }
617 switch (flags[i]) {
618 case FSCONTEXT_MNT:
619 fscontext_sid = sid;
620
621 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
622 fscontext_sid))
623 goto out_double_mount;
624
625 sbsec->flags |= FSCONTEXT_MNT;
626 break;
627 case CONTEXT_MNT:
628 context_sid = sid;
629
630 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
631 context_sid))
632 goto out_double_mount;
633
634 sbsec->flags |= CONTEXT_MNT;
635 break;
636 case ROOTCONTEXT_MNT:
637 rootcontext_sid = sid;
638
639 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
640 rootcontext_sid))
641 goto out_double_mount;
642
643 sbsec->flags |= ROOTCONTEXT_MNT;
644
645 break;
646 case DEFCONTEXT_MNT:
647 defcontext_sid = sid;
648
649 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
650 defcontext_sid))
651 goto out_double_mount;
652
653 sbsec->flags |= DEFCONTEXT_MNT;
654
655 break;
656 default:
657 rc = -EINVAL;
658 goto out;
659 }
660 }
661
662 if (sbsec->initialized) {
663 /* previously mounted with options, but not on this attempt? */
664 if (sbsec->flags && !num_opts)
665 goto out_double_mount;
666 rc = 0;
667 goto out;
668 }
669
James Morris089be432008-07-15 18:32:49 +1000670 if (strcmp(sb->s_type->name, "proc") == 0)
Eric Parisc9180a52007-11-30 13:00:35 -0500671 sbsec->proc = 1;
672
673 /* Determine the labeling behavior to use for this filesystem type. */
James Morris089be432008-07-15 18:32:49 +1000674 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500675 if (rc) {
676 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000677 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500678 goto out;
679 }
680
681 /* sets the context of the superblock for the fs being mounted. */
682 if (fscontext_sid) {
683
684 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
685 if (rc)
686 goto out;
687
688 sbsec->sid = fscontext_sid;
689 }
690
691 /*
692 * Switch to using mount point labeling behavior.
693 * sets the label used on all file below the mountpoint, and will set
694 * the superblock context if not already set.
695 */
696 if (context_sid) {
697 if (!fscontext_sid) {
698 rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
699 if (rc)
700 goto out;
701 sbsec->sid = context_sid;
702 } else {
703 rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
704 if (rc)
705 goto out;
706 }
707 if (!rootcontext_sid)
708 rootcontext_sid = context_sid;
709
710 sbsec->mntpoint_sid = context_sid;
711 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
712 }
713
714 if (rootcontext_sid) {
715 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
716 if (rc)
717 goto out;
718
719 root_isec->sid = rootcontext_sid;
720 root_isec->initialized = 1;
721 }
722
723 if (defcontext_sid) {
724 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
725 rc = -EINVAL;
726 printk(KERN_WARNING "SELinux: defcontext option is "
727 "invalid for this filesystem type\n");
728 goto out;
729 }
730
731 if (defcontext_sid != sbsec->def_sid) {
732 rc = may_context_mount_inode_relabel(defcontext_sid,
733 sbsec, tsec);
734 if (rc)
735 goto out;
736 }
737
738 sbsec->def_sid = defcontext_sid;
739 }
740
741 rc = sb_finish_set_opts(sb);
742out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700743 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500745out_double_mount:
746 rc = -EINVAL;
747 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
748 "security settings for (dev %s, type %s)\n", sb->s_id, name);
749 goto out;
750}
751
752static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
753 struct super_block *newsb)
754{
755 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
756 struct superblock_security_struct *newsbsec = newsb->s_security;
757
758 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
759 int set_context = (oldsbsec->flags & CONTEXT_MNT);
760 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
761
Eric Paris0f5e6422008-04-21 16:24:11 -0400762 /*
763 * if the parent was able to be mounted it clearly had no special lsm
764 * mount options. thus we can safely put this sb on the list and deal
765 * with it later
766 */
767 if (!ss_initialized) {
768 spin_lock(&sb_security_lock);
769 if (list_empty(&newsbsec->list))
770 list_add(&newsbsec->list, &superblock_security_head);
771 spin_unlock(&sb_security_lock);
772 return;
773 }
Eric Parisc9180a52007-11-30 13:00:35 -0500774
Eric Parisc9180a52007-11-30 13:00:35 -0500775 /* how can we clone if the old one wasn't set up?? */
776 BUG_ON(!oldsbsec->initialized);
777
Eric Paris5a552612008-04-09 14:08:35 -0400778 /* if fs is reusing a sb, just let its options stand... */
779 if (newsbsec->initialized)
780 return;
781
Eric Parisc9180a52007-11-30 13:00:35 -0500782 mutex_lock(&newsbsec->lock);
783
784 newsbsec->flags = oldsbsec->flags;
785
786 newsbsec->sid = oldsbsec->sid;
787 newsbsec->def_sid = oldsbsec->def_sid;
788 newsbsec->behavior = oldsbsec->behavior;
789
790 if (set_context) {
791 u32 sid = oldsbsec->mntpoint_sid;
792
793 if (!set_fscontext)
794 newsbsec->sid = sid;
795 if (!set_rootcontext) {
796 struct inode *newinode = newsb->s_root->d_inode;
797 struct inode_security_struct *newisec = newinode->i_security;
798 newisec->sid = sid;
799 }
800 newsbsec->mntpoint_sid = sid;
801 }
802 if (set_rootcontext) {
803 const struct inode *oldinode = oldsb->s_root->d_inode;
804 const struct inode_security_struct *oldisec = oldinode->i_security;
805 struct inode *newinode = newsb->s_root->d_inode;
806 struct inode_security_struct *newisec = newinode->i_security;
807
808 newisec->sid = oldisec->sid;
809 }
810
811 sb_finish_set_opts(newsb);
812 mutex_unlock(&newsbsec->lock);
813}
814
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200815static int selinux_parse_opts_str(char *options,
816 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500817{
Eric Parise0007522008-03-05 10:31:54 -0500818 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500819 char *context = NULL, *defcontext = NULL;
820 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500821 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500822
Eric Parise0007522008-03-05 10:31:54 -0500823 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500824
825 /* Standard string-based options. */
826 while ((p = strsep(&options, "|")) != NULL) {
827 int token;
828 substring_t args[MAX_OPT_ARGS];
829
830 if (!*p)
831 continue;
832
833 token = match_token(p, tokens, args);
834
835 switch (token) {
836 case Opt_context:
837 if (context || defcontext) {
838 rc = -EINVAL;
839 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
840 goto out_err;
841 }
842 context = match_strdup(&args[0]);
843 if (!context) {
844 rc = -ENOMEM;
845 goto out_err;
846 }
847 break;
848
849 case Opt_fscontext:
850 if (fscontext) {
851 rc = -EINVAL;
852 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
853 goto out_err;
854 }
855 fscontext = match_strdup(&args[0]);
856 if (!fscontext) {
857 rc = -ENOMEM;
858 goto out_err;
859 }
860 break;
861
862 case Opt_rootcontext:
863 if (rootcontext) {
864 rc = -EINVAL;
865 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
866 goto out_err;
867 }
868 rootcontext = match_strdup(&args[0]);
869 if (!rootcontext) {
870 rc = -ENOMEM;
871 goto out_err;
872 }
873 break;
874
875 case Opt_defcontext:
876 if (context || defcontext) {
877 rc = -EINVAL;
878 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
879 goto out_err;
880 }
881 defcontext = match_strdup(&args[0]);
882 if (!defcontext) {
883 rc = -ENOMEM;
884 goto out_err;
885 }
886 break;
887
888 default:
889 rc = -EINVAL;
890 printk(KERN_WARNING "SELinux: unknown mount option\n");
891 goto out_err;
892
893 }
894 }
895
Eric Parise0007522008-03-05 10:31:54 -0500896 rc = -ENOMEM;
897 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
898 if (!opts->mnt_opts)
899 goto out_err;
900
901 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
902 if (!opts->mnt_opts_flags) {
903 kfree(opts->mnt_opts);
904 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500905 }
906
Eric Parise0007522008-03-05 10:31:54 -0500907 if (fscontext) {
908 opts->mnt_opts[num_mnt_opts] = fscontext;
909 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
910 }
911 if (context) {
912 opts->mnt_opts[num_mnt_opts] = context;
913 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
914 }
915 if (rootcontext) {
916 opts->mnt_opts[num_mnt_opts] = rootcontext;
917 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
918 }
919 if (defcontext) {
920 opts->mnt_opts[num_mnt_opts] = defcontext;
921 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
922 }
923
924 opts->num_mnt_opts = num_mnt_opts;
925 return 0;
926
Eric Parisc9180a52007-11-30 13:00:35 -0500927out_err:
928 kfree(context);
929 kfree(defcontext);
930 kfree(fscontext);
931 kfree(rootcontext);
932 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
Eric Parise0007522008-03-05 10:31:54 -0500934/*
935 * string mount options parsing and call set the sbsec
936 */
937static int superblock_doinit(struct super_block *sb, void *data)
938{
939 int rc = 0;
940 char *options = data;
941 struct security_mnt_opts opts;
942
943 security_init_mnt_opts(&opts);
944
945 if (!data)
946 goto out;
947
948 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
949
950 rc = selinux_parse_opts_str(options, &opts);
951 if (rc)
952 goto out_err;
953
954out:
955 rc = selinux_set_mnt_opts(sb, &opts);
956
957out_err:
958 security_free_mnt_opts(&opts);
959 return rc;
960}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
Adrian Bunk3583a712008-07-22 20:21:23 +0300962static void selinux_write_opts(struct seq_file *m,
963 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000964{
965 int i;
966 char *prefix;
967
968 for (i = 0; i < opts->num_mnt_opts; i++) {
969 char *has_comma = strchr(opts->mnt_opts[i], ',');
970
971 switch (opts->mnt_opts_flags[i]) {
972 case CONTEXT_MNT:
973 prefix = CONTEXT_STR;
974 break;
975 case FSCONTEXT_MNT:
976 prefix = FSCONTEXT_STR;
977 break;
978 case ROOTCONTEXT_MNT:
979 prefix = ROOTCONTEXT_STR;
980 break;
981 case DEFCONTEXT_MNT:
982 prefix = DEFCONTEXT_STR;
983 break;
984 default:
985 BUG();
986 };
987 /* we need a comma before each option */
988 seq_putc(m, ',');
989 seq_puts(m, prefix);
990 if (has_comma)
991 seq_putc(m, '\"');
992 seq_puts(m, opts->mnt_opts[i]);
993 if (has_comma)
994 seq_putc(m, '\"');
995 }
996}
997
998static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
999{
1000 struct security_mnt_opts opts;
1001 int rc;
1002
1003 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001004 if (rc) {
1005 /* before policy load we may get EINVAL, don't show anything */
1006 if (rc == -EINVAL)
1007 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001008 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001009 }
Eric Paris2069f452008-07-04 09:47:13 +10001010
1011 selinux_write_opts(m, &opts);
1012
1013 security_free_mnt_opts(&opts);
1014
1015 return rc;
1016}
1017
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018static inline u16 inode_mode_to_security_class(umode_t mode)
1019{
1020 switch (mode & S_IFMT) {
1021 case S_IFSOCK:
1022 return SECCLASS_SOCK_FILE;
1023 case S_IFLNK:
1024 return SECCLASS_LNK_FILE;
1025 case S_IFREG:
1026 return SECCLASS_FILE;
1027 case S_IFBLK:
1028 return SECCLASS_BLK_FILE;
1029 case S_IFDIR:
1030 return SECCLASS_DIR;
1031 case S_IFCHR:
1032 return SECCLASS_CHR_FILE;
1033 case S_IFIFO:
1034 return SECCLASS_FIFO_FILE;
1035
1036 }
1037
1038 return SECCLASS_FILE;
1039}
1040
James Morris13402582005-09-30 14:24:34 -04001041static inline int default_protocol_stream(int protocol)
1042{
1043 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1044}
1045
1046static inline int default_protocol_dgram(int protocol)
1047{
1048 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1049}
1050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1052{
1053 switch (family) {
1054 case PF_UNIX:
1055 switch (type) {
1056 case SOCK_STREAM:
1057 case SOCK_SEQPACKET:
1058 return SECCLASS_UNIX_STREAM_SOCKET;
1059 case SOCK_DGRAM:
1060 return SECCLASS_UNIX_DGRAM_SOCKET;
1061 }
1062 break;
1063 case PF_INET:
1064 case PF_INET6:
1065 switch (type) {
1066 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001067 if (default_protocol_stream(protocol))
1068 return SECCLASS_TCP_SOCKET;
1069 else
1070 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001072 if (default_protocol_dgram(protocol))
1073 return SECCLASS_UDP_SOCKET;
1074 else
1075 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001076 case SOCK_DCCP:
1077 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001078 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 return SECCLASS_RAWIP_SOCKET;
1080 }
1081 break;
1082 case PF_NETLINK:
1083 switch (protocol) {
1084 case NETLINK_ROUTE:
1085 return SECCLASS_NETLINK_ROUTE_SOCKET;
1086 case NETLINK_FIREWALL:
1087 return SECCLASS_NETLINK_FIREWALL_SOCKET;
James Morris216efaa2005-08-15 20:34:48 -07001088 case NETLINK_INET_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1090 case NETLINK_NFLOG:
1091 return SECCLASS_NETLINK_NFLOG_SOCKET;
1092 case NETLINK_XFRM:
1093 return SECCLASS_NETLINK_XFRM_SOCKET;
1094 case NETLINK_SELINUX:
1095 return SECCLASS_NETLINK_SELINUX_SOCKET;
1096 case NETLINK_AUDIT:
1097 return SECCLASS_NETLINK_AUDIT_SOCKET;
1098 case NETLINK_IP6_FW:
1099 return SECCLASS_NETLINK_IP6FW_SOCKET;
1100 case NETLINK_DNRTMSG:
1101 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001102 case NETLINK_KOBJECT_UEVENT:
1103 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 default:
1105 return SECCLASS_NETLINK_SOCKET;
1106 }
1107 case PF_PACKET:
1108 return SECCLASS_PACKET_SOCKET;
1109 case PF_KEY:
1110 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001111 case PF_APPLETALK:
1112 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
1114
1115 return SECCLASS_SOCKET;
1116}
1117
1118#ifdef CONFIG_PROC_FS
1119static int selinux_proc_get_sid(struct proc_dir_entry *de,
1120 u16 tclass,
1121 u32 *sid)
1122{
1123 int buflen, rc;
1124 char *buffer, *path, *end;
1125
Eric Paris828dfe12008-04-17 13:17:49 -04001126 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 if (!buffer)
1128 return -ENOMEM;
1129
1130 buflen = PAGE_SIZE;
1131 end = buffer+buflen;
1132 *--end = '\0';
1133 buflen--;
1134 path = end-1;
1135 *path = '/';
1136 while (de && de != de->parent) {
1137 buflen -= de->namelen + 1;
1138 if (buflen < 0)
1139 break;
1140 end -= de->namelen;
1141 memcpy(end, de->name, de->namelen);
1142 *--end = '/';
1143 path = end;
1144 de = de->parent;
1145 }
1146 rc = security_genfs_sid("proc", path, tclass, sid);
1147 free_page((unsigned long)buffer);
1148 return rc;
1149}
1150#else
1151static int selinux_proc_get_sid(struct proc_dir_entry *de,
1152 u16 tclass,
1153 u32 *sid)
1154{
1155 return -EINVAL;
1156}
1157#endif
1158
1159/* The inode's security attributes must be initialized before first use. */
1160static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1161{
1162 struct superblock_security_struct *sbsec = NULL;
1163 struct inode_security_struct *isec = inode->i_security;
1164 u32 sid;
1165 struct dentry *dentry;
1166#define INITCONTEXTLEN 255
1167 char *context = NULL;
1168 unsigned len = 0;
1169 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171 if (isec->initialized)
1172 goto out;
1173
Eric Paris23970742006-09-25 23:32:01 -07001174 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001176 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 sbsec = inode->i_sb->s_security;
1179 if (!sbsec->initialized) {
1180 /* Defer initialization until selinux_complete_init,
1181 after the initial policy is loaded and the security
1182 server is ready to handle calls. */
1183 spin_lock(&sbsec->isec_lock);
1184 if (list_empty(&isec->list))
1185 list_add(&isec->list, &sbsec->isec_head);
1186 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001187 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189
1190 switch (sbsec->behavior) {
1191 case SECURITY_FS_USE_XATTR:
1192 if (!inode->i_op->getxattr) {
1193 isec->sid = sbsec->def_sid;
1194 break;
1195 }
1196
1197 /* Need a dentry, since the xattr API requires one.
1198 Life would be simpler if we could just pass the inode. */
1199 if (opt_dentry) {
1200 /* Called from d_instantiate or d_splice_alias. */
1201 dentry = dget(opt_dentry);
1202 } else {
1203 /* Called from selinux_complete_init, try to find a dentry. */
1204 dentry = d_find_alias(inode);
1205 }
1206 if (!dentry) {
Eric Paris744ba352008-04-17 11:52:44 -04001207 printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001208 "ino=%ld\n", __func__, inode->i_sb->s_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 inode->i_ino);
Eric Paris23970742006-09-25 23:32:01 -07001210 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 }
1212
1213 len = INITCONTEXTLEN;
Stephen Smalley869ab512008-04-04 08:46:05 -04001214 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (!context) {
1216 rc = -ENOMEM;
1217 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001218 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 }
1220 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1221 context, len);
1222 if (rc == -ERANGE) {
1223 /* Need a larger buffer. Query for the right size. */
1224 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1225 NULL, 0);
1226 if (rc < 0) {
1227 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001228 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 }
1230 kfree(context);
1231 len = rc;
Stephen Smalley869ab512008-04-04 08:46:05 -04001232 context = kmalloc(len, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 if (!context) {
1234 rc = -ENOMEM;
1235 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001236 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 }
1238 rc = inode->i_op->getxattr(dentry,
1239 XATTR_NAME_SELINUX,
1240 context, len);
1241 }
1242 dput(dentry);
1243 if (rc < 0) {
1244 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001245 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001246 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 -rc, inode->i_sb->s_id, inode->i_ino);
1248 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001249 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 }
1251 /* Map ENODATA to the default file SID */
1252 sid = sbsec->def_sid;
1253 rc = 0;
1254 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001255 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001256 sbsec->def_sid,
1257 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 if (rc) {
Eric Paris744ba352008-04-17 11:52:44 -04001259 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 "returned %d for dev=%s ino=%ld\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001261 __func__, context, -rc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 inode->i_sb->s_id, inode->i_ino);
1263 kfree(context);
1264 /* Leave with the unlabeled SID */
1265 rc = 0;
1266 break;
1267 }
1268 }
1269 kfree(context);
1270 isec->sid = sid;
1271 break;
1272 case SECURITY_FS_USE_TASK:
1273 isec->sid = isec->task_sid;
1274 break;
1275 case SECURITY_FS_USE_TRANS:
1276 /* Default to the fs SID. */
1277 isec->sid = sbsec->sid;
1278
1279 /* Try to obtain a transition SID. */
1280 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1281 rc = security_transition_sid(isec->task_sid,
1282 sbsec->sid,
1283 isec->sclass,
1284 &sid);
1285 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001286 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 isec->sid = sid;
1288 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001289 case SECURITY_FS_USE_MNTPOINT:
1290 isec->sid = sbsec->mntpoint_sid;
1291 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001293 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 isec->sid = sbsec->sid;
1295
Stephen Smalleyea6b1842008-09-22 15:41:19 -04001296 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 struct proc_inode *proci = PROC_I(inode);
1298 if (proci->pde) {
1299 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1300 rc = selinux_proc_get_sid(proci->pde,
1301 isec->sclass,
1302 &sid);
1303 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001304 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 isec->sid = sid;
1306 }
1307 }
1308 break;
1309 }
1310
1311 isec->initialized = 1;
1312
Eric Paris23970742006-09-25 23:32:01 -07001313out_unlock:
1314 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315out:
1316 if (isec->sclass == SECCLASS_FILE)
1317 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 return rc;
1319}
1320
1321/* Convert a Linux signal to an access vector. */
1322static inline u32 signal_to_av(int sig)
1323{
1324 u32 perm = 0;
1325
1326 switch (sig) {
1327 case SIGCHLD:
1328 /* Commonly granted from child to parent. */
1329 perm = PROCESS__SIGCHLD;
1330 break;
1331 case SIGKILL:
1332 /* Cannot be caught or ignored */
1333 perm = PROCESS__SIGKILL;
1334 break;
1335 case SIGSTOP:
1336 /* Cannot be caught or ignored */
1337 perm = PROCESS__SIGSTOP;
1338 break;
1339 default:
1340 /* All other signals. */
1341 perm = PROCESS__SIGNAL;
1342 break;
1343 }
1344
1345 return perm;
1346}
1347
1348/* Check permission betweeen a pair of tasks, e.g. signal checks,
1349 fork check, ptrace check, etc. */
1350static int task_has_perm(struct task_struct *tsk1,
1351 struct task_struct *tsk2,
1352 u32 perms)
1353{
1354 struct task_security_struct *tsec1, *tsec2;
1355
1356 tsec1 = tsk1->security;
1357 tsec2 = tsk2->security;
1358 return avc_has_perm(tsec1->sid, tsec2->sid,
1359 SECCLASS_PROCESS, perms, NULL);
1360}
1361
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001362#if CAP_LAST_CAP > 63
1363#error Fix SELinux to handle capabilities > 63.
1364#endif
1365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366/* Check whether a task is allowed to use a capability. */
1367static int task_has_capability(struct task_struct *tsk,
Eric Paris06112162008-11-11 22:02:50 +11001368 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 struct task_security_struct *tsec;
1371 struct avc_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001372 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001373 u16 sclass;
1374 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001375 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
1377 tsec = tsk->security;
1378
Eric Paris828dfe12008-04-17 13:17:49 -04001379 AVC_AUDIT_DATA_INIT(&ad, CAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 ad.tsk = tsk;
1381 ad.u.cap = cap;
1382
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001383 switch (CAP_TO_INDEX(cap)) {
1384 case 0:
1385 sclass = SECCLASS_CAPABILITY;
1386 break;
1387 case 1:
1388 sclass = SECCLASS_CAPABILITY2;
1389 break;
1390 default:
1391 printk(KERN_ERR
1392 "SELinux: out of range capability %d\n", cap);
1393 BUG();
1394 }
Eric Paris06112162008-11-11 22:02:50 +11001395
1396 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, sclass, av, 0, &avd);
1397 if (audit == SECURITY_CAP_AUDIT)
1398 avc_audit(tsec->sid, tsec->sid, sclass, av, &avd, rc, &ad);
1399 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400}
1401
1402/* Check whether a task is allowed to use a system operation. */
1403static int task_has_system(struct task_struct *tsk,
1404 u32 perms)
1405{
1406 struct task_security_struct *tsec;
1407
1408 tsec = tsk->security;
1409
1410 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
1411 SECCLASS_SYSTEM, perms, NULL);
1412}
1413
1414/* Check whether a task has a particular permission to an inode.
1415 The 'adp' parameter is optional and allows other audit
1416 data to be passed (e.g. the dentry). */
1417static int inode_has_perm(struct task_struct *tsk,
1418 struct inode *inode,
1419 u32 perms,
1420 struct avc_audit_data *adp)
1421{
1422 struct task_security_struct *tsec;
1423 struct inode_security_struct *isec;
1424 struct avc_audit_data ad;
1425
Eric Paris828dfe12008-04-17 13:17:49 -04001426 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001427 return 0;
1428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 tsec = tsk->security;
1430 isec = inode->i_security;
1431
1432 if (!adp) {
1433 adp = &ad;
1434 AVC_AUDIT_DATA_INIT(&ad, FS);
1435 ad.u.fs.inode = inode;
1436 }
1437
1438 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
1439}
1440
1441/* Same as inode_has_perm, but pass explicit audit data containing
1442 the dentry to help the auditing code to more easily generate the
1443 pathname if needed. */
1444static inline int dentry_has_perm(struct task_struct *tsk,
1445 struct vfsmount *mnt,
1446 struct dentry *dentry,
1447 u32 av)
1448{
1449 struct inode *inode = dentry->d_inode;
1450 struct avc_audit_data ad;
Eric Paris828dfe12008-04-17 13:17:49 -04001451 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001452 ad.u.fs.path.mnt = mnt;
1453 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 return inode_has_perm(tsk, inode, av, &ad);
1455}
1456
1457/* Check whether a task can use an open file descriptor to
1458 access an inode in a given way. Check access to the
1459 descriptor itself, and then use dentry_has_perm to
1460 check a particular permission to the file.
1461 Access to the descriptor is implicitly granted if it
1462 has the same SID as the process. If av is zero, then
1463 access to the file is not checked, e.g. for cases
1464 where only the descriptor is affected like seek. */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001465static int file_has_perm(struct task_struct *tsk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 struct file *file,
1467 u32 av)
1468{
1469 struct task_security_struct *tsec = tsk->security;
1470 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001471 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 struct avc_audit_data ad;
1473 int rc;
1474
1475 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001476 ad.u.fs.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
1478 if (tsec->sid != fsec->sid) {
1479 rc = avc_has_perm(tsec->sid, fsec->sid,
1480 SECCLASS_FD,
1481 FD__USE,
1482 &ad);
1483 if (rc)
1484 return rc;
1485 }
1486
1487 /* av is zero if only checking access to the descriptor. */
1488 if (av)
1489 return inode_has_perm(tsk, inode, av, &ad);
1490
1491 return 0;
1492}
1493
1494/* Check whether a task can create a file. */
1495static int may_create(struct inode *dir,
1496 struct dentry *dentry,
1497 u16 tclass)
1498{
1499 struct task_security_struct *tsec;
1500 struct inode_security_struct *dsec;
1501 struct superblock_security_struct *sbsec;
1502 u32 newsid;
1503 struct avc_audit_data ad;
1504 int rc;
1505
1506 tsec = current->security;
1507 dsec = dir->i_security;
1508 sbsec = dir->i_sb->s_security;
1509
1510 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001511 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
1513 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1514 DIR__ADD_NAME | DIR__SEARCH,
1515 &ad);
1516 if (rc)
1517 return rc;
1518
1519 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1520 newsid = tsec->create_sid;
1521 } else {
1522 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1523 &newsid);
1524 if (rc)
1525 return rc;
1526 }
1527
1528 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1529 if (rc)
1530 return rc;
1531
1532 return avc_has_perm(newsid, sbsec->sid,
1533 SECCLASS_FILESYSTEM,
1534 FILESYSTEM__ASSOCIATE, &ad);
1535}
1536
Michael LeMay4eb582c2006-06-26 00:24:57 -07001537/* Check whether a task can create a key. */
1538static int may_create_key(u32 ksid,
1539 struct task_struct *ctx)
1540{
1541 struct task_security_struct *tsec;
1542
1543 tsec = ctx->security;
1544
1545 return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
1546}
1547
Eric Paris828dfe12008-04-17 13:17:49 -04001548#define MAY_LINK 0
1549#define MAY_UNLINK 1
1550#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552/* Check whether a task can link, unlink, or rmdir a file/directory. */
1553static int may_link(struct inode *dir,
1554 struct dentry *dentry,
1555 int kind)
1556
1557{
1558 struct task_security_struct *tsec;
1559 struct inode_security_struct *dsec, *isec;
1560 struct avc_audit_data ad;
1561 u32 av;
1562 int rc;
1563
1564 tsec = current->security;
1565 dsec = dir->i_security;
1566 isec = dentry->d_inode->i_security;
1567
1568 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08001569 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
1571 av = DIR__SEARCH;
1572 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1573 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1574 if (rc)
1575 return rc;
1576
1577 switch (kind) {
1578 case MAY_LINK:
1579 av = FILE__LINK;
1580 break;
1581 case MAY_UNLINK:
1582 av = FILE__UNLINK;
1583 break;
1584 case MAY_RMDIR:
1585 av = DIR__RMDIR;
1586 break;
1587 default:
Eric Paris744ba352008-04-17 11:52:44 -04001588 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1589 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 return 0;
1591 }
1592
1593 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1594 return rc;
1595}
1596
1597static inline int may_rename(struct inode *old_dir,
1598 struct dentry *old_dentry,
1599 struct inode *new_dir,
1600 struct dentry *new_dentry)
1601{
1602 struct task_security_struct *tsec;
1603 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1604 struct avc_audit_data ad;
1605 u32 av;
1606 int old_is_dir, new_is_dir;
1607 int rc;
1608
1609 tsec = current->security;
1610 old_dsec = old_dir->i_security;
1611 old_isec = old_dentry->d_inode->i_security;
1612 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1613 new_dsec = new_dir->i_security;
1614
1615 AVC_AUDIT_DATA_INIT(&ad, FS);
1616
Jan Blunck44707fd2008-02-14 19:38:33 -08001617 ad.u.fs.path.dentry = old_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1619 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1620 if (rc)
1621 return rc;
1622 rc = avc_has_perm(tsec->sid, old_isec->sid,
1623 old_isec->sclass, FILE__RENAME, &ad);
1624 if (rc)
1625 return rc;
1626 if (old_is_dir && new_dir != old_dir) {
1627 rc = avc_has_perm(tsec->sid, old_isec->sid,
1628 old_isec->sclass, DIR__REPARENT, &ad);
1629 if (rc)
1630 return rc;
1631 }
1632
Jan Blunck44707fd2008-02-14 19:38:33 -08001633 ad.u.fs.path.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 av = DIR__ADD_NAME | DIR__SEARCH;
1635 if (new_dentry->d_inode)
1636 av |= DIR__REMOVE_NAME;
1637 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1638 if (rc)
1639 return rc;
1640 if (new_dentry->d_inode) {
1641 new_isec = new_dentry->d_inode->i_security;
1642 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1643 rc = avc_has_perm(tsec->sid, new_isec->sid,
1644 new_isec->sclass,
1645 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1646 if (rc)
1647 return rc;
1648 }
1649
1650 return 0;
1651}
1652
1653/* Check whether a task can perform a filesystem operation. */
1654static int superblock_has_perm(struct task_struct *tsk,
1655 struct super_block *sb,
1656 u32 perms,
1657 struct avc_audit_data *ad)
1658{
1659 struct task_security_struct *tsec;
1660 struct superblock_security_struct *sbsec;
1661
1662 tsec = tsk->security;
1663 sbsec = sb->s_security;
1664 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1665 perms, ad);
1666}
1667
1668/* Convert a Linux mode and permission mask to an access vector. */
1669static inline u32 file_mask_to_av(int mode, int mask)
1670{
1671 u32 av = 0;
1672
1673 if ((mode & S_IFMT) != S_IFDIR) {
1674 if (mask & MAY_EXEC)
1675 av |= FILE__EXECUTE;
1676 if (mask & MAY_READ)
1677 av |= FILE__READ;
1678
1679 if (mask & MAY_APPEND)
1680 av |= FILE__APPEND;
1681 else if (mask & MAY_WRITE)
1682 av |= FILE__WRITE;
1683
1684 } else {
1685 if (mask & MAY_EXEC)
1686 av |= DIR__SEARCH;
1687 if (mask & MAY_WRITE)
1688 av |= DIR__WRITE;
1689 if (mask & MAY_READ)
1690 av |= DIR__READ;
1691 }
1692
1693 return av;
1694}
1695
1696/* Convert a Linux file to an access vector. */
1697static inline u32 file_to_av(struct file *file)
1698{
1699 u32 av = 0;
1700
1701 if (file->f_mode & FMODE_READ)
1702 av |= FILE__READ;
1703 if (file->f_mode & FMODE_WRITE) {
1704 if (file->f_flags & O_APPEND)
1705 av |= FILE__APPEND;
1706 else
1707 av |= FILE__WRITE;
1708 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001709 if (!av) {
1710 /*
1711 * Special file opened with flags 3 for ioctl-only use.
1712 */
1713 av = FILE__IOCTL;
1714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
1716 return av;
1717}
1718
Eric Paris8b6a5a32008-10-29 17:06:46 -04001719/*
1720 * Convert a file to an access vector and include the correct open
1721 * open permission.
1722 */
1723static inline u32 open_file_to_av(struct file *file)
1724{
1725 u32 av = file_to_av(file);
1726
1727 if (selinux_policycap_openperm) {
1728 mode_t mode = file->f_path.dentry->d_inode->i_mode;
1729 /*
1730 * lnk files and socks do not really have an 'open'
1731 */
1732 if (S_ISREG(mode))
1733 av |= FILE__OPEN;
1734 else if (S_ISCHR(mode))
1735 av |= CHR_FILE__OPEN;
1736 else if (S_ISBLK(mode))
1737 av |= BLK_FILE__OPEN;
1738 else if (S_ISFIFO(mode))
1739 av |= FIFO_FILE__OPEN;
1740 else if (S_ISDIR(mode))
1741 av |= DIR__OPEN;
1742 else
1743 printk(KERN_ERR "SELinux: WARNING: inside %s with "
1744 "unknown mode:%o\n", __func__, mode);
1745 }
1746 return av;
1747}
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749/* Hook functions begin here. */
1750
David Howells5cd9c582008-08-14 11:37:28 +01001751static int selinux_ptrace_may_access(struct task_struct *child,
1752 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 int rc;
1755
David Howells5cd9c582008-08-14 11:37:28 +01001756 rc = secondary_ops->ptrace_may_access(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 if (rc)
1758 return rc;
1759
Stephen Smalley006ebb42008-05-19 08:32:49 -04001760 if (mode == PTRACE_MODE_READ) {
David Howells5cd9c582008-08-14 11:37:28 +01001761 struct task_security_struct *tsec = current->security;
Stephen Smalley006ebb42008-05-19 08:32:49 -04001762 struct task_security_struct *csec = child->security;
1763 return avc_has_perm(tsec->sid, csec->sid,
1764 SECCLASS_FILE, FILE__READ, NULL);
1765 }
1766
David Howells5cd9c582008-08-14 11:37:28 +01001767 return task_has_perm(current, child, PROCESS__PTRACE);
1768}
1769
1770static int selinux_ptrace_traceme(struct task_struct *parent)
1771{
1772 int rc;
1773
1774 rc = secondary_ops->ptrace_traceme(parent);
1775 if (rc)
1776 return rc;
1777
1778 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779}
1780
1781static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001782 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783{
1784 int error;
1785
1786 error = task_has_perm(current, target, PROCESS__GETCAP);
1787 if (error)
1788 return error;
1789
1790 return secondary_ops->capget(target, effective, inheritable, permitted);
1791}
1792
David Howells1cdcbec2008-11-14 10:39:14 +11001793static int selinux_capset_check(kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001794 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795{
1796 int error;
1797
David Howells1cdcbec2008-11-14 10:39:14 +11001798 error = secondary_ops->capset_check(effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 if (error)
1800 return error;
1801
David Howells1cdcbec2008-11-14 10:39:14 +11001802 return task_has_perm(current, current, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803}
1804
David Howells1cdcbec2008-11-14 10:39:14 +11001805static void selinux_capset_set(kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001806 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807{
David Howells1cdcbec2008-11-14 10:39:14 +11001808 secondary_ops->capset_set(effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809}
1810
Eric Paris06112162008-11-11 22:02:50 +11001811static int selinux_capable(struct task_struct *tsk, int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812{
1813 int rc;
1814
Eric Paris06112162008-11-11 22:02:50 +11001815 rc = secondary_ops->capable(tsk, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 if (rc)
1817 return rc;
1818
Eric Paris06112162008-11-11 22:02:50 +11001819 return task_has_capability(tsk, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820}
1821
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001822static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
1823{
1824 int buflen, rc;
1825 char *buffer, *path, *end;
1826
1827 rc = -ENOMEM;
Eric Paris828dfe12008-04-17 13:17:49 -04001828 buffer = (char *)__get_free_page(GFP_KERNEL);
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001829 if (!buffer)
1830 goto out;
1831
1832 buflen = PAGE_SIZE;
1833 end = buffer+buflen;
1834 *--end = '\0';
1835 buflen--;
1836 path = end-1;
1837 *path = '/';
1838 while (table) {
1839 const char *name = table->procname;
1840 size_t namelen = strlen(name);
1841 buflen -= namelen + 1;
1842 if (buflen < 0)
1843 goto out_free;
1844 end -= namelen;
1845 memcpy(end, name, namelen);
1846 *--end = '/';
1847 path = end;
1848 table = table->parent;
1849 }
Eric W. Biedermanb599fdf2007-02-14 00:34:15 -08001850 buflen -= 4;
1851 if (buflen < 0)
1852 goto out_free;
1853 end -= 4;
1854 memcpy(end, "/sys", 4);
1855 path = end;
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001856 rc = security_genfs_sid("proc", path, tclass, sid);
1857out_free:
1858 free_page((unsigned long)buffer);
1859out:
1860 return rc;
1861}
1862
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863static int selinux_sysctl(ctl_table *table, int op)
1864{
1865 int error = 0;
1866 u32 av;
1867 struct task_security_struct *tsec;
1868 u32 tsid;
1869 int rc;
1870
1871 rc = secondary_ops->sysctl(table, op);
1872 if (rc)
1873 return rc;
1874
1875 tsec = current->security;
1876
Eric W. Biederman3fbfa982007-02-14 00:34:14 -08001877 rc = selinux_sysctl_get_sid(table, (op == 0001) ?
1878 SECCLASS_DIR : SECCLASS_FILE, &tsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 if (rc) {
1880 /* Default to the well-defined sysctl SID. */
1881 tsid = SECINITSID_SYSCTL;
1882 }
1883
1884 /* The op values are "defined" in sysctl.c, thereby creating
1885 * a bad coupling between this module and sysctl.c */
Eric Paris828dfe12008-04-17 13:17:49 -04001886 if (op == 001) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 error = avc_has_perm(tsec->sid, tsid,
1888 SECCLASS_DIR, DIR__SEARCH, NULL);
1889 } else {
1890 av = 0;
1891 if (op & 004)
1892 av |= FILE__READ;
1893 if (op & 002)
1894 av |= FILE__WRITE;
1895 if (av)
1896 error = avc_has_perm(tsec->sid, tsid,
1897 SECCLASS_FILE, av, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 return error;
1901}
1902
1903static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1904{
1905 int rc = 0;
1906
1907 if (!sb)
1908 return 0;
1909
1910 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001911 case Q_SYNC:
1912 case Q_QUOTAON:
1913 case Q_QUOTAOFF:
1914 case Q_SETINFO:
1915 case Q_SETQUOTA:
1916 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
1917 NULL);
1918 break;
1919 case Q_GETFMT:
1920 case Q_GETINFO:
1921 case Q_GETQUOTA:
1922 rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
1923 NULL);
1924 break;
1925 default:
1926 rc = 0; /* let the kernel handle invalid cmds */
1927 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 }
1929 return rc;
1930}
1931
1932static int selinux_quota_on(struct dentry *dentry)
1933{
1934 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1935}
1936
1937static int selinux_syslog(int type)
1938{
1939 int rc;
1940
1941 rc = secondary_ops->syslog(type);
1942 if (rc)
1943 return rc;
1944
1945 switch (type) {
Eric Paris828dfe12008-04-17 13:17:49 -04001946 case 3: /* Read last kernel messages */
1947 case 10: /* Return size of the log buffer */
1948 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1949 break;
1950 case 6: /* Disable logging to console */
1951 case 7: /* Enable logging to console */
1952 case 8: /* Set level of messages printed to console */
1953 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1954 break;
1955 case 0: /* Close log */
1956 case 1: /* Open log */
1957 case 2: /* Read from log */
1958 case 4: /* Read/clear last kernel messages */
1959 case 5: /* Clear ring buffer */
1960 default:
1961 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1962 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
1964 return rc;
1965}
1966
1967/*
1968 * Check that a process has enough memory to allocate a new virtual
1969 * mapping. 0 means there is enough memory for the allocation to
1970 * succeed and -ENOMEM implies there is not.
1971 *
1972 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1973 * if the capability is granted, but __vm_enough_memory requires 1 if
1974 * the capability is granted.
1975 *
1976 * Do not audit the selinux permission check, as this is applied to all
1977 * processes that allocate mappings.
1978 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001979static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
1981 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Eric Paris06674672008-11-11 22:02:57 +11001983 rc = selinux_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 if (rc == 0)
1985 cap_sys_admin = 1;
1986
Alan Cox34b4e4a2007-08-22 14:01:28 -07001987 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988}
1989
1990/* binprm security operations */
1991
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1993{
1994 struct bprm_security_struct *bsec;
1995
James Morris89d155e2005-10-30 14:59:21 -08001996 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 if (!bsec)
1998 return -ENOMEM;
1999
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 bsec->sid = SECINITSID_UNLABELED;
2001 bsec->set = 0;
2002
2003 bprm->security = bsec;
2004 return 0;
2005}
2006
2007static int selinux_bprm_set_security(struct linux_binprm *bprm)
2008{
2009 struct task_security_struct *tsec;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002010 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 struct inode_security_struct *isec;
2012 struct bprm_security_struct *bsec;
2013 u32 newsid;
2014 struct avc_audit_data ad;
2015 int rc;
2016
2017 rc = secondary_ops->bprm_set_security(bprm);
2018 if (rc)
2019 return rc;
2020
2021 bsec = bprm->security;
2022
2023 if (bsec->set)
2024 return 0;
2025
2026 tsec = current->security;
2027 isec = inode->i_security;
2028
2029 /* Default to the current task SID. */
2030 bsec->sid = tsec->sid;
2031
Michael LeMay28eba5b2006-06-27 02:53:42 -07002032 /* Reset fs, key, and sock SIDs on execve. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 tsec->create_sid = 0;
Michael LeMay28eba5b2006-06-27 02:53:42 -07002034 tsec->keycreate_sid = 0;
Eric Paris42c3e032006-06-26 00:26:03 -07002035 tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
2037 if (tsec->exec_sid) {
2038 newsid = tsec->exec_sid;
2039 /* Reset exec SID on execve. */
2040 tsec->exec_sid = 0;
2041 } else {
2042 /* Check for a default transition on this program. */
2043 rc = security_transition_sid(tsec->sid, isec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002044 SECCLASS_PROCESS, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 if (rc)
2046 return rc;
2047 }
2048
2049 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002050 ad.u.fs.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Josef Sipek3d5ff522006-12-08 02:37:38 -08002052 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 newsid = tsec->sid;
2054
Eric Paris828dfe12008-04-17 13:17:49 -04002055 if (tsec->sid == newsid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 rc = avc_has_perm(tsec->sid, isec->sid,
2057 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2058 if (rc)
2059 return rc;
2060 } else {
2061 /* Check permissions for the transition. */
2062 rc = avc_has_perm(tsec->sid, newsid,
2063 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2064 if (rc)
2065 return rc;
2066
2067 rc = avc_has_perm(newsid, isec->sid,
2068 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2069 if (rc)
2070 return rc;
2071
2072 /* Clear any possibly unsafe personality bits on exec: */
2073 current->personality &= ~PER_CLEAR_ON_SETID;
2074
2075 /* Set the security field to the new SID. */
2076 bsec->sid = newsid;
2077 }
2078
2079 bsec->set = 1;
2080 return 0;
2081}
2082
Eric Paris828dfe12008-04-17 13:17:49 -04002083static int selinux_bprm_check_security(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084{
2085 return secondary_ops->bprm_check_security(bprm);
2086}
2087
2088
Eric Paris828dfe12008-04-17 13:17:49 -04002089static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090{
2091 struct task_security_struct *tsec = current->security;
2092 int atsecure = 0;
2093
2094 if (tsec->osid != tsec->sid) {
2095 /* Enable secure mode for SIDs transitions unless
2096 the noatsecure permission is granted between
2097 the two SIDs, i.e. ahp returns 0. */
2098 atsecure = avc_has_perm(tsec->osid, tsec->sid,
2099 SECCLASS_PROCESS,
2100 PROCESS__NOATSECURE, NULL);
2101 }
2102
2103 return (atsecure || secondary_ops->bprm_secureexec(bprm));
2104}
2105
2106static void selinux_bprm_free_security(struct linux_binprm *bprm)
2107{
Jesper Juhl9a5f04b2005-06-25 14:58:51 -07002108 kfree(bprm->security);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 bprm->security = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110}
2111
2112extern struct vfsmount *selinuxfs_mount;
2113extern struct dentry *selinux_null;
2114
2115/* Derived from fs/exec.c:flush_old_files. */
Eric Paris828dfe12008-04-17 13:17:49 -04002116static inline void flush_unauthorized_files(struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117{
2118 struct avc_audit_data ad;
2119 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002120 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002121 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002123 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002125 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 if (tty) {
2127 file_list_lock();
Eric Paris37dd0bd2008-10-31 17:40:00 -04002128 if (!list_empty(&tty->tty_files)) {
2129 struct inode *inode;
2130
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 /* Revalidate access to controlling tty.
2132 Use inode_has_perm on the tty inode directly rather
2133 than using file_has_perm, as this particular open
2134 file may belong to another process and we are only
2135 interested in the inode-based check here. */
Eric Paris37dd0bd2008-10-31 17:40:00 -04002136 file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list);
2137 inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 if (inode_has_perm(current, inode,
2139 FILE__READ | FILE__WRITE, NULL)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002140 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 }
2142 }
2143 file_list_unlock();
Alan Cox452a00d2008-10-13 10:39:13 +01002144 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002146 /* Reset controlling tty. */
2147 if (drop_tty)
2148 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
2150 /* Revalidate access to inherited open files. */
2151
Eric Paris828dfe12008-04-17 13:17:49 -04002152 AVC_AUDIT_DATA_INIT(&ad, FS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153
2154 spin_lock(&files->file_lock);
2155 for (;;) {
2156 unsigned long set, i;
2157 int fd;
2158
2159 j++;
2160 i = j * __NFDBITS;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002161 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002162 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 break;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002164 set = fdt->open_fds->fds_bits[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 if (!set)
2166 continue;
2167 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002168 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 if (set & 1) {
2170 file = fget(i);
2171 if (!file)
2172 continue;
2173 if (file_has_perm(current,
2174 file,
2175 file_to_av(file))) {
2176 sys_close(i);
2177 fd = get_unused_fd();
2178 if (fd != i) {
2179 if (fd >= 0)
2180 put_unused_fd(fd);
2181 fput(file);
2182 continue;
2183 }
2184 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002185 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 } else {
2187 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002188 if (IS_ERR(devnull)) {
2189 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 put_unused_fd(fd);
2191 fput(file);
2192 continue;
2193 }
2194 }
2195 fd_install(fd, devnull);
2196 }
2197 fput(file);
2198 }
2199 }
2200 spin_lock(&files->file_lock);
2201
2202 }
2203 spin_unlock(&files->file_lock);
2204}
2205
2206static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2207{
2208 struct task_security_struct *tsec;
2209 struct bprm_security_struct *bsec;
2210 u32 sid;
2211 int rc;
2212
2213 secondary_ops->bprm_apply_creds(bprm, unsafe);
2214
2215 tsec = current->security;
2216
2217 bsec = bprm->security;
2218 sid = bsec->sid;
2219
2220 tsec->osid = tsec->sid;
2221 bsec->unsafe = 0;
2222 if (tsec->sid != sid) {
2223 /* Check for shared state. If not ok, leave SID
2224 unchanged and kill. */
2225 if (unsafe & LSM_UNSAFE_SHARE) {
2226 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2227 PROCESS__SHARE, NULL);
2228 if (rc) {
2229 bsec->unsafe = 1;
2230 return;
2231 }
2232 }
2233
2234 /* Check for ptracing, and update the task SID if ok.
2235 Otherwise, leave SID unchanged and kill. */
2236 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Roland McGrath03563572008-03-26 15:46:39 -07002237 struct task_struct *tracer;
2238 struct task_security_struct *sec;
2239 u32 ptsid = 0;
2240
2241 rcu_read_lock();
Roland McGrath0d094ef2008-07-25 19:45:49 -07002242 tracer = tracehook_tracer_task(current);
Roland McGrath03563572008-03-26 15:46:39 -07002243 if (likely(tracer != NULL)) {
2244 sec = tracer->security;
2245 ptsid = sec->sid;
2246 }
2247 rcu_read_unlock();
2248
2249 if (ptsid != 0) {
2250 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
2251 PROCESS__PTRACE, NULL);
2252 if (rc) {
2253 bsec->unsafe = 1;
2254 return;
2255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 }
2257 }
2258 tsec->sid = sid;
2259 }
2260}
2261
2262/*
2263 * called after apply_creds without the task lock held
2264 */
2265static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2266{
2267 struct task_security_struct *tsec;
2268 struct rlimit *rlim, *initrlim;
2269 struct itimerval itimer;
2270 struct bprm_security_struct *bsec;
Eric Paris41d9f9c2008-11-04 15:18:26 -05002271 struct sighand_struct *psig;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 int rc, i;
Eric Paris41d9f9c2008-11-04 15:18:26 -05002273 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 tsec = current->security;
2276 bsec = bprm->security;
2277
2278 if (bsec->unsafe) {
2279 force_sig_specific(SIGKILL, current);
2280 return;
2281 }
2282 if (tsec->osid == tsec->sid)
2283 return;
2284
2285 /* Close files for which the new task SID is not authorized. */
2286 flush_unauthorized_files(current->files);
2287
2288 /* Check whether the new SID can inherit signal state
2289 from the old SID. If not, clear itimers to avoid
2290 subsequent signal generation and flush and unblock
2291 signals. This must occur _after_ the task SID has
2292 been updated so that any kill done after the flush
2293 will be checked against the new SID. */
2294 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2295 PROCESS__SIGINH, NULL);
2296 if (rc) {
2297 memset(&itimer, 0, sizeof itimer);
2298 for (i = 0; i < 3; i++)
2299 do_setitimer(i, &itimer, NULL);
2300 flush_signals(current);
2301 spin_lock_irq(&current->sighand->siglock);
2302 flush_signal_handlers(current, 1);
2303 sigemptyset(&current->blocked);
2304 recalc_sigpending();
2305 spin_unlock_irq(&current->sighand->siglock);
2306 }
2307
Stephen Smalley4ac212a2007-08-29 08:51:50 -04002308 /* Always clear parent death signal on SID transitions. */
2309 current->pdeath_signal = 0;
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 /* Check whether the new SID can inherit resource limits
2312 from the old SID. If not, reset all soft limits to
2313 the lower of the current task's hard limit and the init
2314 task's soft limit. Note that the setting of hard limits
2315 (even to lower them) can be controlled by the setrlimit
2316 check. The inclusion of the init task's soft limit into
2317 the computation is to avoid resetting soft limits higher
2318 than the default soft limit for cases where the default
2319 is lower than the hard limit, e.g. RLIMIT_CORE or
2320 RLIMIT_STACK.*/
2321 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2322 PROCESS__RLIMITINH, NULL);
2323 if (rc) {
2324 for (i = 0; i < RLIM_NLIMITS; i++) {
2325 rlim = current->signal->rlim + i;
2326 initrlim = init_task.signal->rlim+i;
Eric Paris828dfe12008-04-17 13:17:49 -04002327 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
Frank Mayharf06febc2008-09-12 09:54:39 -07002329 update_rlimit_cpu(rlim->rlim_cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 }
2331
2332 /* Wake up the parent if it is waiting so that it can
2333 recheck wait permission to the new task SID. */
Eric Paris41d9f9c2008-11-04 15:18:26 -05002334 read_lock_irq(&tasklist_lock);
2335 psig = current->parent->sighand;
2336 spin_lock_irqsave(&psig->siglock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 wake_up_interruptible(&current->parent->signal->wait_chldexit);
Eric Paris41d9f9c2008-11-04 15:18:26 -05002338 spin_unlock_irqrestore(&psig->siglock, flags);
2339 read_unlock_irq(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340}
2341
2342/* superblock security operations */
2343
2344static int selinux_sb_alloc_security(struct super_block *sb)
2345{
2346 return superblock_alloc_security(sb);
2347}
2348
2349static void selinux_sb_free_security(struct super_block *sb)
2350{
2351 superblock_free_security(sb);
2352}
2353
2354static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2355{
2356 if (plen > olen)
2357 return 0;
2358
2359 return !memcmp(prefix, option, plen);
2360}
2361
2362static inline int selinux_option(char *option, int len)
2363{
Eric Paris832cbd92008-04-01 13:24:09 -04002364 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2365 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2366 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2367 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368}
2369
2370static inline void take_option(char **to, char *from, int *first, int len)
2371{
2372 if (!*first) {
2373 **to = ',';
2374 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002375 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 *first = 0;
2377 memcpy(*to, from, len);
2378 *to += len;
2379}
2380
Eric Paris828dfe12008-04-17 13:17:49 -04002381static inline void take_selinux_option(char **to, char *from, int *first,
2382 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002383{
2384 int current_size = 0;
2385
2386 if (!*first) {
2387 **to = '|';
2388 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002389 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002390 *first = 0;
2391
2392 while (current_size < len) {
2393 if (*from != '"') {
2394 **to = *from;
2395 *to += 1;
2396 }
2397 from += 1;
2398 current_size += 1;
2399 }
2400}
2401
Eric Parise0007522008-03-05 10:31:54 -05002402static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403{
2404 int fnosec, fsec, rc = 0;
2405 char *in_save, *in_curr, *in_end;
2406 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002407 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
2409 in_curr = orig;
2410 sec_curr = copy;
2411
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2413 if (!nosec) {
2414 rc = -ENOMEM;
2415 goto out;
2416 }
2417
2418 nosec_save = nosec;
2419 fnosec = fsec = 1;
2420 in_save = in_end = orig;
2421
2422 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002423 if (*in_end == '"')
2424 open_quote = !open_quote;
2425 if ((*in_end == ',' && open_quote == 0) ||
2426 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 int len = in_end - in_curr;
2428
2429 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002430 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 else
2432 take_option(&nosec, in_curr, &fnosec, len);
2433
2434 in_curr = in_end + 1;
2435 }
2436 } while (*in_end++);
2437
Eric Paris6931dfc2005-06-30 02:58:51 -07002438 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002439 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440out:
2441 return rc;
2442}
2443
2444static int selinux_sb_kern_mount(struct super_block *sb, void *data)
2445{
2446 struct avc_audit_data ad;
2447 int rc;
2448
2449 rc = superblock_doinit(sb, data);
2450 if (rc)
2451 return rc;
2452
Eric Paris828dfe12008-04-17 13:17:49 -04002453 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002454 ad.u.fs.path.dentry = sb->s_root;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
2456}
2457
David Howells726c3342006-06-23 02:02:58 -07002458static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
2460 struct avc_audit_data ad;
2461
Eric Paris828dfe12008-04-17 13:17:49 -04002462 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002463 ad.u.fs.path.dentry = dentry->d_sb->s_root;
David Howells726c3342006-06-23 02:02:58 -07002464 return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465}
2466
Eric Paris828dfe12008-04-17 13:17:49 -04002467static int selinux_mount(char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002468 struct path *path,
Eric Paris828dfe12008-04-17 13:17:49 -04002469 char *type,
2470 unsigned long flags,
2471 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472{
2473 int rc;
2474
Al Virob5266eb2008-03-22 17:48:24 -04002475 rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 if (rc)
2477 return rc;
2478
2479 if (flags & MS_REMOUNT)
Al Virob5266eb2008-03-22 17:48:24 -04002480 return superblock_has_perm(current, path->mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002481 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 else
Al Virob5266eb2008-03-22 17:48:24 -04002483 return dentry_has_perm(current, path->mnt, path->dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002484 FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485}
2486
2487static int selinux_umount(struct vfsmount *mnt, int flags)
2488{
2489 int rc;
2490
2491 rc = secondary_ops->sb_umount(mnt, flags);
2492 if (rc)
2493 return rc;
2494
Eric Paris828dfe12008-04-17 13:17:49 -04002495 return superblock_has_perm(current, mnt->mnt_sb,
2496 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497}
2498
2499/* inode security operations */
2500
2501static int selinux_inode_alloc_security(struct inode *inode)
2502{
2503 return inode_alloc_security(inode);
2504}
2505
2506static void selinux_inode_free_security(struct inode *inode)
2507{
2508 inode_free_security(inode);
2509}
2510
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002511static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2512 char **name, void **value,
2513 size_t *len)
2514{
2515 struct task_security_struct *tsec;
2516 struct inode_security_struct *dsec;
2517 struct superblock_security_struct *sbsec;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002518 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002519 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002520 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002521
2522 tsec = current->security;
2523 dsec = dir->i_security;
2524 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002525
2526 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2527 newsid = tsec->create_sid;
2528 } else {
2529 rc = security_transition_sid(tsec->sid, dsec->sid,
2530 inode_mode_to_security_class(inode->i_mode),
2531 &newsid);
2532 if (rc) {
2533 printk(KERN_WARNING "%s: "
2534 "security_transition_sid failed, rc=%d (dev=%s "
2535 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002536 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002537 -rc, inode->i_sb->s_id, inode->i_ino);
2538 return rc;
2539 }
2540 }
2541
Eric Paris296fddf2006-09-25 23:32:00 -07002542 /* Possibly defer initialization to selinux_complete_init. */
2543 if (sbsec->initialized) {
2544 struct inode_security_struct *isec = inode->i_security;
2545 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2546 isec->sid = newsid;
2547 isec->initialized = 1;
2548 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002549
Stephen Smalley8aad3872006-03-22 00:09:13 -08002550 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
Stephen Smalley25a74f32005-11-08 21:34:33 -08002551 return -EOPNOTSUPP;
2552
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002553 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002554 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002555 if (!namep)
2556 return -ENOMEM;
2557 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002558 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002559
2560 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002561 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002562 if (rc) {
2563 kfree(namep);
2564 return rc;
2565 }
2566 *value = context;
2567 *len = clen;
2568 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002569
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002570 return 0;
2571}
2572
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2574{
2575 return may_create(dir, dentry, SECCLASS_FILE);
2576}
2577
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2579{
2580 int rc;
2581
Eric Paris828dfe12008-04-17 13:17:49 -04002582 rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 if (rc)
2584 return rc;
2585 return may_link(dir, old_dentry, MAY_LINK);
2586}
2587
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2589{
2590 int rc;
2591
2592 rc = secondary_ops->inode_unlink(dir, dentry);
2593 if (rc)
2594 return rc;
2595 return may_link(dir, dentry, MAY_UNLINK);
2596}
2597
2598static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2599{
2600 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2601}
2602
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2604{
2605 return may_create(dir, dentry, SECCLASS_DIR);
2606}
2607
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2609{
2610 return may_link(dir, dentry, MAY_RMDIR);
2611}
2612
2613static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2614{
2615 int rc;
2616
2617 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2618 if (rc)
2619 return rc;
2620
2621 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2622}
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002625 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
2627 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2628}
2629
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630static int selinux_inode_readlink(struct dentry *dentry)
2631{
2632 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2633}
2634
2635static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2636{
2637 int rc;
2638
Eric Paris828dfe12008-04-17 13:17:49 -04002639 rc = secondary_ops->inode_follow_link(dentry, nameidata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 if (rc)
2641 return rc;
2642 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2643}
2644
Al Virob77b0642008-07-17 09:37:02 -04002645static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
2647 int rc;
2648
Al Virob77b0642008-07-17 09:37:02 -04002649 rc = secondary_ops->inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 if (rc)
2651 return rc;
2652
2653 if (!mask) {
2654 /* No permission to check. Existence test. */
2655 return 0;
2656 }
2657
2658 return inode_has_perm(current, inode,
Eric Paris8b6a5a32008-10-29 17:06:46 -04002659 file_mask_to_av(inode->i_mode, mask), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660}
2661
2662static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2663{
2664 int rc;
2665
2666 rc = secondary_ops->inode_setattr(dentry, iattr);
2667 if (rc)
2668 return rc;
2669
2670 if (iattr->ia_valid & ATTR_FORCE)
2671 return 0;
2672
2673 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2674 ATTR_ATIME_SET | ATTR_MTIME_SET))
2675 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2676
2677 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2678}
2679
2680static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2681{
2682 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2683}
2684
David Howells8f0cfa52008-04-29 00:59:41 -07002685static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002686{
2687 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2688 sizeof XATTR_SECURITY_PREFIX - 1)) {
2689 if (!strcmp(name, XATTR_NAME_CAPS)) {
2690 if (!capable(CAP_SETFCAP))
2691 return -EPERM;
2692 } else if (!capable(CAP_SYS_ADMIN)) {
2693 /* A different attribute in the security namespace.
2694 Restrict to administrator. */
2695 return -EPERM;
2696 }
2697 }
2698
2699 /* Not an attribute we recognize, so just check the
2700 ordinary setattr permission. */
2701 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2702}
2703
David Howells8f0cfa52008-04-29 00:59:41 -07002704static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2705 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706{
2707 struct task_security_struct *tsec = current->security;
2708 struct inode *inode = dentry->d_inode;
2709 struct inode_security_struct *isec = inode->i_security;
2710 struct superblock_security_struct *sbsec;
2711 struct avc_audit_data ad;
2712 u32 newsid;
2713 int rc = 0;
2714
Serge E. Hallynb5376772007-10-16 23:31:36 -07002715 if (strcmp(name, XATTR_NAME_SELINUX))
2716 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
2718 sbsec = inode->i_sb->s_security;
2719 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2720 return -EOPNOTSUPP;
2721
Satyam Sharma3bd858a2007-07-17 15:00:08 +05302722 if (!is_owner_or_cap(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 return -EPERM;
2724
Eric Paris828dfe12008-04-17 13:17:49 -04002725 AVC_AUDIT_DATA_INIT(&ad, FS);
Jan Blunck44707fd2008-02-14 19:38:33 -08002726 ad.u.fs.path.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727
2728 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2729 FILE__RELABELFROM, &ad);
2730 if (rc)
2731 return rc;
2732
2733 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002734 if (rc == -EINVAL) {
2735 if (!capable(CAP_MAC_ADMIN))
2736 return rc;
2737 rc = security_context_to_sid_force(value, size, &newsid);
2738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 if (rc)
2740 return rc;
2741
2742 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2743 FILE__RELABELTO, &ad);
2744 if (rc)
2745 return rc;
2746
2747 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002748 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 if (rc)
2750 return rc;
2751
2752 return avc_has_perm(newsid,
2753 sbsec->sid,
2754 SECCLASS_FILESYSTEM,
2755 FILESYSTEM__ASSOCIATE,
2756 &ad);
2757}
2758
David Howells8f0cfa52008-04-29 00:59:41 -07002759static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002760 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002761 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762{
2763 struct inode *inode = dentry->d_inode;
2764 struct inode_security_struct *isec = inode->i_security;
2765 u32 newsid;
2766 int rc;
2767
2768 if (strcmp(name, XATTR_NAME_SELINUX)) {
2769 /* Not an attribute we recognize, so nothing to do. */
2770 return;
2771 }
2772
Stephen Smalley12b29f32008-05-07 13:03:20 -04002773 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002775 printk(KERN_ERR "SELinux: unable to map context to SID"
2776 "for (%s, %lu), rc=%d\n",
2777 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 return;
2779 }
2780
2781 isec->sid = newsid;
2782 return;
2783}
2784
David Howells8f0cfa52008-04-29 00:59:41 -07002785static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2788}
2789
Eric Paris828dfe12008-04-17 13:17:49 -04002790static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
2792 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2793}
2794
David Howells8f0cfa52008-04-29 00:59:41 -07002795static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002797 if (strcmp(name, XATTR_NAME_SELINUX))
2798 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800 /* No one is allowed to remove a SELinux security label.
2801 You can change the label, but all data must be labeled. */
2802 return -EACCES;
2803}
2804
James Morrisd381d8a2005-10-30 14:59:22 -08002805/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002806 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002807 *
2808 * Permission check is handled by selinux_inode_getxattr hook.
2809 */
David P. Quigley42492592008-02-04 22:29:39 -08002810static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811{
David P. Quigley42492592008-02-04 22:29:39 -08002812 u32 size;
2813 int error;
2814 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002817 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2818 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002820 /*
2821 * If the caller has CAP_MAC_ADMIN, then get the raw context
2822 * value even if it is not defined by current policy; otherwise,
2823 * use the in-core value under current policy.
2824 * Use the non-auditing forms of the permission checks since
2825 * getxattr may be called by unprivileged processes commonly
2826 * and lack of permission just means that we fall back to the
2827 * in-core context value, not a denial.
2828 */
Eric Paris06674672008-11-11 22:02:57 +11002829 error = selinux_capable(current, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002830 if (!error)
2831 error = security_sid_to_context_force(isec->sid, &context,
2832 &size);
2833 else
2834 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002835 if (error)
2836 return error;
2837 error = size;
2838 if (alloc) {
2839 *buffer = context;
2840 goto out_nofree;
2841 }
2842 kfree(context);
2843out_nofree:
2844 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845}
2846
2847static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002848 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
2850 struct inode_security_struct *isec = inode->i_security;
2851 u32 newsid;
2852 int rc;
2853
2854 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2855 return -EOPNOTSUPP;
2856
2857 if (!value || !size)
2858 return -EACCES;
2859
Eric Paris828dfe12008-04-17 13:17:49 -04002860 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 if (rc)
2862 return rc;
2863
2864 isec->sid = newsid;
2865 return 0;
2866}
2867
2868static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2869{
2870 const int len = sizeof(XATTR_NAME_SELINUX);
2871 if (buffer && len <= buffer_size)
2872 memcpy(buffer, XATTR_NAME_SELINUX, len);
2873 return len;
2874}
2875
Serge E. Hallynb5376772007-10-16 23:31:36 -07002876static int selinux_inode_need_killpriv(struct dentry *dentry)
2877{
2878 return secondary_ops->inode_need_killpriv(dentry);
2879}
2880
2881static int selinux_inode_killpriv(struct dentry *dentry)
2882{
2883 return secondary_ops->inode_killpriv(dentry);
2884}
2885
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02002886static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2887{
2888 struct inode_security_struct *isec = inode->i_security;
2889 *secid = isec->sid;
2890}
2891
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892/* file security operations */
2893
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002894static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002896 int rc;
Josef Sipek3d5ff522006-12-08 02:37:38 -08002897 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898
2899 if (!mask) {
2900 /* No permission to check. Existence test. */
2901 return 0;
2902 }
2903
2904 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2905 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2906 mask |= MAY_APPEND;
2907
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07002908 rc = file_has_perm(current, file,
2909 file_mask_to_av(inode->i_mode, mask));
2910 if (rc)
2911 return rc;
2912
2913 return selinux_netlbl_inode_permission(inode, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914}
2915
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002916static int selinux_file_permission(struct file *file, int mask)
2917{
2918 struct inode *inode = file->f_path.dentry->d_inode;
2919 struct task_security_struct *tsec = current->security;
2920 struct file_security_struct *fsec = file->f_security;
2921 struct inode_security_struct *isec = inode->i_security;
2922
2923 if (!mask) {
2924 /* No permission to check. Existence test. */
2925 return 0;
2926 }
2927
2928 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2929 && fsec->pseqno == avc_policy_seqno())
2930 return selinux_netlbl_inode_permission(inode, mask);
2931
2932 return selinux_revalidate_file_permission(file, mask);
2933}
2934
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935static int selinux_file_alloc_security(struct file *file)
2936{
2937 return file_alloc_security(file);
2938}
2939
2940static void selinux_file_free_security(struct file *file)
2941{
2942 file_free_security(file);
2943}
2944
2945static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2946 unsigned long arg)
2947{
Stephen Smalley242631c2008-06-05 09:21:28 -04002948 u32 av = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949
Stephen Smalley242631c2008-06-05 09:21:28 -04002950 if (_IOC_DIR(cmd) & _IOC_WRITE)
2951 av |= FILE__WRITE;
2952 if (_IOC_DIR(cmd) & _IOC_READ)
2953 av |= FILE__READ;
2954 if (!av)
2955 av = FILE__IOCTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Stephen Smalley242631c2008-06-05 09:21:28 -04002957 return file_has_perm(current, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958}
2959
2960static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2961{
2962#ifndef CONFIG_PPC32
2963 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2964 /*
2965 * We are making executable an anonymous mapping or a
2966 * private file mapping that will also be writable.
2967 * This has an additional check.
2968 */
2969 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2970 if (rc)
2971 return rc;
2972 }
2973#endif
2974
2975 if (file) {
2976 /* read access is always possible with a mapping */
2977 u32 av = FILE__READ;
2978
2979 /* write access only matters if the mapping is shared */
2980 if (shared && (prot & PROT_WRITE))
2981 av |= FILE__WRITE;
2982
2983 if (prot & PROT_EXEC)
2984 av |= FILE__EXECUTE;
2985
2986 return file_has_perm(current, file, av);
2987 }
2988 return 0;
2989}
2990
2991static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04002992 unsigned long prot, unsigned long flags,
2993 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994{
Eric Parised032182007-06-28 15:55:21 -04002995 int rc = 0;
Eric Paris828dfe12008-04-17 13:17:49 -04002996 u32 sid = ((struct task_security_struct *)(current->security))->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997
Eric Parised032182007-06-28 15:55:21 -04002998 if (addr < mmap_min_addr)
2999 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3000 MEMPROTECT__MMAP_ZERO, NULL);
3001 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 return rc;
3003
3004 if (selinux_checkreqprot)
3005 prot = reqprot;
3006
3007 return file_map_prot_check(file, prot,
3008 (flags & MAP_TYPE) == MAP_SHARED);
3009}
3010
3011static int selinux_file_mprotect(struct vm_area_struct *vma,
3012 unsigned long reqprot,
3013 unsigned long prot)
3014{
3015 int rc;
3016
3017 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
3018 if (rc)
3019 return rc;
3020
3021 if (selinux_checkreqprot)
3022 prot = reqprot;
3023
3024#ifndef CONFIG_PPC32
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003025 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
3026 rc = 0;
3027 if (vma->vm_start >= vma->vm_mm->start_brk &&
3028 vma->vm_end <= vma->vm_mm->brk) {
3029 rc = task_has_perm(current, current,
3030 PROCESS__EXECHEAP);
3031 } else if (!vma->vm_file &&
3032 vma->vm_start <= vma->vm_mm->start_stack &&
3033 vma->vm_end >= vma->vm_mm->start_stack) {
3034 rc = task_has_perm(current, current, PROCESS__EXECSTACK);
3035 } else if (vma->vm_file && vma->anon_vma) {
3036 /*
3037 * We are making executable a file mapping that has
3038 * had some COW done. Since pages might have been
3039 * written, check ability to execute the possibly
3040 * modified content. This typically should only
3041 * occur for text relocations.
3042 */
3043 rc = file_has_perm(current, vma->vm_file,
3044 FILE__EXECMOD);
3045 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003046 if (rc)
3047 return rc;
3048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049#endif
3050
3051 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3052}
3053
3054static int selinux_file_lock(struct file *file, unsigned int cmd)
3055{
3056 return file_has_perm(current, file, FILE__LOCK);
3057}
3058
3059static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3060 unsigned long arg)
3061{
3062 int err = 0;
3063
3064 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003065 case F_SETFL:
3066 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3067 err = -EINVAL;
3068 break;
3069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
Eric Paris828dfe12008-04-17 13:17:49 -04003071 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
3072 err = file_has_perm(current, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003074 }
3075 /* fall through */
3076 case F_SETOWN:
3077 case F_SETSIG:
3078 case F_GETFL:
3079 case F_GETOWN:
3080 case F_GETSIG:
3081 /* Just check FD__USE permission */
3082 err = file_has_perm(current, file, 0);
3083 break;
3084 case F_GETLK:
3085 case F_SETLK:
3086 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003088 case F_GETLK64:
3089 case F_SETLK64:
3090 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003092 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3093 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003095 }
3096 err = file_has_perm(current, file, FILE__LOCK);
3097 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 }
3099
3100 return err;
3101}
3102
3103static int selinux_file_set_fowner(struct file *file)
3104{
3105 struct task_security_struct *tsec;
3106 struct file_security_struct *fsec;
3107
3108 tsec = current->security;
3109 fsec = file->f_security;
3110 fsec->fown_sid = tsec->sid;
3111
3112 return 0;
3113}
3114
3115static int selinux_file_send_sigiotask(struct task_struct *tsk,
3116 struct fown_struct *fown, int signum)
3117{
Eric Paris828dfe12008-04-17 13:17:49 -04003118 struct file *file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 u32 perm;
3120 struct task_security_struct *tsec;
3121 struct file_security_struct *fsec;
3122
3123 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003124 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125
3126 tsec = tsk->security;
3127 fsec = file->f_security;
3128
3129 if (!signum)
3130 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3131 else
3132 perm = signal_to_av(signum);
3133
3134 return avc_has_perm(fsec->fown_sid, tsec->sid,
3135 SECCLASS_PROCESS, perm, NULL);
3136}
3137
3138static int selinux_file_receive(struct file *file)
3139{
3140 return file_has_perm(current, file, file_to_av(file));
3141}
3142
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003143static int selinux_dentry_open(struct file *file)
3144{
3145 struct file_security_struct *fsec;
3146 struct inode *inode;
3147 struct inode_security_struct *isec;
3148 inode = file->f_path.dentry->d_inode;
3149 fsec = file->f_security;
3150 isec = inode->i_security;
3151 /*
3152 * Save inode label and policy sequence number
3153 * at open-time so that selinux_file_permission
3154 * can determine whether revalidation is necessary.
3155 * Task label is already saved in the file security
3156 * struct as its SID.
3157 */
3158 fsec->isid = isec->sid;
3159 fsec->pseqno = avc_policy_seqno();
3160 /*
3161 * Since the inode label or policy seqno may have changed
3162 * between the selinux_inode_permission check and the saving
3163 * of state above, recheck that access is still permitted.
3164 * Otherwise, access might never be revalidated against the
3165 * new inode label or new policy.
3166 * This check is not redundant - do not remove.
3167 */
Eric Paris8b6a5a32008-10-29 17:06:46 -04003168 return inode_has_perm(current, inode, open_file_to_av(file), NULL);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003169}
3170
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171/* task security operations */
3172
3173static int selinux_task_create(unsigned long clone_flags)
3174{
3175 int rc;
3176
3177 rc = secondary_ops->task_create(clone_flags);
3178 if (rc)
3179 return rc;
3180
3181 return task_has_perm(current, current, PROCESS__FORK);
3182}
3183
3184static int selinux_task_alloc_security(struct task_struct *tsk)
3185{
3186 struct task_security_struct *tsec1, *tsec2;
3187 int rc;
3188
3189 tsec1 = current->security;
3190
3191 rc = task_alloc_security(tsk);
3192 if (rc)
3193 return rc;
3194 tsec2 = tsk->security;
3195
3196 tsec2->osid = tsec1->osid;
3197 tsec2->sid = tsec1->sid;
3198
Michael LeMay28eba5b2006-06-27 02:53:42 -07003199 /* Retain the exec, fs, key, and sock SIDs across fork */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 tsec2->exec_sid = tsec1->exec_sid;
3201 tsec2->create_sid = tsec1->create_sid;
Michael LeMay28eba5b2006-06-27 02:53:42 -07003202 tsec2->keycreate_sid = tsec1->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07003203 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 return 0;
3206}
3207
3208static void selinux_task_free_security(struct task_struct *tsk)
3209{
3210 task_free_security(tsk);
3211}
3212
3213static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3214{
3215 /* Since setuid only affects the current process, and
3216 since the SELinux controls are not based on the Linux
3217 identity attributes, SELinux does not need to control
3218 this operation. However, SELinux does control the use
3219 of the CAP_SETUID and CAP_SETGID capabilities using the
3220 capable hook. */
3221 return 0;
3222}
3223
3224static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3225{
Eric Paris828dfe12008-04-17 13:17:49 -04003226 return secondary_ops->task_post_setuid(id0, id1, id2, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
3229static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3230{
3231 /* See the comment for setuid above. */
3232 return 0;
3233}
3234
3235static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3236{
3237 return task_has_perm(current, p, PROCESS__SETPGID);
3238}
3239
3240static int selinux_task_getpgid(struct task_struct *p)
3241{
3242 return task_has_perm(current, p, PROCESS__GETPGID);
3243}
3244
3245static int selinux_task_getsid(struct task_struct *p)
3246{
3247 return task_has_perm(current, p, PROCESS__GETSESSION);
3248}
3249
David Quigleyf9008e42006-06-30 01:55:46 -07003250static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3251{
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003252 struct task_security_struct *tsec = p->security;
3253 *secid = tsec->sid;
David Quigleyf9008e42006-06-30 01:55:46 -07003254}
3255
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256static int selinux_task_setgroups(struct group_info *group_info)
3257{
3258 /* See the comment for setuid above. */
3259 return 0;
3260}
3261
3262static int selinux_task_setnice(struct task_struct *p, int nice)
3263{
3264 int rc;
3265
3266 rc = secondary_ops->task_setnice(p, nice);
3267 if (rc)
3268 return rc;
3269
Eric Paris828dfe12008-04-17 13:17:49 -04003270 return task_has_perm(current, p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271}
3272
James Morris03e68062006-06-23 02:03:58 -07003273static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3274{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003275 int rc;
3276
3277 rc = secondary_ops->task_setioprio(p, ioprio);
3278 if (rc)
3279 return rc;
3280
James Morris03e68062006-06-23 02:03:58 -07003281 return task_has_perm(current, p, PROCESS__SETSCHED);
3282}
3283
David Quigleya1836a42006-06-30 01:55:49 -07003284static int selinux_task_getioprio(struct task_struct *p)
3285{
3286 return task_has_perm(current, p, PROCESS__GETSCHED);
3287}
3288
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3290{
3291 struct rlimit *old_rlim = current->signal->rlim + resource;
3292 int rc;
3293
3294 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3295 if (rc)
3296 return rc;
3297
3298 /* Control the ability to change the hard limit (whether
3299 lowering or raising it), so that the hard limit can
3300 later be used as a safe reset point for the soft limit
3301 upon context transitions. See selinux_bprm_apply_creds. */
3302 if (old_rlim->rlim_max != new_rlim->rlim_max)
3303 return task_has_perm(current, current, PROCESS__SETRLIMIT);
3304
3305 return 0;
3306}
3307
3308static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
3309{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003310 int rc;
3311
3312 rc = secondary_ops->task_setscheduler(p, policy, lp);
3313 if (rc)
3314 return rc;
3315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 return task_has_perm(current, p, PROCESS__SETSCHED);
3317}
3318
3319static int selinux_task_getscheduler(struct task_struct *p)
3320{
3321 return task_has_perm(current, p, PROCESS__GETSCHED);
3322}
3323
David Quigley35601542006-06-23 02:04:01 -07003324static int selinux_task_movememory(struct task_struct *p)
3325{
3326 return task_has_perm(current, p, PROCESS__SETSCHED);
3327}
3328
David Quigleyf9008e42006-06-30 01:55:46 -07003329static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3330 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331{
3332 u32 perm;
3333 int rc;
David Quigleyf9008e42006-06-30 01:55:46 -07003334 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
David Quigleyf9008e42006-06-30 01:55:46 -07003336 rc = secondary_ops->task_kill(p, info, sig, secid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 if (rc)
3338 return rc;
3339
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 if (!sig)
3341 perm = PROCESS__SIGNULL; /* null signal; existence test */
3342 else
3343 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003344 tsec = p->security;
3345 if (secid)
3346 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
3347 else
3348 rc = task_has_perm(current, p, perm);
3349 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350}
3351
3352static int selinux_task_prctl(int option,
3353 unsigned long arg2,
3354 unsigned long arg3,
3355 unsigned long arg4,
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003356 unsigned long arg5,
3357 long *rc_p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358{
3359 /* The current prctl operations do not appear to require
3360 any SELinux controls since they merely observe or modify
3361 the state of the current process. */
Andrew G. Morgan3898b1b2008-04-28 02:13:40 -07003362 return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363}
3364
3365static int selinux_task_wait(struct task_struct *p)
3366{
Eric Paris8a535142007-10-22 16:10:31 -04003367 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368}
3369
3370static void selinux_task_reparent_to_init(struct task_struct *p)
3371{
Eric Paris828dfe12008-04-17 13:17:49 -04003372 struct task_security_struct *tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
3374 secondary_ops->task_reparent_to_init(p);
3375
3376 tsec = p->security;
3377 tsec->osid = tsec->sid;
3378 tsec->sid = SECINITSID_KERNEL;
3379 return;
3380}
3381
3382static void selinux_task_to_inode(struct task_struct *p,
3383 struct inode *inode)
3384{
3385 struct task_security_struct *tsec = p->security;
3386 struct inode_security_struct *isec = inode->i_security;
3387
3388 isec->sid = tsec->sid;
3389 isec->initialized = 1;
3390 return;
3391}
3392
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003394static int selinux_parse_skb_ipv4(struct sk_buff *skb,
3395 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396{
3397 int offset, ihlen, ret = -EINVAL;
3398 struct iphdr _iph, *ih;
3399
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003400 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3402 if (ih == NULL)
3403 goto out;
3404
3405 ihlen = ih->ihl * 4;
3406 if (ihlen < sizeof(_iph))
3407 goto out;
3408
3409 ad->u.net.v4info.saddr = ih->saddr;
3410 ad->u.net.v4info.daddr = ih->daddr;
3411 ret = 0;
3412
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003413 if (proto)
3414 *proto = ih->protocol;
3415
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003417 case IPPROTO_TCP: {
3418 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419
Eric Paris828dfe12008-04-17 13:17:49 -04003420 if (ntohs(ih->frag_off) & IP_OFFSET)
3421 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
3423 offset += ihlen;
3424 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3425 if (th == NULL)
3426 break;
3427
3428 ad->u.net.sport = th->source;
3429 ad->u.net.dport = th->dest;
3430 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Eric Paris828dfe12008-04-17 13:17:49 -04003433 case IPPROTO_UDP: {
3434 struct udphdr _udph, *uh;
3435
3436 if (ntohs(ih->frag_off) & IP_OFFSET)
3437 break;
3438
3439 offset += ihlen;
3440 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3441 if (uh == NULL)
3442 break;
3443
3444 ad->u.net.sport = uh->source;
3445 ad->u.net.dport = uh->dest;
3446 break;
3447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448
James Morris2ee92d42006-11-13 16:09:01 -08003449 case IPPROTO_DCCP: {
3450 struct dccp_hdr _dccph, *dh;
3451
3452 if (ntohs(ih->frag_off) & IP_OFFSET)
3453 break;
3454
3455 offset += ihlen;
3456 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3457 if (dh == NULL)
3458 break;
3459
3460 ad->u.net.sport = dh->dccph_sport;
3461 ad->u.net.dport = dh->dccph_dport;
3462 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003463 }
James Morris2ee92d42006-11-13 16:09:01 -08003464
Eric Paris828dfe12008-04-17 13:17:49 -04003465 default:
3466 break;
3467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468out:
3469 return ret;
3470}
3471
3472#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3473
3474/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003475static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3476 struct avc_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477{
3478 u8 nexthdr;
3479 int ret = -EINVAL, offset;
3480 struct ipv6hdr _ipv6h, *ip6;
3481
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003482 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3484 if (ip6 == NULL)
3485 goto out;
3486
3487 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
3488 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
3489 ret = 0;
3490
3491 nexthdr = ip6->nexthdr;
3492 offset += sizeof(_ipv6h);
Herbert Xu0d3d0772005-04-24 20:16:19 -07003493 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 if (offset < 0)
3495 goto out;
3496
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003497 if (proto)
3498 *proto = nexthdr;
3499
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 switch (nexthdr) {
3501 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003502 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503
3504 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3505 if (th == NULL)
3506 break;
3507
3508 ad->u.net.sport = th->source;
3509 ad->u.net.dport = th->dest;
3510 break;
3511 }
3512
3513 case IPPROTO_UDP: {
3514 struct udphdr _udph, *uh;
3515
3516 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3517 if (uh == NULL)
3518 break;
3519
3520 ad->u.net.sport = uh->source;
3521 ad->u.net.dport = uh->dest;
3522 break;
3523 }
3524
James Morris2ee92d42006-11-13 16:09:01 -08003525 case IPPROTO_DCCP: {
3526 struct dccp_hdr _dccph, *dh;
3527
3528 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3529 if (dh == NULL)
3530 break;
3531
3532 ad->u.net.sport = dh->dccph_sport;
3533 ad->u.net.dport = dh->dccph_dport;
3534 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003535 }
James Morris2ee92d42006-11-13 16:09:01 -08003536
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 /* includes fragments */
3538 default:
3539 break;
3540 }
3541out:
3542 return ret;
3543}
3544
3545#endif /* IPV6 */
3546
3547static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003548 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549{
David Howellscf9481e2008-07-27 21:31:07 +10003550 char *addrp;
3551 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552
3553 switch (ad->u.net.family) {
3554 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003555 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003556 if (ret)
3557 goto parse_error;
3558 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3559 &ad->u.net.v4info.daddr);
3560 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
3562#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3563 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003564 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003565 if (ret)
3566 goto parse_error;
3567 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3568 &ad->u.net.v6info.daddr);
3569 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570#endif /* IPV6 */
3571 default:
David Howellscf9481e2008-07-27 21:31:07 +10003572 addrp = NULL;
3573 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 }
3575
David Howellscf9481e2008-07-27 21:31:07 +10003576parse_error:
3577 printk(KERN_WARNING
3578 "SELinux: failure in selinux_parse_skb(),"
3579 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003581
3582okay:
3583 if (_addrp)
3584 *_addrp = addrp;
3585 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586}
3587
Paul Moore4f6a9932007-03-01 14:35:22 -05003588/**
Paul Moore220deb92008-01-29 08:38:23 -05003589 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003590 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003591 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003592 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003593 *
3594 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003595 * Check the various different forms of network peer labeling and determine
3596 * the peer label/SID for the packet; most of the magic actually occurs in
3597 * the security server function security_net_peersid_cmp(). The function
3598 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3599 * or -EACCES if @sid is invalid due to inconsistencies with the different
3600 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003601 *
3602 */
Paul Moore220deb92008-01-29 08:38:23 -05003603static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003604{
Paul Moore71f1cb02008-01-29 08:51:16 -05003605 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003606 u32 xfrm_sid;
3607 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003608 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003609
3610 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003611 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003612
Paul Moore71f1cb02008-01-29 08:51:16 -05003613 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3614 if (unlikely(err)) {
3615 printk(KERN_WARNING
3616 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3617 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003618 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003619 }
Paul Moore220deb92008-01-29 08:38:23 -05003620
3621 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003622}
3623
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624/* socket security operations */
3625static int socket_has_perm(struct task_struct *task, struct socket *sock,
3626 u32 perms)
3627{
3628 struct inode_security_struct *isec;
3629 struct task_security_struct *tsec;
3630 struct avc_audit_data ad;
3631 int err = 0;
3632
3633 tsec = task->security;
3634 isec = SOCK_INODE(sock)->i_security;
3635
3636 if (isec->sid == SECINITSID_KERNEL)
3637 goto out;
3638
Eric Paris828dfe12008-04-17 13:17:49 -04003639 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 ad.u.net.sk = sock->sk;
3641 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
3642
3643out:
3644 return err;
3645}
3646
3647static int selinux_socket_create(int family, int type,
3648 int protocol, int kern)
3649{
3650 int err = 0;
3651 struct task_security_struct *tsec;
Eric Paris42c3e032006-06-26 00:26:03 -07003652 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
3654 if (kern)
3655 goto out;
3656
3657 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003658 newsid = tsec->sockcreate_sid ? : tsec->sid;
3659 err = avc_has_perm(tsec->sid, newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 socket_type_to_security_class(family, type,
3661 protocol), SOCKET__CREATE, NULL);
3662
3663out:
3664 return err;
3665}
3666
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003667static int selinux_socket_post_create(struct socket *sock, int family,
3668 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003670 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 struct inode_security_struct *isec;
3672 struct task_security_struct *tsec;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003673 struct sk_security_struct *sksec;
Eric Paris42c3e032006-06-26 00:26:03 -07003674 u32 newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675
3676 isec = SOCK_INODE(sock)->i_security;
3677
3678 tsec = current->security;
Eric Paris42c3e032006-06-26 00:26:03 -07003679 newsid = tsec->sockcreate_sid ? : tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 isec->sclass = socket_type_to_security_class(family, type, protocol);
Eric Paris42c3e032006-06-26 00:26:03 -07003681 isec->sid = kern ? SECINITSID_KERNEL : newsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 isec->initialized = 1;
3683
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003684 if (sock->sk) {
3685 sksec = sock->sk->sk_security;
3686 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003687 sksec->sclass = isec->sclass;
Paul Moore9f2ad662006-11-17 17:38:53 -05003688 err = selinux_netlbl_socket_post_create(sock);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003689 }
3690
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003691 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692}
3693
3694/* Range of port numbers used to automatically bind.
3695 Need to determine whether we should perform a name_bind
3696 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
3698static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3699{
3700 u16 family;
3701 int err;
3702
3703 err = socket_has_perm(current, sock, SOCKET__BIND);
3704 if (err)
3705 goto out;
3706
3707 /*
3708 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003709 * Multiple address binding for SCTP is not supported yet: we just
3710 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 */
3712 family = sock->sk->sk_family;
3713 if (family == PF_INET || family == PF_INET6) {
3714 char *addrp;
3715 struct inode_security_struct *isec;
3716 struct task_security_struct *tsec;
3717 struct avc_audit_data ad;
3718 struct sockaddr_in *addr4 = NULL;
3719 struct sockaddr_in6 *addr6 = NULL;
3720 unsigned short snum;
3721 struct sock *sk = sock->sk;
James Morrise399f982008-06-12 01:39:58 +10003722 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
3724 tsec = current->security;
3725 isec = SOCK_INODE(sock)->i_security;
3726
3727 if (family == PF_INET) {
3728 addr4 = (struct sockaddr_in *)address;
3729 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 addrp = (char *)&addr4->sin_addr.s_addr;
3731 } else {
3732 addr6 = (struct sockaddr_in6 *)address;
3733 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 addrp = (char *)&addr6->sin6_addr.s6_addr;
3735 }
3736
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003737 if (snum) {
3738 int low, high;
3739
3740 inet_get_local_port_range(&low, &high);
3741
3742 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003743 err = sel_netport_sid(sk->sk_protocol,
3744 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003745 if (err)
3746 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003747 AVC_AUDIT_DATA_INIT(&ad, NET);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003748 ad.u.net.sport = htons(snum);
3749 ad.u.net.family = family;
3750 err = avc_has_perm(isec->sid, sid,
3751 isec->sclass,
3752 SOCKET__NAME_BIND, &ad);
3753 if (err)
3754 goto out;
3755 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 }
Eric Paris828dfe12008-04-17 13:17:49 -04003757
3758 switch (isec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003759 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 node_perm = TCP_SOCKET__NODE_BIND;
3761 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003762
James Morris13402582005-09-30 14:24:34 -04003763 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 node_perm = UDP_SOCKET__NODE_BIND;
3765 break;
James Morris2ee92d42006-11-13 16:09:01 -08003766
3767 case SECCLASS_DCCP_SOCKET:
3768 node_perm = DCCP_SOCKET__NODE_BIND;
3769 break;
3770
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 default:
3772 node_perm = RAWIP_SOCKET__NODE_BIND;
3773 break;
3774 }
Eric Paris828dfe12008-04-17 13:17:49 -04003775
Paul Moore224dfbd2008-01-29 08:38:13 -05003776 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 if (err)
3778 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003779
3780 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 ad.u.net.sport = htons(snum);
3782 ad.u.net.family = family;
3783
3784 if (family == PF_INET)
3785 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3786 else
3787 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3788
3789 err = avc_has_perm(isec->sid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003790 isec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 if (err)
3792 goto out;
3793 }
3794out:
3795 return err;
3796}
3797
3798static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3799{
Paul Moore014ab192008-10-10 10:16:33 -04003800 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 struct inode_security_struct *isec;
3802 int err;
3803
3804 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3805 if (err)
3806 return err;
3807
3808 /*
James Morris2ee92d42006-11-13 16:09:01 -08003809 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 */
3811 isec = SOCK_INODE(sock)->i_security;
James Morris2ee92d42006-11-13 16:09:01 -08003812 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3813 isec->sclass == SECCLASS_DCCP_SOCKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 struct avc_audit_data ad;
3815 struct sockaddr_in *addr4 = NULL;
3816 struct sockaddr_in6 *addr6 = NULL;
3817 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003818 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819
3820 if (sk->sk_family == PF_INET) {
3821 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003822 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 return -EINVAL;
3824 snum = ntohs(addr4->sin_port);
3825 } else {
3826 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003827 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 return -EINVAL;
3829 snum = ntohs(addr6->sin6_port);
3830 }
3831
Paul Moore3e112172008-04-10 10:48:14 -04003832 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 if (err)
3834 goto out;
3835
James Morris2ee92d42006-11-13 16:09:01 -08003836 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3837 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3838
Eric Paris828dfe12008-04-17 13:17:49 -04003839 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 ad.u.net.dport = htons(snum);
3841 ad.u.net.family = sk->sk_family;
James Morris2ee92d42006-11-13 16:09:01 -08003842 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 if (err)
3844 goto out;
3845 }
3846
Paul Moore014ab192008-10-10 10:16:33 -04003847 err = selinux_netlbl_socket_connect(sk, address);
3848
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849out:
3850 return err;
3851}
3852
3853static int selinux_socket_listen(struct socket *sock, int backlog)
3854{
3855 return socket_has_perm(current, sock, SOCKET__LISTEN);
3856}
3857
3858static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3859{
3860 int err;
3861 struct inode_security_struct *isec;
3862 struct inode_security_struct *newisec;
3863
3864 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3865 if (err)
3866 return err;
3867
3868 newisec = SOCK_INODE(newsock)->i_security;
3869
3870 isec = SOCK_INODE(sock)->i_security;
3871 newisec->sclass = isec->sclass;
3872 newisec->sid = isec->sid;
3873 newisec->initialized = 1;
3874
3875 return 0;
3876}
3877
3878static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04003879 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880{
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003881 int rc;
3882
3883 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3884 if (rc)
3885 return rc;
3886
3887 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
3890static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3891 int size, int flags)
3892{
3893 return socket_has_perm(current, sock, SOCKET__READ);
3894}
3895
3896static int selinux_socket_getsockname(struct socket *sock)
3897{
3898 return socket_has_perm(current, sock, SOCKET__GETATTR);
3899}
3900
3901static int selinux_socket_getpeername(struct socket *sock)
3902{
3903 return socket_has_perm(current, sock, SOCKET__GETATTR);
3904}
3905
Eric Paris828dfe12008-04-17 13:17:49 -04003906static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907{
Paul Mooref8687af2006-10-30 15:22:15 -08003908 int err;
3909
3910 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3911 if (err)
3912 return err;
3913
3914 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915}
3916
3917static int selinux_socket_getsockopt(struct socket *sock, int level,
3918 int optname)
3919{
3920 return socket_has_perm(current, sock, SOCKET__GETOPT);
3921}
3922
3923static int selinux_socket_shutdown(struct socket *sock, int how)
3924{
3925 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3926}
3927
3928static int selinux_socket_unix_stream_connect(struct socket *sock,
3929 struct socket *other,
3930 struct sock *newsk)
3931{
3932 struct sk_security_struct *ssec;
3933 struct inode_security_struct *isec;
3934 struct inode_security_struct *other_isec;
3935 struct avc_audit_data ad;
3936 int err;
3937
3938 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3939 if (err)
3940 return err;
3941
3942 isec = SOCK_INODE(sock)->i_security;
3943 other_isec = SOCK_INODE(other)->i_security;
3944
Eric Paris828dfe12008-04-17 13:17:49 -04003945 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 ad.u.net.sk = other->sk;
3947
3948 err = avc_has_perm(isec->sid, other_isec->sid,
3949 isec->sclass,
3950 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3951 if (err)
3952 return err;
3953
3954 /* connecting socket */
3955 ssec = sock->sk->sk_security;
3956 ssec->peer_sid = other_isec->sid;
Eric Paris828dfe12008-04-17 13:17:49 -04003957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 /* server child socket */
3959 ssec = newsk->sk_security;
3960 ssec->peer_sid = isec->sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07003961 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3962
3963 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964}
3965
3966static int selinux_socket_unix_may_send(struct socket *sock,
3967 struct socket *other)
3968{
3969 struct inode_security_struct *isec;
3970 struct inode_security_struct *other_isec;
3971 struct avc_audit_data ad;
3972 int err;
3973
3974 isec = SOCK_INODE(sock)->i_security;
3975 other_isec = SOCK_INODE(other)->i_security;
3976
Eric Paris828dfe12008-04-17 13:17:49 -04003977 AVC_AUDIT_DATA_INIT(&ad, NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 ad.u.net.sk = other->sk;
3979
3980 err = avc_has_perm(isec->sid, other_isec->sid,
3981 isec->sclass, SOCKET__SENDTO, &ad);
3982 if (err)
3983 return err;
3984
3985 return 0;
3986}
3987
Paul Mooreeffad8d2008-01-29 08:49:27 -05003988static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3989 u32 peer_sid,
3990 struct avc_audit_data *ad)
3991{
3992 int err;
3993 u32 if_sid;
3994 u32 node_sid;
3995
3996 err = sel_netif_sid(ifindex, &if_sid);
3997 if (err)
3998 return err;
3999 err = avc_has_perm(peer_sid, if_sid,
4000 SECCLASS_NETIF, NETIF__INGRESS, ad);
4001 if (err)
4002 return err;
4003
4004 err = sel_netnode_sid(addrp, family, &node_sid);
4005 if (err)
4006 return err;
4007 return avc_has_perm(peer_sid, node_sid,
4008 SECCLASS_NODE, NODE__RECVFROM, ad);
4009}
4010
Paul Moore220deb92008-01-29 08:38:23 -05004011static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4012 struct sk_buff *skb,
4013 struct avc_audit_data *ad,
4014 u16 family,
4015 char *addrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016{
Paul Moore220deb92008-01-29 08:38:23 -05004017 int err;
4018 struct sk_security_struct *sksec = sk->sk_security;
4019 u16 sk_class;
4020 u32 netif_perm, node_perm, recv_perm;
4021 u32 port_sid, node_sid, if_sid, sk_sid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004022
Paul Moore220deb92008-01-29 08:38:23 -05004023 sk_sid = sksec->sid;
4024 sk_class = sksec->sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025
Paul Moore220deb92008-01-29 08:38:23 -05004026 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 case SECCLASS_UDP_SOCKET:
4028 netif_perm = NETIF__UDP_RECV;
4029 node_perm = NODE__UDP_RECV;
4030 recv_perm = UDP_SOCKET__RECV_MSG;
4031 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 case SECCLASS_TCP_SOCKET:
4033 netif_perm = NETIF__TCP_RECV;
4034 node_perm = NODE__TCP_RECV;
4035 recv_perm = TCP_SOCKET__RECV_MSG;
4036 break;
James Morris2ee92d42006-11-13 16:09:01 -08004037 case SECCLASS_DCCP_SOCKET:
4038 netif_perm = NETIF__DCCP_RECV;
4039 node_perm = NODE__DCCP_RECV;
4040 recv_perm = DCCP_SOCKET__RECV_MSG;
4041 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 default:
4043 netif_perm = NETIF__RAWIP_RECV;
4044 node_perm = NODE__RAWIP_RECV;
Paul Moore220deb92008-01-29 08:38:23 -05004045 recv_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 break;
4047 }
4048
Paul Moore220deb92008-01-29 08:38:23 -05004049 err = sel_netif_sid(skb->iif, &if_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004051 return err;
4052 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4053 if (err)
4054 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004055
Paul Moore224dfbd2008-01-29 08:38:13 -05004056 err = sel_netnode_sid(addrp, family, &node_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004058 return err;
4059 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004061 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
Paul Moore220deb92008-01-29 08:38:23 -05004063 if (!recv_perm)
4064 return 0;
Paul Moore3e112172008-04-10 10:48:14 -04004065 err = sel_netport_sid(sk->sk_protocol,
4066 ntohs(ad->u.net.sport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004067 if (unlikely(err)) {
4068 printk(KERN_WARNING
4069 "SELinux: failure in"
4070 " selinux_sock_rcv_skb_iptables_compat(),"
4071 " network port label not found\n");
Paul Moore220deb92008-01-29 08:38:23 -05004072 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004073 }
Paul Moore220deb92008-01-29 08:38:23 -05004074 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4075}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076
Paul Moore220deb92008-01-29 08:38:23 -05004077static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004078 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004079{
4080 int err;
4081 struct sk_security_struct *sksec = sk->sk_security;
4082 u32 peer_sid;
4083 u32 sk_sid = sksec->sid;
Paul Moored8395c82008-10-10 10:16:30 -04004084 struct avc_audit_data ad;
4085 char *addrp;
4086
4087 AVC_AUDIT_DATA_INIT(&ad, NET);
4088 ad.u.net.netif = skb->iif;
4089 ad.u.net.family = family;
4090 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4091 if (err)
4092 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004093
4094 if (selinux_compat_net)
Paul Moored8395c82008-10-10 10:16:30 -04004095 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
Paul Moore220deb92008-01-29 08:38:23 -05004096 family, addrp);
4097 else
4098 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004099 PACKET__RECV, &ad);
Paul Moore220deb92008-01-29 08:38:23 -05004100 if (err)
4101 return err;
4102
4103 if (selinux_policycap_netpeer) {
4104 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004106 return err;
4107 err = avc_has_perm(sk_sid, peer_sid,
Paul Moored8395c82008-10-10 10:16:30 -04004108 SECCLASS_PEER, PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004109 if (err)
4110 selinux_netlbl_err(skb, err, 0);
Paul Moore220deb92008-01-29 08:38:23 -05004111 } else {
Paul Moored8395c82008-10-10 10:16:30 -04004112 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
Paul Moore220deb92008-01-29 08:38:23 -05004113 if (err)
4114 return err;
Paul Moored8395c82008-10-10 10:16:30 -04004115 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004117
James Morris4e5ab4c2006-06-09 00:33:33 -07004118 return err;
4119}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004120
James Morris4e5ab4c2006-06-09 00:33:33 -07004121static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4122{
Paul Moore220deb92008-01-29 08:38:23 -05004123 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004124 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004125 u16 family = sk->sk_family;
4126 u32 sk_sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004127 struct avc_audit_data ad;
4128 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004129 u8 secmark_active;
4130 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004131
James Morris4e5ab4c2006-06-09 00:33:33 -07004132 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004133 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004134
4135 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004136 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004137 family = PF_INET;
4138
Paul Moored8395c82008-10-10 10:16:30 -04004139 /* If any sort of compatibility mode is enabled then handoff processing
4140 * to the selinux_sock_rcv_skb_compat() function to deal with the
4141 * special handling. We do this in an attempt to keep this function
4142 * as fast and as clean as possible. */
4143 if (selinux_compat_net || !selinux_policycap_netpeer)
4144 return selinux_sock_rcv_skb_compat(sk, skb, family);
4145
4146 secmark_active = selinux_secmark_enabled();
4147 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4148 if (!secmark_active && !peerlbl_active)
4149 return 0;
4150
James Morris4e5ab4c2006-06-09 00:33:33 -07004151 AVC_AUDIT_DATA_INIT(&ad, NET);
Paul Mooreda5645a2008-01-29 08:38:10 -05004152 ad.u.net.netif = skb->iif;
James Morris4e5ab4c2006-06-09 00:33:33 -07004153 ad.u.net.family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004154 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004155 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004156 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004157
Paul Moored8395c82008-10-10 10:16:30 -04004158 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004159 u32 peer_sid;
4160
4161 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4162 if (err)
4163 return err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004164 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4165 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004166 if (err) {
4167 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004168 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004169 }
Paul Moored621d352008-01-29 08:43:36 -05004170 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4171 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004172 if (err)
4173 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004174 }
4175
Paul Moored8395c82008-10-10 10:16:30 -04004176 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004177 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4178 PACKET__RECV, &ad);
4179 if (err)
4180 return err;
4181 }
4182
Paul Moored621d352008-01-29 08:43:36 -05004183 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184}
4185
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004186static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4187 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188{
4189 int err = 0;
4190 char *scontext;
4191 u32 scontext_len;
4192 struct sk_security_struct *ssec;
4193 struct inode_security_struct *isec;
Paul Moore3de4bab2006-11-17 17:38:54 -05004194 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
4196 isec = SOCK_INODE(sock)->i_security;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004197
Paul Moore3de4bab2006-11-17 17:38:54 -05004198 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4199 isec->sclass == SECCLASS_TCP_SOCKET) {
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004200 ssec = sock->sk->sk_security;
4201 peer_sid = ssec->peer_sid;
4202 }
Paul Moore3de4bab2006-11-17 17:38:54 -05004203 if (peer_sid == SECSID_NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 err = -ENOPROTOOPT;
4205 goto out;
4206 }
4207
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004208 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4209
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 if (err)
4211 goto out;
4212
4213 if (scontext_len > len) {
4214 err = -ERANGE;
4215 goto out_len;
4216 }
4217
4218 if (copy_to_user(optval, scontext, scontext_len))
4219 err = -EFAULT;
4220
4221out_len:
4222 if (put_user(scontext_len, optlen))
4223 err = -EFAULT;
4224
4225 kfree(scontext);
Eric Paris828dfe12008-04-17 13:17:49 -04004226out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 return err;
4228}
4229
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004230static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004231{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004232 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004233 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004234
Paul Mooreaa862902008-10-10 10:16:29 -04004235 if (skb && skb->protocol == htons(ETH_P_IP))
4236 family = PF_INET;
4237 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4238 family = PF_INET6;
4239 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004240 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004241 else
4242 goto out;
4243
4244 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004245 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004246 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004247 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004248
Paul Moore75e22912008-01-29 08:38:04 -05004249out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004250 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004251 if (peer_secid == SECSID_NULL)
4252 return -EINVAL;
4253 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004254}
4255
Al Viro7d877f32005-10-21 03:20:43 -04004256static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257{
4258 return sk_alloc_security(sk, family, priority);
4259}
4260
4261static void selinux_sk_free_security(struct sock *sk)
4262{
4263 sk_free_security(sk);
4264}
4265
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004266static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4267{
4268 struct sk_security_struct *ssec = sk->sk_security;
4269 struct sk_security_struct *newssec = newsk->sk_security;
4270
4271 newssec->sid = ssec->sid;
4272 newssec->peer_sid = ssec->peer_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004273 newssec->sclass = ssec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004274
Paul Mooref74af6e2008-02-25 11:40:33 -05004275 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004276}
4277
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004278static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004279{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004280 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004281 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004282 else {
4283 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004284
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004285 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004286 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004287}
4288
Eric Paris828dfe12008-04-17 13:17:49 -04004289static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004290{
4291 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4292 struct sk_security_struct *sksec = sk->sk_security;
4293
David Woodhouse2148ccc2006-09-29 15:50:25 -07004294 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4295 sk->sk_family == PF_UNIX)
4296 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004297 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004298}
4299
Adrian Bunk9a673e52006-08-15 00:03:53 -07004300static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4301 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004302{
4303 struct sk_security_struct *sksec = sk->sk_security;
4304 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004305 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004306 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004307 u32 peersid;
4308
Paul Mooreaa862902008-10-10 10:16:29 -04004309 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4310 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4311 family = PF_INET;
4312
4313 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004314 if (err)
4315 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004316 if (peersid == SECSID_NULL) {
4317 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004318 req->peer_secid = SECSID_NULL;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004319 return 0;
4320 }
4321
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004322 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4323 if (err)
4324 return err;
4325
4326 req->secid = newsid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004327 req->peer_secid = peersid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004328 return 0;
4329}
4330
Adrian Bunk9a673e52006-08-15 00:03:53 -07004331static void selinux_inet_csk_clone(struct sock *newsk,
4332 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004333{
4334 struct sk_security_struct *newsksec = newsk->sk_security;
4335
4336 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004337 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004338 /* NOTE: Ideally, we should also get the isec->sid for the
4339 new socket in sync, but we don't have the isec available yet.
4340 So we will wait until sock_graft to do it, by which
4341 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004342
Paul Moore9f2ad662006-11-17 17:38:53 -05004343 /* We don't need to take any sort of lock here as we are the only
4344 * thread with access to newsksec */
4345 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004346}
4347
Paul Moore014ab192008-10-10 10:16:33 -04004348static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004349{
Paul Mooreaa862902008-10-10 10:16:29 -04004350 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004351 struct sk_security_struct *sksec = sk->sk_security;
4352
Paul Mooreaa862902008-10-10 10:16:29 -04004353 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4354 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4355 family = PF_INET;
4356
4357 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Paul Moore014ab192008-10-10 10:16:33 -04004358
4359 selinux_netlbl_inet_conn_established(sk, family);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004360}
4361
Adrian Bunk9a673e52006-08-15 00:03:53 -07004362static void selinux_req_classify_flow(const struct request_sock *req,
4363 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004364{
4365 fl->secid = req->secid;
4366}
4367
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4369{
4370 int err = 0;
4371 u32 perm;
4372 struct nlmsghdr *nlh;
4373 struct socket *sock = sk->sk_socket;
4374 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004375
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 if (skb->len < NLMSG_SPACE(0)) {
4377 err = -EINVAL;
4378 goto out;
4379 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004380 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004381
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4383 if (err) {
4384 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004385 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 "SELinux: unrecognized netlink message"
4387 " type=%hu for sclass=%hu\n",
4388 nlh->nlmsg_type, isec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004389 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 err = 0;
4391 }
4392
4393 /* Ignore */
4394 if (err == -ENOENT)
4395 err = 0;
4396 goto out;
4397 }
4398
4399 err = socket_has_perm(current, sock, perm);
4400out:
4401 return err;
4402}
4403
4404#ifdef CONFIG_NETFILTER
4405
Paul Mooreeffad8d2008-01-29 08:49:27 -05004406static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4407 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
Paul Mooredfaebe92008-10-10 10:16:31 -04004409 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004410 char *addrp;
4411 u32 peer_sid;
4412 struct avc_audit_data ad;
4413 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004414 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004415 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004416
Paul Mooreeffad8d2008-01-29 08:49:27 -05004417 if (!selinux_policycap_netpeer)
4418 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004419
Paul Mooreeffad8d2008-01-29 08:49:27 -05004420 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004421 netlbl_active = netlbl_enabled();
4422 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004423 if (!secmark_active && !peerlbl_active)
4424 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004425
Paul Moored8395c82008-10-10 10:16:30 -04004426 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4427 return NF_DROP;
4428
Paul Mooreeffad8d2008-01-29 08:49:27 -05004429 AVC_AUDIT_DATA_INIT(&ad, NET);
4430 ad.u.net.netif = ifindex;
4431 ad.u.net.family = family;
4432 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4433 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Paul Mooredfaebe92008-10-10 10:16:31 -04004435 if (peerlbl_active) {
4436 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4437 peer_sid, &ad);
4438 if (err) {
4439 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004440 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004441 }
4442 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004443
4444 if (secmark_active)
4445 if (avc_has_perm(peer_sid, skb->secmark,
4446 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4447 return NF_DROP;
4448
Paul Moore948bf852008-10-10 10:16:32 -04004449 if (netlbl_active)
4450 /* we do this in the FORWARD path and not the POST_ROUTING
4451 * path because we want to make sure we apply the necessary
4452 * labeling before IPsec is applied so we can leverage AH
4453 * protection */
4454 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4455 return NF_DROP;
4456
Paul Mooreeffad8d2008-01-29 08:49:27 -05004457 return NF_ACCEPT;
4458}
4459
4460static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4461 struct sk_buff *skb,
4462 const struct net_device *in,
4463 const struct net_device *out,
4464 int (*okfn)(struct sk_buff *))
4465{
4466 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4467}
4468
4469#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4470static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4471 struct sk_buff *skb,
4472 const struct net_device *in,
4473 const struct net_device *out,
4474 int (*okfn)(struct sk_buff *))
4475{
4476 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4477}
4478#endif /* IPV6 */
4479
Paul Moore948bf852008-10-10 10:16:32 -04004480static unsigned int selinux_ip_output(struct sk_buff *skb,
4481 u16 family)
4482{
4483 u32 sid;
4484
4485 if (!netlbl_enabled())
4486 return NF_ACCEPT;
4487
4488 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4489 * because we want to make sure we apply the necessary labeling
4490 * before IPsec is applied so we can leverage AH protection */
4491 if (skb->sk) {
4492 struct sk_security_struct *sksec = skb->sk->sk_security;
4493 sid = sksec->sid;
4494 } else
4495 sid = SECINITSID_KERNEL;
4496 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4497 return NF_DROP;
4498
4499 return NF_ACCEPT;
4500}
4501
4502static unsigned int selinux_ipv4_output(unsigned int hooknum,
4503 struct sk_buff *skb,
4504 const struct net_device *in,
4505 const struct net_device *out,
4506 int (*okfn)(struct sk_buff *))
4507{
4508 return selinux_ip_output(skb, PF_INET);
4509}
4510
Paul Mooreeffad8d2008-01-29 08:49:27 -05004511static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4512 int ifindex,
4513 struct avc_audit_data *ad,
4514 u16 family, char *addrp)
4515{
4516 int err;
4517 struct sk_security_struct *sksec = sk->sk_security;
4518 u16 sk_class;
4519 u32 netif_perm, node_perm, send_perm;
4520 u32 port_sid, node_sid, if_sid, sk_sid;
4521
4522 sk_sid = sksec->sid;
4523 sk_class = sksec->sclass;
4524
4525 switch (sk_class) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526 case SECCLASS_UDP_SOCKET:
4527 netif_perm = NETIF__UDP_SEND;
4528 node_perm = NODE__UDP_SEND;
4529 send_perm = UDP_SOCKET__SEND_MSG;
4530 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 case SECCLASS_TCP_SOCKET:
4532 netif_perm = NETIF__TCP_SEND;
4533 node_perm = NODE__TCP_SEND;
4534 send_perm = TCP_SOCKET__SEND_MSG;
4535 break;
James Morris2ee92d42006-11-13 16:09:01 -08004536 case SECCLASS_DCCP_SOCKET:
4537 netif_perm = NETIF__DCCP_SEND;
4538 node_perm = NODE__DCCP_SEND;
4539 send_perm = DCCP_SOCKET__SEND_MSG;
4540 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 default:
4542 netif_perm = NETIF__RAWIP_SEND;
4543 node_perm = NODE__RAWIP_SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004544 send_perm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 break;
4546 }
4547
Paul Mooreeffad8d2008-01-29 08:49:27 -05004548 err = sel_netif_sid(ifindex, &if_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004549 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004550 return err;
4551 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4552 return err;
Eric Paris828dfe12008-04-17 13:17:49 -04004553
Paul Moore224dfbd2008-01-29 08:38:13 -05004554 err = sel_netnode_sid(addrp, family, &node_sid);
James Morris4e5ab4c2006-06-09 00:33:33 -07004555 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004556 return err;
4557 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004558 if (err)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004559 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560
Paul Mooreeffad8d2008-01-29 08:49:27 -05004561 if (send_perm != 0)
4562 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563
Paul Moore3e112172008-04-10 10:48:14 -04004564 err = sel_netport_sid(sk->sk_protocol,
4565 ntohs(ad->u.net.dport), &port_sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004566 if (unlikely(err)) {
4567 printk(KERN_WARNING
4568 "SELinux: failure in"
4569 " selinux_ip_postroute_iptables_compat(),"
4570 " network port label not found\n");
Paul Mooreeffad8d2008-01-29 08:49:27 -05004571 return err;
Paul Moore71f1cb02008-01-29 08:51:16 -05004572 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004573 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
James Morris4e5ab4c2006-06-09 00:33:33 -07004574}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575
Paul Mooreeffad8d2008-01-29 08:49:27 -05004576static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4577 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004578 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004579{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004580 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581 struct sk_security_struct *sksec;
Paul Moored8395c82008-10-10 10:16:30 -04004582 struct avc_audit_data ad;
4583 char *addrp;
4584 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004585
Paul Mooreeffad8d2008-01-29 08:49:27 -05004586 if (sk == NULL)
4587 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004588 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004589
Paul Moored8395c82008-10-10 10:16:30 -04004590 AVC_AUDIT_DATA_INIT(&ad, NET);
4591 ad.u.net.netif = ifindex;
4592 ad.u.net.family = family;
4593 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4594 return NF_DROP;
4595
Paul Mooreeffad8d2008-01-29 08:49:27 -05004596 if (selinux_compat_net) {
4597 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004598 &ad, family, addrp))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004599 return NF_DROP;
4600 } else {
4601 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004602 SECCLASS_PACKET, PACKET__SEND, &ad))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004603 return NF_DROP;
4604 }
James Morris4e5ab4c2006-06-09 00:33:33 -07004605
Paul Mooreeffad8d2008-01-29 08:49:27 -05004606 if (selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004607 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004608 return NF_DROP;
James Morris4e5ab4c2006-06-09 00:33:33 -07004609
Paul Mooreeffad8d2008-01-29 08:49:27 -05004610 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611}
4612
Paul Mooreeffad8d2008-01-29 08:49:27 -05004613static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4614 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004616 u32 secmark_perm;
4617 u32 peer_sid;
4618 struct sock *sk;
4619 struct avc_audit_data ad;
4620 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004621 u8 secmark_active;
4622 u8 peerlbl_active;
4623
Paul Mooreeffad8d2008-01-29 08:49:27 -05004624 /* If any sort of compatibility mode is enabled then handoff processing
4625 * to the selinux_ip_postroute_compat() function to deal with the
4626 * special handling. We do this in an attempt to keep this function
4627 * as fast and as clean as possible. */
4628 if (selinux_compat_net || !selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004629 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004630
4631 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4632 * packet transformation so allow the packet to pass without any checks
4633 * since we'll have another chance to perform access control checks
4634 * when the packet is on it's final way out.
4635 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4636 * is NULL, in this case go ahead and apply access control. */
4637 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4638 return NF_ACCEPT;
4639
4640 secmark_active = selinux_secmark_enabled();
4641 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4642 if (!secmark_active && !peerlbl_active)
4643 return NF_ACCEPT;
4644
Paul Moored8395c82008-10-10 10:16:30 -04004645 /* if the packet is being forwarded then get the peer label from the
4646 * packet itself; otherwise check to see if it is from a local
4647 * application or the kernel, if from an application get the peer label
4648 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004649 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004650 if (sk == NULL) {
4651 switch (family) {
4652 case PF_INET:
4653 if (IPCB(skb)->flags & IPSKB_FORWARDED)
4654 secmark_perm = PACKET__FORWARD_OUT;
4655 else
4656 secmark_perm = PACKET__SEND;
4657 break;
4658 case PF_INET6:
4659 if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
4660 secmark_perm = PACKET__FORWARD_OUT;
4661 else
4662 secmark_perm = PACKET__SEND;
4663 break;
4664 default:
4665 return NF_DROP;
4666 }
4667 if (secmark_perm == PACKET__FORWARD_OUT) {
4668 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4669 return NF_DROP;
4670 } else
4671 peer_sid = SECINITSID_KERNEL;
4672 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004673 struct sk_security_struct *sksec = sk->sk_security;
4674 peer_sid = sksec->sid;
4675 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004676 }
4677
Paul Moored8395c82008-10-10 10:16:30 -04004678 AVC_AUDIT_DATA_INIT(&ad, NET);
4679 ad.u.net.netif = ifindex;
4680 ad.u.net.family = family;
4681 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
4682 return NF_DROP;
4683
Paul Mooreeffad8d2008-01-29 08:49:27 -05004684 if (secmark_active)
4685 if (avc_has_perm(peer_sid, skb->secmark,
4686 SECCLASS_PACKET, secmark_perm, &ad))
4687 return NF_DROP;
4688
4689 if (peerlbl_active) {
4690 u32 if_sid;
4691 u32 node_sid;
4692
4693 if (sel_netif_sid(ifindex, &if_sid))
4694 return NF_DROP;
4695 if (avc_has_perm(peer_sid, if_sid,
4696 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4697 return NF_DROP;
4698
4699 if (sel_netnode_sid(addrp, family, &node_sid))
4700 return NF_DROP;
4701 if (avc_has_perm(peer_sid, node_sid,
4702 SECCLASS_NODE, NODE__SENDTO, &ad))
4703 return NF_DROP;
4704 }
4705
4706 return NF_ACCEPT;
4707}
4708
4709static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4710 struct sk_buff *skb,
4711 const struct net_device *in,
4712 const struct net_device *out,
4713 int (*okfn)(struct sk_buff *))
4714{
4715 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716}
4717
4718#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004719static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4720 struct sk_buff *skb,
4721 const struct net_device *in,
4722 const struct net_device *out,
4723 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004725 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727#endif /* IPV6 */
4728
4729#endif /* CONFIG_NETFILTER */
4730
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4732{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 int err;
4734
4735 err = secondary_ops->netlink_send(sk, skb);
4736 if (err)
4737 return err;
4738
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
4740 err = selinux_nlmsg_perm(sk, skb);
4741
4742 return err;
4743}
4744
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004745static int selinux_netlink_recv(struct sk_buff *skb, int capability)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746{
Darrel Goeddelc7bdb542006-06-27 13:26:11 -07004747 int err;
4748 struct avc_audit_data ad;
4749
4750 err = secondary_ops->netlink_recv(skb, capability);
4751 if (err)
4752 return err;
4753
4754 AVC_AUDIT_DATA_INIT(&ad, CAP);
4755 ad.u.cap = capability;
4756
4757 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
Eric Paris828dfe12008-04-17 13:17:49 -04004758 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759}
4760
4761static int ipc_alloc_security(struct task_struct *task,
4762 struct kern_ipc_perm *perm,
4763 u16 sclass)
4764{
4765 struct task_security_struct *tsec = task->security;
4766 struct ipc_security_struct *isec;
4767
James Morris89d155e2005-10-30 14:59:21 -08004768 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769 if (!isec)
4770 return -ENOMEM;
4771
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 isec->sclass = sclass;
Stephen Smalley9ac49d22006-02-01 03:05:56 -08004773 isec->sid = tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 perm->security = isec;
4775
4776 return 0;
4777}
4778
4779static void ipc_free_security(struct kern_ipc_perm *perm)
4780{
4781 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 perm->security = NULL;
4783 kfree(isec);
4784}
4785
4786static int msg_msg_alloc_security(struct msg_msg *msg)
4787{
4788 struct msg_security_struct *msec;
4789
James Morris89d155e2005-10-30 14:59:21 -08004790 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791 if (!msec)
4792 return -ENOMEM;
4793
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 msec->sid = SECINITSID_UNLABELED;
4795 msg->security = msec;
4796
4797 return 0;
4798}
4799
4800static void msg_msg_free_security(struct msg_msg *msg)
4801{
4802 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803
4804 msg->security = NULL;
4805 kfree(msec);
4806}
4807
4808static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004809 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810{
4811 struct task_security_struct *tsec;
4812 struct ipc_security_struct *isec;
4813 struct avc_audit_data ad;
4814
4815 tsec = current->security;
4816 isec = ipc_perms->security;
4817
4818 AVC_AUDIT_DATA_INIT(&ad, IPC);
4819 ad.u.ipc_id = ipc_perms->key;
4820
Stephen Smalley6af963f2005-05-01 08:58:39 -07004821 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822}
4823
4824static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4825{
4826 return msg_msg_alloc_security(msg);
4827}
4828
4829static void selinux_msg_msg_free_security(struct msg_msg *msg)
4830{
4831 msg_msg_free_security(msg);
4832}
4833
4834/* message queue security operations */
4835static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4836{
4837 struct task_security_struct *tsec;
4838 struct ipc_security_struct *isec;
4839 struct avc_audit_data ad;
4840 int rc;
4841
4842 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4843 if (rc)
4844 return rc;
4845
4846 tsec = current->security;
4847 isec = msq->q_perm.security;
4848
4849 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004850 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
4852 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4853 MSGQ__CREATE, &ad);
4854 if (rc) {
4855 ipc_free_security(&msq->q_perm);
4856 return rc;
4857 }
4858 return 0;
4859}
4860
4861static void selinux_msg_queue_free_security(struct msg_queue *msq)
4862{
4863 ipc_free_security(&msq->q_perm);
4864}
4865
4866static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4867{
4868 struct task_security_struct *tsec;
4869 struct ipc_security_struct *isec;
4870 struct avc_audit_data ad;
4871
4872 tsec = current->security;
4873 isec = msq->q_perm.security;
4874
4875 AVC_AUDIT_DATA_INIT(&ad, IPC);
4876 ad.u.ipc_id = msq->q_perm.key;
4877
4878 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4879 MSGQ__ASSOCIATE, &ad);
4880}
4881
4882static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4883{
4884 int err;
4885 int perms;
4886
Eric Paris828dfe12008-04-17 13:17:49 -04004887 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888 case IPC_INFO:
4889 case MSG_INFO:
4890 /* No specific object, just general system-wide information. */
4891 return task_has_system(current, SYSTEM__IPC_INFO);
4892 case IPC_STAT:
4893 case MSG_STAT:
4894 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4895 break;
4896 case IPC_SET:
4897 perms = MSGQ__SETATTR;
4898 break;
4899 case IPC_RMID:
4900 perms = MSGQ__DESTROY;
4901 break;
4902 default:
4903 return 0;
4904 }
4905
Stephen Smalley6af963f2005-05-01 08:58:39 -07004906 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907 return err;
4908}
4909
4910static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4911{
4912 struct task_security_struct *tsec;
4913 struct ipc_security_struct *isec;
4914 struct msg_security_struct *msec;
4915 struct avc_audit_data ad;
4916 int rc;
4917
4918 tsec = current->security;
4919 isec = msq->q_perm.security;
4920 msec = msg->security;
4921
4922 /*
4923 * First time through, need to assign label to the message
4924 */
4925 if (msec->sid == SECINITSID_UNLABELED) {
4926 /*
4927 * Compute new sid based on current process and
4928 * message queue this message will be stored in
4929 */
4930 rc = security_transition_sid(tsec->sid,
4931 isec->sid,
4932 SECCLASS_MSG,
4933 &msec->sid);
4934 if (rc)
4935 return rc;
4936 }
4937
4938 AVC_AUDIT_DATA_INIT(&ad, IPC);
4939 ad.u.ipc_id = msq->q_perm.key;
4940
4941 /* Can this process write to the queue? */
4942 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
4943 MSGQ__WRITE, &ad);
4944 if (!rc)
4945 /* Can this process send the message */
4946 rc = avc_has_perm(tsec->sid, msec->sid,
4947 SECCLASS_MSG, MSG__SEND, &ad);
4948 if (!rc)
4949 /* Can the message be put in the queue? */
4950 rc = avc_has_perm(msec->sid, isec->sid,
4951 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
4952
4953 return rc;
4954}
4955
4956static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
4957 struct task_struct *target,
4958 long type, int mode)
4959{
4960 struct task_security_struct *tsec;
4961 struct ipc_security_struct *isec;
4962 struct msg_security_struct *msec;
4963 struct avc_audit_data ad;
4964 int rc;
4965
4966 tsec = target->security;
4967 isec = msq->q_perm.security;
4968 msec = msg->security;
4969
4970 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004971 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972
4973 rc = avc_has_perm(tsec->sid, isec->sid,
4974 SECCLASS_MSGQ, MSGQ__READ, &ad);
4975 if (!rc)
4976 rc = avc_has_perm(tsec->sid, msec->sid,
4977 SECCLASS_MSG, MSG__RECEIVE, &ad);
4978 return rc;
4979}
4980
4981/* Shared Memory security operations */
4982static int selinux_shm_alloc_security(struct shmid_kernel *shp)
4983{
4984 struct task_security_struct *tsec;
4985 struct ipc_security_struct *isec;
4986 struct avc_audit_data ad;
4987 int rc;
4988
4989 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
4990 if (rc)
4991 return rc;
4992
4993 tsec = current->security;
4994 isec = shp->shm_perm.security;
4995
4996 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04004997 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998
4999 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
5000 SHM__CREATE, &ad);
5001 if (rc) {
5002 ipc_free_security(&shp->shm_perm);
5003 return rc;
5004 }
5005 return 0;
5006}
5007
5008static void selinux_shm_free_security(struct shmid_kernel *shp)
5009{
5010 ipc_free_security(&shp->shm_perm);
5011}
5012
5013static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5014{
5015 struct task_security_struct *tsec;
5016 struct ipc_security_struct *isec;
5017 struct avc_audit_data ad;
5018
5019 tsec = current->security;
5020 isec = shp->shm_perm.security;
5021
5022 AVC_AUDIT_DATA_INIT(&ad, IPC);
5023 ad.u.ipc_id = shp->shm_perm.key;
5024
5025 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
5026 SHM__ASSOCIATE, &ad);
5027}
5028
5029/* Note, at this point, shp is locked down */
5030static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5031{
5032 int perms;
5033 int err;
5034
Eric Paris828dfe12008-04-17 13:17:49 -04005035 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036 case IPC_INFO:
5037 case SHM_INFO:
5038 /* No specific object, just general system-wide information. */
5039 return task_has_system(current, SYSTEM__IPC_INFO);
5040 case IPC_STAT:
5041 case SHM_STAT:
5042 perms = SHM__GETATTR | SHM__ASSOCIATE;
5043 break;
5044 case IPC_SET:
5045 perms = SHM__SETATTR;
5046 break;
5047 case SHM_LOCK:
5048 case SHM_UNLOCK:
5049 perms = SHM__LOCK;
5050 break;
5051 case IPC_RMID:
5052 perms = SHM__DESTROY;
5053 break;
5054 default:
5055 return 0;
5056 }
5057
Stephen Smalley6af963f2005-05-01 08:58:39 -07005058 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059 return err;
5060}
5061
5062static int selinux_shm_shmat(struct shmid_kernel *shp,
5063 char __user *shmaddr, int shmflg)
5064{
5065 u32 perms;
5066 int rc;
5067
5068 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
5069 if (rc)
5070 return rc;
5071
5072 if (shmflg & SHM_RDONLY)
5073 perms = SHM__READ;
5074 else
5075 perms = SHM__READ | SHM__WRITE;
5076
Stephen Smalley6af963f2005-05-01 08:58:39 -07005077 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078}
5079
5080/* Semaphore security operations */
5081static int selinux_sem_alloc_security(struct sem_array *sma)
5082{
5083 struct task_security_struct *tsec;
5084 struct ipc_security_struct *isec;
5085 struct avc_audit_data ad;
5086 int rc;
5087
5088 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5089 if (rc)
5090 return rc;
5091
5092 tsec = current->security;
5093 isec = sma->sem_perm.security;
5094
5095 AVC_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris828dfe12008-04-17 13:17:49 -04005096 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097
5098 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
5099 SEM__CREATE, &ad);
5100 if (rc) {
5101 ipc_free_security(&sma->sem_perm);
5102 return rc;
5103 }
5104 return 0;
5105}
5106
5107static void selinux_sem_free_security(struct sem_array *sma)
5108{
5109 ipc_free_security(&sma->sem_perm);
5110}
5111
5112static int selinux_sem_associate(struct sem_array *sma, int semflg)
5113{
5114 struct task_security_struct *tsec;
5115 struct ipc_security_struct *isec;
5116 struct avc_audit_data ad;
5117
5118 tsec = current->security;
5119 isec = sma->sem_perm.security;
5120
5121 AVC_AUDIT_DATA_INIT(&ad, IPC);
5122 ad.u.ipc_id = sma->sem_perm.key;
5123
5124 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
5125 SEM__ASSOCIATE, &ad);
5126}
5127
5128/* Note, at this point, sma is locked down */
5129static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5130{
5131 int err;
5132 u32 perms;
5133
Eric Paris828dfe12008-04-17 13:17:49 -04005134 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135 case IPC_INFO:
5136 case SEM_INFO:
5137 /* No specific object, just general system-wide information. */
5138 return task_has_system(current, SYSTEM__IPC_INFO);
5139 case GETPID:
5140 case GETNCNT:
5141 case GETZCNT:
5142 perms = SEM__GETATTR;
5143 break;
5144 case GETVAL:
5145 case GETALL:
5146 perms = SEM__READ;
5147 break;
5148 case SETVAL:
5149 case SETALL:
5150 perms = SEM__WRITE;
5151 break;
5152 case IPC_RMID:
5153 perms = SEM__DESTROY;
5154 break;
5155 case IPC_SET:
5156 perms = SEM__SETATTR;
5157 break;
5158 case IPC_STAT:
5159 case SEM_STAT:
5160 perms = SEM__GETATTR | SEM__ASSOCIATE;
5161 break;
5162 default:
5163 return 0;
5164 }
5165
Stephen Smalley6af963f2005-05-01 08:58:39 -07005166 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167 return err;
5168}
5169
5170static int selinux_sem_semop(struct sem_array *sma,
5171 struct sembuf *sops, unsigned nsops, int alter)
5172{
5173 u32 perms;
5174
5175 if (alter)
5176 perms = SEM__READ | SEM__WRITE;
5177 else
5178 perms = SEM__READ;
5179
Stephen Smalley6af963f2005-05-01 08:58:39 -07005180 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181}
5182
5183static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5184{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185 u32 av = 0;
5186
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187 av = 0;
5188 if (flag & S_IRUGO)
5189 av |= IPC__UNIX_READ;
5190 if (flag & S_IWUGO)
5191 av |= IPC__UNIX_WRITE;
5192
5193 if (av == 0)
5194 return 0;
5195
Stephen Smalley6af963f2005-05-01 08:58:39 -07005196 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197}
5198
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005199static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5200{
5201 struct ipc_security_struct *isec = ipcp->security;
5202 *secid = isec->sid;
5203}
5204
Eric Paris828dfe12008-04-17 13:17:49 -04005205static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206{
5207 if (inode)
5208 inode_doinit_with_dentry(inode, dentry);
5209}
5210
5211static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005212 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213{
5214 struct task_security_struct *tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005215 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005217 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218
5219 if (current != p) {
5220 error = task_has_perm(current, p, PROCESS__GETATTR);
5221 if (error)
5222 return error;
5223 }
5224
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 tsec = p->security;
5226
5227 if (!strcmp(name, "current"))
5228 sid = tsec->sid;
5229 else if (!strcmp(name, "prev"))
5230 sid = tsec->osid;
5231 else if (!strcmp(name, "exec"))
5232 sid = tsec->exec_sid;
5233 else if (!strcmp(name, "fscreate"))
5234 sid = tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005235 else if (!strcmp(name, "keycreate"))
5236 sid = tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005237 else if (!strcmp(name, "sockcreate"))
5238 sid = tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 else
5240 return -EINVAL;
5241
5242 if (!sid)
5243 return 0;
5244
Al Viro04ff9702007-03-12 16:17:58 +00005245 error = security_sid_to_context(sid, value, &len);
5246 if (error)
5247 return error;
5248 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249}
5250
5251static int selinux_setprocattr(struct task_struct *p,
5252 char *name, void *value, size_t size)
5253{
5254 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005255 struct task_struct *tracer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 u32 sid = 0;
5257 int error;
5258 char *str = value;
5259
5260 if (current != p) {
5261 /* SELinux only allows a process to change its own
5262 security attributes. */
5263 return -EACCES;
5264 }
5265
5266 /*
5267 * Basic control over ability to set these attributes at all.
5268 * current == p, but we'll pass them separately in case the
5269 * above restriction is ever removed.
5270 */
5271 if (!strcmp(name, "exec"))
5272 error = task_has_perm(current, p, PROCESS__SETEXEC);
5273 else if (!strcmp(name, "fscreate"))
5274 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005275 else if (!strcmp(name, "keycreate"))
5276 error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005277 else if (!strcmp(name, "sockcreate"))
5278 error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 else if (!strcmp(name, "current"))
5280 error = task_has_perm(current, p, PROCESS__SETCURRENT);
5281 else
5282 error = -EINVAL;
5283 if (error)
5284 return error;
5285
5286 /* Obtain a SID for the context, if one was specified. */
5287 if (size && str[1] && str[1] != '\n') {
5288 if (str[size-1] == '\n') {
5289 str[size-1] = 0;
5290 size--;
5291 }
5292 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005293 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5294 if (!capable(CAP_MAC_ADMIN))
5295 return error;
5296 error = security_context_to_sid_force(value, size,
5297 &sid);
5298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299 if (error)
5300 return error;
5301 }
5302
5303 /* Permission checking based on the specified context is
5304 performed during the actual operation (execve,
5305 open/mkdir/...), when we know the full context of the
5306 operation. See selinux_bprm_set_security for the execve
5307 checks and may_create for the file creation checks. The
5308 operation will then fail if the context is not permitted. */
5309 tsec = p->security;
5310 if (!strcmp(name, "exec"))
5311 tsec->exec_sid = sid;
5312 else if (!strcmp(name, "fscreate"))
5313 tsec->create_sid = sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005314 else if (!strcmp(name, "keycreate")) {
5315 error = may_create_key(sid, p);
5316 if (error)
5317 return error;
5318 tsec->keycreate_sid = sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005319 } else if (!strcmp(name, "sockcreate"))
5320 tsec->sockcreate_sid = sid;
5321 else if (!strcmp(name, "current")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322 struct av_decision avd;
5323
5324 if (sid == 0)
5325 return -EINVAL;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005326 /*
5327 * SELinux allows to change context in the following case only.
5328 * - Single threaded processes.
5329 * - Multi threaded processes intend to change its context into
5330 * more restricted domain (defined by TYPEBOUNDS statement).
5331 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 if (atomic_read(&p->mm->mm_users) != 1) {
5333 struct task_struct *g, *t;
5334 struct mm_struct *mm = p->mm;
5335 read_lock(&tasklist_lock);
James Morris2baf06d2008-06-12 01:42:35 +10005336 do_each_thread(g, t) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005337 if (t->mm == mm && t != p) {
5338 read_unlock(&tasklist_lock);
KaiGai Koheid9250de2008-08-28 16:35:57 +09005339 error = security_bounded_transition(tsec->sid, sid);
5340 if (!error)
5341 goto boundary_ok;
5342
5343 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005344 }
James Morris2baf06d2008-06-12 01:42:35 +10005345 } while_each_thread(g, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346 read_unlock(&tasklist_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04005347 }
KaiGai Koheid9250de2008-08-28 16:35:57 +09005348boundary_ok:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
5350 /* Check permissions for the transition. */
5351 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005352 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353 if (error)
5354 return error;
5355
5356 /* Check for ptracing, and update the task SID if ok.
5357 Otherwise, leave SID unchanged and fail. */
5358 task_lock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005359 rcu_read_lock();
Roland McGrath0d094ef2008-07-25 19:45:49 -07005360 tracer = tracehook_tracer_task(p);
Roland McGrath03563572008-03-26 15:46:39 -07005361 if (tracer != NULL) {
5362 struct task_security_struct *ptsec = tracer->security;
5363 u32 ptsid = ptsec->sid;
5364 rcu_read_unlock();
5365 error = avc_has_perm_noaudit(ptsid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366 SECCLASS_PROCESS,
Stephen Smalley2c3c05d2007-06-07 15:34:10 -04005367 PROCESS__PTRACE, 0, &avd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368 if (!error)
5369 tsec->sid = sid;
5370 task_unlock(p);
Roland McGrath03563572008-03-26 15:46:39 -07005371 avc_audit(ptsid, sid, SECCLASS_PROCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372 PROCESS__PTRACE, &avd, error, NULL);
5373 if (error)
5374 return error;
5375 } else {
Roland McGrath03563572008-03-26 15:46:39 -07005376 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377 tsec->sid = sid;
5378 task_unlock(p);
5379 }
Eric Paris828dfe12008-04-17 13:17:49 -04005380 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 return -EINVAL;
5382
5383 return size;
5384}
5385
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005386static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5387{
5388 return security_sid_to_context(secid, secdata, seclen);
5389}
5390
David Howells7bf570d2008-04-29 20:52:51 +01005391static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005392{
5393 return security_context_to_sid(secdata, seclen, secid);
5394}
5395
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005396static void selinux_release_secctx(char *secdata, u32 seclen)
5397{
Paul Moore088999e2007-08-01 11:12:58 -04005398 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005399}
5400
Michael LeMayd7200242006-06-22 14:47:17 -07005401#ifdef CONFIG_KEYS
5402
David Howells7e047ef2006-06-26 00:24:50 -07005403static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
5404 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005405{
5406 struct task_security_struct *tsec = tsk->security;
5407 struct key_security_struct *ksec;
5408
5409 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5410 if (!ksec)
5411 return -ENOMEM;
5412
Michael LeMay4eb582c2006-06-26 00:24:57 -07005413 if (tsec->keycreate_sid)
5414 ksec->sid = tsec->keycreate_sid;
5415 else
5416 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005417 k->security = ksec;
5418
5419 return 0;
5420}
5421
5422static void selinux_key_free(struct key *k)
5423{
5424 struct key_security_struct *ksec = k->security;
5425
5426 k->security = NULL;
5427 kfree(ksec);
5428}
5429
5430static int selinux_key_permission(key_ref_t key_ref,
5431 struct task_struct *ctx,
5432 key_perm_t perm)
5433{
5434 struct key *key;
5435 struct task_security_struct *tsec;
5436 struct key_security_struct *ksec;
5437
5438 key = key_ref_to_ptr(key_ref);
5439
5440 tsec = ctx->security;
5441 ksec = key->security;
5442
5443 /* if no specific permissions are requested, we skip the
5444 permission check. No serious, additional covert channels
5445 appear to be created. */
5446 if (perm == 0)
5447 return 0;
5448
5449 return avc_has_perm(tsec->sid, ksec->sid,
5450 SECCLASS_KEY, perm, NULL);
5451}
5452
David Howells70a5bb72008-04-29 01:01:26 -07005453static int selinux_key_getsecurity(struct key *key, char **_buffer)
5454{
5455 struct key_security_struct *ksec = key->security;
5456 char *context = NULL;
5457 unsigned len;
5458 int rc;
5459
5460 rc = security_sid_to_context(ksec->sid, &context, &len);
5461 if (!rc)
5462 rc = len;
5463 *_buffer = context;
5464 return rc;
5465}
5466
Michael LeMayd7200242006-06-22 14:47:17 -07005467#endif
5468
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005470 .name = "selinux",
5471
David Howells5cd9c582008-08-14 11:37:28 +01005472 .ptrace_may_access = selinux_ptrace_may_access,
5473 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474 .capget = selinux_capget,
5475 .capset_check = selinux_capset_check,
5476 .capset_set = selinux_capset_set,
5477 .sysctl = selinux_sysctl,
5478 .capable = selinux_capable,
5479 .quotactl = selinux_quotactl,
5480 .quota_on = selinux_quota_on,
5481 .syslog = selinux_syslog,
5482 .vm_enough_memory = selinux_vm_enough_memory,
5483
5484 .netlink_send = selinux_netlink_send,
Eric Paris828dfe12008-04-17 13:17:49 -04005485 .netlink_recv = selinux_netlink_recv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486
5487 .bprm_alloc_security = selinux_bprm_alloc_security,
5488 .bprm_free_security = selinux_bprm_free_security,
5489 .bprm_apply_creds = selinux_bprm_apply_creds,
5490 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5491 .bprm_set_security = selinux_bprm_set_security,
5492 .bprm_check_security = selinux_bprm_check_security,
5493 .bprm_secureexec = selinux_bprm_secureexec,
5494
5495 .sb_alloc_security = selinux_sb_alloc_security,
5496 .sb_free_security = selinux_sb_free_security,
5497 .sb_copy_data = selinux_sb_copy_data,
Eric Paris828dfe12008-04-17 13:17:49 -04005498 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005499 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500 .sb_statfs = selinux_sb_statfs,
5501 .sb_mount = selinux_mount,
5502 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005503 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005504 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005505 .sb_parse_opts_str = selinux_parse_opts_str,
5506
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507
5508 .inode_alloc_security = selinux_inode_alloc_security,
5509 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005510 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513 .inode_unlink = selinux_inode_unlink,
5514 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 .inode_rmdir = selinux_inode_rmdir,
5517 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 .inode_readlink = selinux_inode_readlink,
5520 .inode_follow_link = selinux_inode_follow_link,
5521 .inode_permission = selinux_inode_permission,
5522 .inode_setattr = selinux_inode_setattr,
5523 .inode_getattr = selinux_inode_getattr,
5524 .inode_setxattr = selinux_inode_setxattr,
5525 .inode_post_setxattr = selinux_inode_post_setxattr,
5526 .inode_getxattr = selinux_inode_getxattr,
5527 .inode_listxattr = selinux_inode_listxattr,
5528 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005529 .inode_getsecurity = selinux_inode_getsecurity,
5530 .inode_setsecurity = selinux_inode_setsecurity,
5531 .inode_listsecurity = selinux_inode_listsecurity,
Serge E. Hallynb5376772007-10-16 23:31:36 -07005532 .inode_need_killpriv = selinux_inode_need_killpriv,
5533 .inode_killpriv = selinux_inode_killpriv,
Eric Parisf5269712008-05-14 11:27:45 -04005534 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535
5536 .file_permission = selinux_file_permission,
5537 .file_alloc_security = selinux_file_alloc_security,
5538 .file_free_security = selinux_file_free_security,
5539 .file_ioctl = selinux_file_ioctl,
5540 .file_mmap = selinux_file_mmap,
5541 .file_mprotect = selinux_file_mprotect,
5542 .file_lock = selinux_file_lock,
5543 .file_fcntl = selinux_file_fcntl,
5544 .file_set_fowner = selinux_file_set_fowner,
5545 .file_send_sigiotask = selinux_file_send_sigiotask,
5546 .file_receive = selinux_file_receive,
5547
Eric Paris828dfe12008-04-17 13:17:49 -04005548 .dentry_open = selinux_dentry_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005549
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550 .task_create = selinux_task_create,
5551 .task_alloc_security = selinux_task_alloc_security,
5552 .task_free_security = selinux_task_free_security,
5553 .task_setuid = selinux_task_setuid,
5554 .task_post_setuid = selinux_task_post_setuid,
5555 .task_setgid = selinux_task_setgid,
5556 .task_setpgid = selinux_task_setpgid,
5557 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005558 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005559 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 .task_setgroups = selinux_task_setgroups,
5561 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005562 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005563 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564 .task_setrlimit = selinux_task_setrlimit,
5565 .task_setscheduler = selinux_task_setscheduler,
5566 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005567 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 .task_kill = selinux_task_kill,
5569 .task_wait = selinux_task_wait,
5570 .task_prctl = selinux_task_prctl,
5571 .task_reparent_to_init = selinux_task_reparent_to_init,
Eric Paris828dfe12008-04-17 13:17:49 -04005572 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
5574 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005575 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
5577 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5578 .msg_msg_free_security = selinux_msg_msg_free_security,
5579
5580 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5581 .msg_queue_free_security = selinux_msg_queue_free_security,
5582 .msg_queue_associate = selinux_msg_queue_associate,
5583 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5584 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5585 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5586
5587 .shm_alloc_security = selinux_shm_alloc_security,
5588 .shm_free_security = selinux_shm_free_security,
5589 .shm_associate = selinux_shm_associate,
5590 .shm_shmctl = selinux_shm_shmctl,
5591 .shm_shmat = selinux_shm_shmat,
5592
Eric Paris828dfe12008-04-17 13:17:49 -04005593 .sem_alloc_security = selinux_sem_alloc_security,
5594 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595 .sem_associate = selinux_sem_associate,
5596 .sem_semctl = selinux_sem_semctl,
5597 .sem_semop = selinux_sem_semop,
5598
Eric Paris828dfe12008-04-17 13:17:49 -04005599 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600
Eric Paris828dfe12008-04-17 13:17:49 -04005601 .getprocattr = selinux_getprocattr,
5602 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005604 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005605 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005606 .release_secctx = selinux_release_secctx,
5607
Eric Paris828dfe12008-04-17 13:17:49 -04005608 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 .unix_may_send = selinux_socket_unix_may_send,
5610
5611 .socket_create = selinux_socket_create,
5612 .socket_post_create = selinux_socket_post_create,
5613 .socket_bind = selinux_socket_bind,
5614 .socket_connect = selinux_socket_connect,
5615 .socket_listen = selinux_socket_listen,
5616 .socket_accept = selinux_socket_accept,
5617 .socket_sendmsg = selinux_socket_sendmsg,
5618 .socket_recvmsg = selinux_socket_recvmsg,
5619 .socket_getsockname = selinux_socket_getsockname,
5620 .socket_getpeername = selinux_socket_getpeername,
5621 .socket_getsockopt = selinux_socket_getsockopt,
5622 .socket_setsockopt = selinux_socket_setsockopt,
5623 .socket_shutdown = selinux_socket_shutdown,
5624 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005625 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5626 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627 .sk_alloc_security = selinux_sk_alloc_security,
5628 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005629 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005630 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005631 .sock_graft = selinux_sock_graft,
5632 .inet_conn_request = selinux_inet_conn_request,
5633 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005634 .inet_conn_established = selinux_inet_conn_established,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005635 .req_classify_flow = selinux_req_classify_flow,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005636
5637#ifdef CONFIG_SECURITY_NETWORK_XFRM
5638 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5639 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5640 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005641 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005642 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5643 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005644 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005645 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005646 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005647 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005649
5650#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005651 .key_alloc = selinux_key_alloc,
5652 .key_free = selinux_key_free,
5653 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005654 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005655#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005656
5657#ifdef CONFIG_AUDIT
5658 .audit_rule_init = selinux_audit_rule_init,
5659 .audit_rule_known = selinux_audit_rule_known,
5660 .audit_rule_match = selinux_audit_rule_match,
5661 .audit_rule_free = selinux_audit_rule_free,
5662#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663};
5664
5665static __init int selinux_init(void)
5666{
5667 struct task_security_struct *tsec;
5668
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005669 if (!security_module_enable(&selinux_ops)) {
5670 selinux_enabled = 0;
5671 return 0;
5672 }
5673
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 if (!selinux_enabled) {
5675 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5676 return 0;
5677 }
5678
5679 printk(KERN_INFO "SELinux: Initializing.\n");
5680
5681 /* Set the security state for the initial task. */
5682 if (task_alloc_security(current))
5683 panic("SELinux: Failed to initialize initial task.\n");
5684 tsec = current->security;
5685 tsec->osid = tsec->sid = SECINITSID_KERNEL;
5686
James Morris7cae7e22006-03-22 00:09:22 -08005687 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5688 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005689 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690 avc_init();
5691
James Morris6f0f0fd2008-07-10 17:02:07 +09005692 secondary_ops = security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693 if (!secondary_ops)
Eric Paris828dfe12008-04-17 13:17:49 -04005694 panic("SELinux: No initial security operations\n");
5695 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696 panic("SELinux: Unable to register with kernel.\n");
5697
Eric Paris828dfe12008-04-17 13:17:49 -04005698 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005699 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005700 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005701 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005702
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703 return 0;
5704}
5705
5706void selinux_complete_init(void)
5707{
Eric Parisfadcdb42007-02-22 18:11:31 -05005708 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709
5710 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005711 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005712 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713 spin_lock(&sb_security_lock);
5714next_sb:
5715 if (!list_empty(&superblock_security_head)) {
5716 struct superblock_security_struct *sbsec =
5717 list_entry(superblock_security_head.next,
Eric Paris828dfe12008-04-17 13:17:49 -04005718 struct superblock_security_struct,
5719 list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720 struct super_block *sb = sbsec->sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721 sb->s_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005722 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005723 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724 down_read(&sb->s_umount);
5725 if (sb->s_root)
5726 superblock_doinit(sb, NULL);
5727 drop_super(sb);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005728 spin_lock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 spin_lock(&sb_security_lock);
5730 list_del_init(&sbsec->list);
5731 goto next_sb;
5732 }
5733 spin_unlock(&sb_security_lock);
Stephen Smalleyba0c19e2006-06-04 02:51:30 -07005734 spin_unlock(&sb_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005735}
5736
5737/* SELinux requires early initialization in order to label
5738 all processes and objects when they are created. */
5739security_initcall(selinux_init);
5740
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005741#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742
Paul Mooreeffad8d2008-01-29 08:49:27 -05005743static struct nf_hook_ops selinux_ipv4_ops[] = {
5744 {
5745 .hook = selinux_ipv4_postroute,
5746 .owner = THIS_MODULE,
5747 .pf = PF_INET,
5748 .hooknum = NF_INET_POST_ROUTING,
5749 .priority = NF_IP_PRI_SELINUX_LAST,
5750 },
5751 {
5752 .hook = selinux_ipv4_forward,
5753 .owner = THIS_MODULE,
5754 .pf = PF_INET,
5755 .hooknum = NF_INET_FORWARD,
5756 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005757 },
5758 {
5759 .hook = selinux_ipv4_output,
5760 .owner = THIS_MODULE,
5761 .pf = PF_INET,
5762 .hooknum = NF_INET_LOCAL_OUT,
5763 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765};
5766
5767#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5768
Paul Mooreeffad8d2008-01-29 08:49:27 -05005769static struct nf_hook_ops selinux_ipv6_ops[] = {
5770 {
5771 .hook = selinux_ipv6_postroute,
5772 .owner = THIS_MODULE,
5773 .pf = PF_INET6,
5774 .hooknum = NF_INET_POST_ROUTING,
5775 .priority = NF_IP6_PRI_SELINUX_LAST,
5776 },
5777 {
5778 .hook = selinux_ipv6_forward,
5779 .owner = THIS_MODULE,
5780 .pf = PF_INET6,
5781 .hooknum = NF_INET_FORWARD,
5782 .priority = NF_IP6_PRI_SELINUX_FIRST,
5783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784};
5785
5786#endif /* IPV6 */
5787
5788static int __init selinux_nf_ip_init(void)
5789{
5790 int err = 0;
5791
5792 if (!selinux_enabled)
5793 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005794
5795 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5796
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005797 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5798 if (err)
5799 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800
5801#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005802 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5803 if (err)
5804 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005806
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807out:
5808 return err;
5809}
5810
5811__initcall(selinux_nf_ip_init);
5812
5813#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5814static void selinux_nf_ip_exit(void)
5815{
Eric Parisfadcdb42007-02-22 18:11:31 -05005816 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005818 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005820 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821#endif /* IPV6 */
5822}
5823#endif
5824
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005825#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826
5827#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5828#define selinux_nf_ip_exit()
5829#endif
5830
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005831#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832
5833#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005834static int selinux_disabled;
5835
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836int selinux_disable(void)
5837{
5838 extern void exit_sel_fs(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005839
5840 if (ss_initialized) {
5841 /* Not permitted after initial policy load. */
5842 return -EINVAL;
5843 }
5844
5845 if (selinux_disabled) {
5846 /* Only do this once. */
5847 return -EINVAL;
5848 }
5849
5850 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5851
5852 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005853 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
5855 /* Reset security_ops to the secondary module, dummy or capability. */
5856 security_ops = secondary_ops;
5857
5858 /* Unregister netfilter hooks. */
5859 selinux_nf_ip_exit();
5860
5861 /* Unregister selinuxfs. */
5862 exit_sel_fs();
5863
5864 return 0;
5865}
5866#endif