blob: e13d65a62104a8a3487dc472fd8fe9d53f4db1b7 [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 Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.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>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/security.h>
33#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Eric Dumazetca10b9e2013-04-08 17:58:11 +000054#include <net/sock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
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 */
James Morris56a4ca92011-08-17 11:08:43 +1000100static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500101
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
Christoph Lametere18b8902006-12-06 20:33:20 -0800130static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800131
Paul Moored621d352008-01-29 08:43:36 -0500132/**
133 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
134 *
135 * Description:
136 * This function checks the SECMARK reference counter to see if any SECMARK
137 * targets are currently configured, if the reference counter is greater than
138 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
139 * enabled, false (0) if SECMARK is disabled.
140 *
141 */
142static int selinux_secmark_enabled(void)
143{
144 return (atomic_read(&selinux_secmark_refcount) > 0);
145}
146
David Howellsd84f4f92008-11-14 10:39:23 +1100147/*
148 * initialise the security for the init task
149 */
150static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151{
David Howells3b11a1d2008-11-14 10:39:26 +1100152 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 struct task_security_struct *tsec;
154
James Morris89d155e2005-10-30 14:59:21 -0800155 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100157 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
David Howellsd84f4f92008-11-14 10:39:23 +1100159 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100160 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
David Howells275bb412008-11-14 10:39:19 +1100163/*
David Howells88e67f32008-11-14 10:39:21 +1100164 * get the security ID of a set of credentials
165 */
166static inline u32 cred_sid(const struct cred *cred)
167{
168 const struct task_security_struct *tsec;
169
170 tsec = cred->security;
171 return tsec->sid;
172}
173
174/*
David Howells3b11a1d2008-11-14 10:39:26 +1100175 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100176 */
177static inline u32 task_sid(const struct task_struct *task)
178{
David Howells275bb412008-11-14 10:39:19 +1100179 u32 sid;
180
181 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100182 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100183 rcu_read_unlock();
184 return sid;
185}
186
187/*
David Howells3b11a1d2008-11-14 10:39:26 +1100188 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100189 */
190static inline u32 current_sid(void)
191{
Paul Moore5fb49872010-04-22 14:46:19 -0400192 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100193
194 return tsec->sid;
195}
196
David Howells88e67f32008-11-14 10:39:21 +1100197/* Allocate and free functions for each kind of security blob. */
198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199static int inode_alloc_security(struct inode *inode)
200{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100202 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Josef Bacika02fe132008-04-04 09:35:05 +1100204 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 if (!isec)
206 return -ENOMEM;
207
Eric Paris23970742006-09-25 23:32:01 -0700208 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 isec->inode = inode;
211 isec->sid = SECINITSID_UNLABELED;
212 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100213 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 inode->i_security = isec;
215
216 return 0;
217}
218
219static void inode_free_security(struct inode *inode)
220{
221 struct inode_security_struct *isec = inode->i_security;
222 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 spin_lock(&sbsec->isec_lock);
225 if (!list_empty(&isec->list))
226 list_del_init(&isec->list);
227 spin_unlock(&sbsec->isec_lock);
228
229 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800230 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231}
232
233static int file_alloc_security(struct file *file)
234{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100236 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800238 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 if (!fsec)
240 return -ENOMEM;
241
David Howells275bb412008-11-14 10:39:19 +1100242 fsec->sid = sid;
243 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 file->f_security = fsec;
245
246 return 0;
247}
248
249static void file_free_security(struct file *file)
250{
251 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 file->f_security = NULL;
253 kfree(fsec);
254}
255
256static int superblock_alloc_security(struct super_block *sb)
257{
258 struct superblock_security_struct *sbsec;
259
James Morris89d155e2005-10-30 14:59:21 -0800260 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 if (!sbsec)
262 return -ENOMEM;
263
Eric Parisbc7e9822006-09-25 23:32:02 -0700264 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 INIT_LIST_HEAD(&sbsec->isec_head);
266 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 sbsec->sb = sb;
268 sbsec->sid = SECINITSID_UNLABELED;
269 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700270 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 sb->s_security = sbsec;
272
273 return 0;
274}
275
276static void superblock_free_security(struct super_block *sb)
277{
278 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 sb->s_security = NULL;
280 kfree(sbsec);
281}
282
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283/* The file system's label must be initialized prior to use. */
284
Stephen Hemminger634a5392010-03-04 21:59:03 -0800285static const char *labeling_behaviors[6] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 "uses xattr",
287 "uses transition SIDs",
288 "uses task SIDs",
289 "uses genfs_contexts",
290 "not configured for labeling",
291 "uses mountpoint labeling",
292};
293
294static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
295
296static inline int inode_doinit(struct inode *inode)
297{
298 return inode_doinit_with_dentry(inode, NULL);
299}
300
301enum {
Eric Paris31e87932007-09-19 17:19:12 -0400302 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 Opt_context = 1,
304 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500305 Opt_defcontext = 3,
306 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500307 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400308 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309};
310
Eric Parisd355987f2012-08-24 15:58:53 -0400311#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
312
Steven Whitehousea447c092008-10-13 10:46:57 +0100313static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400314 {Opt_context, CONTEXT_STR "%s"},
315 {Opt_fscontext, FSCONTEXT_STR "%s"},
316 {Opt_defcontext, DEFCONTEXT_STR "%s"},
317 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500318 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400319 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320};
321
322#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
323
Eric Parisc312feb2006-07-10 04:43:53 -0700324static int may_context_mount_sb_relabel(u32 sid,
325 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100326 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700327{
David Howells275bb412008-11-14 10:39:19 +1100328 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700329 int rc;
330
331 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
332 FILESYSTEM__RELABELFROM, NULL);
333 if (rc)
334 return rc;
335
336 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
337 FILESYSTEM__RELABELTO, NULL);
338 return rc;
339}
340
Eric Paris08089252006-07-10 04:43:55 -0700341static int may_context_mount_inode_relabel(u32 sid,
342 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100343 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700344{
David Howells275bb412008-11-14 10:39:19 +1100345 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700346 int rc;
347 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
348 FILESYSTEM__RELABELFROM, NULL);
349 if (rc)
350 return rc;
351
352 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
353 FILESYSTEM__ASSOCIATE, NULL);
354 return rc;
355}
356
Eric Parisc9180a52007-11-30 13:00:35 -0500357static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
359 struct superblock_security_struct *sbsec = sb->s_security;
360 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500361 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 int rc = 0;
363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
365 /* Make sure that the xattr handler exists and that no
366 error other than -ENODATA is returned by getxattr on
367 the root directory. -ENODATA is ok, as this may be
368 the first boot of the SELinux kernel before we have
369 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500370 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
372 "xattr support\n", sb->s_id, sb->s_type->name);
373 rc = -EOPNOTSUPP;
374 goto out;
375 }
Eric Parisc9180a52007-11-30 13:00:35 -0500376 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (rc < 0 && rc != -ENODATA) {
378 if (rc == -EOPNOTSUPP)
379 printk(KERN_WARNING "SELinux: (dev %s, type "
380 "%s) has no security xattr handler\n",
381 sb->s_id, sb->s_type->name);
382 else
383 printk(KERN_WARNING "SELinux: (dev %s, type "
384 "%s) getxattr errno %d\n", sb->s_id,
385 sb->s_type->name, -rc);
386 goto out;
387 }
388 }
389
David P. Quigley11689d42009-01-16 09:22:03 -0500390 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Eric Parisc9180a52007-11-30 13:00:35 -0500392 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500393 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500395 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500396 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 sb->s_id, sb->s_type->name,
398 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
David P. Quigley11689d42009-01-16 09:22:03 -0500400 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
401 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
402 sbsec->behavior == SECURITY_FS_USE_NONE ||
403 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
404 sbsec->flags &= ~SE_SBLABELSUPP;
405
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400406 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
407 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
408 sbsec->flags |= SE_SBLABELSUPP;
409
Stephen Smalley5c73fce2013-07-23 17:38:41 -0400410 /*
411 * Special handling for rootfs. Is genfs but supports
412 * setting SELinux context on in-core inodes.
413 */
414 if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
415 sbsec->flags |= SE_SBLABELSUPP;
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500418 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 /* Initialize any other inodes associated with the superblock, e.g.
421 inodes created prior to initial policy load or inodes created
422 during get_sb by a pseudo filesystem that directly
423 populates itself. */
424 spin_lock(&sbsec->isec_lock);
425next_inode:
426 if (!list_empty(&sbsec->isec_head)) {
427 struct inode_security_struct *isec =
428 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500429 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 struct inode *inode = isec->inode;
431 spin_unlock(&sbsec->isec_lock);
432 inode = igrab(inode);
433 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500434 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 inode_doinit(inode);
436 iput(inode);
437 }
438 spin_lock(&sbsec->isec_lock);
439 list_del_init(&isec->list);
440 goto next_inode;
441 }
442 spin_unlock(&sbsec->isec_lock);
443out:
Eric Parisc9180a52007-11-30 13:00:35 -0500444 return rc;
445}
446
447/*
448 * This function should allow an FS to ask what it's mount security
449 * options were so it can use those later for submounts, displaying
450 * mount options, or whatever.
451 */
452static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500453 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500454{
455 int rc = 0, i;
456 struct superblock_security_struct *sbsec = sb->s_security;
457 char *context = NULL;
458 u32 len;
459 char tmp;
460
Eric Parise0007522008-03-05 10:31:54 -0500461 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500462
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500463 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500464 return -EINVAL;
465
466 if (!ss_initialized)
467 return -EINVAL;
468
Eric Parisaf8e50c2012-08-24 15:59:00 -0400469 /* make sure we always check enough bits to cover the mask */
470 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
471
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500472 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500473 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400474 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500475 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500476 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500477 tmp >>= 1;
478 }
David P. Quigley11689d42009-01-16 09:22:03 -0500479 /* Check if the Label support flag is set */
480 if (sbsec->flags & SE_SBLABELSUPP)
481 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500482
Eric Parise0007522008-03-05 10:31:54 -0500483 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
484 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500485 rc = -ENOMEM;
486 goto out_free;
487 }
488
Eric Parise0007522008-03-05 10:31:54 -0500489 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
490 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500491 rc = -ENOMEM;
492 goto out_free;
493 }
494
495 i = 0;
496 if (sbsec->flags & FSCONTEXT_MNT) {
497 rc = security_sid_to_context(sbsec->sid, &context, &len);
498 if (rc)
499 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500500 opts->mnt_opts[i] = context;
501 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500502 }
503 if (sbsec->flags & CONTEXT_MNT) {
504 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
505 if (rc)
506 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500507 opts->mnt_opts[i] = context;
508 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500509 }
510 if (sbsec->flags & DEFCONTEXT_MNT) {
511 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
512 if (rc)
513 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500514 opts->mnt_opts[i] = context;
515 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500516 }
517 if (sbsec->flags & ROOTCONTEXT_MNT) {
518 struct inode *root = sbsec->sb->s_root->d_inode;
519 struct inode_security_struct *isec = root->i_security;
520
521 rc = security_sid_to_context(isec->sid, &context, &len);
522 if (rc)
523 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500524 opts->mnt_opts[i] = context;
525 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500526 }
David P. Quigley11689d42009-01-16 09:22:03 -0500527 if (sbsec->flags & SE_SBLABELSUPP) {
528 opts->mnt_opts[i] = NULL;
529 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
530 }
Eric Parisc9180a52007-11-30 13:00:35 -0500531
Eric Parise0007522008-03-05 10:31:54 -0500532 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500533
534 return 0;
535
536out_free:
Eric Parise0007522008-03-05 10:31:54 -0500537 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500538 return rc;
539}
540
541static int bad_option(struct superblock_security_struct *sbsec, char flag,
542 u32 old_sid, u32 new_sid)
543{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500544 char mnt_flags = sbsec->flags & SE_MNTMASK;
545
Eric Parisc9180a52007-11-30 13:00:35 -0500546 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500547 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500548 if (!(sbsec->flags & flag) ||
549 (old_sid != new_sid))
550 return 1;
551
552 /* check if we were passed the same options twice,
553 * aka someone passed context=a,context=b
554 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500555 if (!(sbsec->flags & SE_SBINITIALIZED))
556 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500557 return 1;
558 return 0;
559}
Eric Parise0007522008-03-05 10:31:54 -0500560
Eric Parisc9180a52007-11-30 13:00:35 -0500561/*
562 * Allow filesystems with binary mount data to explicitly set mount point
563 * labeling information.
564 */
Eric Parise0007522008-03-05 10:31:54 -0500565static int selinux_set_mnt_opts(struct super_block *sb,
566 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500567{
David Howells275bb412008-11-14 10:39:19 +1100568 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500569 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500570 struct superblock_security_struct *sbsec = sb->s_security;
571 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000572 struct inode *inode = sbsec->sb->s_root->d_inode;
573 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500574 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
575 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500576 char **mount_options = opts->mnt_opts;
577 int *flags = opts->mnt_opts_flags;
578 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500579
580 mutex_lock(&sbsec->lock);
581
582 if (!ss_initialized) {
583 if (!num_opts) {
584 /* Defer initialization until selinux_complete_init,
585 after the initial policy is loaded and the security
586 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500587 goto out;
588 }
589 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400590 printk(KERN_WARNING "SELinux: Unable to set superblock options "
591 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500592 goto out;
593 }
594
595 /*
Eric Parise0007522008-03-05 10:31:54 -0500596 * Binary mount data FS will come through this function twice. Once
597 * from an explicit call and once from the generic calls from the vfs.
598 * Since the generic VFS calls will not contain any security mount data
599 * we need to skip the double mount verification.
600 *
601 * This does open a hole in which we will not notice if the first
602 * mount using this sb set explict options and a second mount using
603 * this sb does not set any security options. (The first options
604 * will be used for both mounts)
605 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500606 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500607 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400608 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500609
610 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500611 * parse the mount options, check if they are valid sids.
612 * also check if someone is trying to mount the same sb more
613 * than once with different security options.
614 */
615 for (i = 0; i < num_opts; i++) {
616 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500617
618 if (flags[i] == SE_SBLABELSUPP)
619 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500620 rc = security_context_to_sid(mount_options[i],
621 strlen(mount_options[i]), &sid);
622 if (rc) {
623 printk(KERN_WARNING "SELinux: security_context_to_sid"
624 "(%s) failed for (dev %s, type %s) errno=%d\n",
625 mount_options[i], sb->s_id, name, rc);
626 goto out;
627 }
628 switch (flags[i]) {
629 case FSCONTEXT_MNT:
630 fscontext_sid = sid;
631
632 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
633 fscontext_sid))
634 goto out_double_mount;
635
636 sbsec->flags |= FSCONTEXT_MNT;
637 break;
638 case CONTEXT_MNT:
639 context_sid = sid;
640
641 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
642 context_sid))
643 goto out_double_mount;
644
645 sbsec->flags |= CONTEXT_MNT;
646 break;
647 case ROOTCONTEXT_MNT:
648 rootcontext_sid = sid;
649
650 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
651 rootcontext_sid))
652 goto out_double_mount;
653
654 sbsec->flags |= ROOTCONTEXT_MNT;
655
656 break;
657 case DEFCONTEXT_MNT:
658 defcontext_sid = sid;
659
660 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
661 defcontext_sid))
662 goto out_double_mount;
663
664 sbsec->flags |= DEFCONTEXT_MNT;
665
666 break;
667 default:
668 rc = -EINVAL;
669 goto out;
670 }
671 }
672
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500673 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500674 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500675 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500676 goto out_double_mount;
677 rc = 0;
678 goto out;
679 }
680
James Morris089be432008-07-15 18:32:49 +1000681 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500682 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500683
684 /* Determine the labeling behavior to use for this filesystem type. */
Eric Paris40d3d0b2012-08-24 15:58:45 -0400685 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500686 if (rc) {
687 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000688 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500689 goto out;
690 }
691
692 /* sets the context of the superblock for the fs being mounted. */
693 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100694 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500695 if (rc)
696 goto out;
697
698 sbsec->sid = fscontext_sid;
699 }
700
701 /*
702 * Switch to using mount point labeling behavior.
703 * sets the label used on all file below the mountpoint, and will set
704 * the superblock context if not already set.
705 */
706 if (context_sid) {
707 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100708 rc = may_context_mount_sb_relabel(context_sid, sbsec,
709 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500710 if (rc)
711 goto out;
712 sbsec->sid = context_sid;
713 } else {
David Howells275bb412008-11-14 10:39:19 +1100714 rc = may_context_mount_inode_relabel(context_sid, sbsec,
715 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500716 if (rc)
717 goto out;
718 }
719 if (!rootcontext_sid)
720 rootcontext_sid = context_sid;
721
722 sbsec->mntpoint_sid = context_sid;
723 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
724 }
725
726 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100727 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
728 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500729 if (rc)
730 goto out;
731
732 root_isec->sid = rootcontext_sid;
733 root_isec->initialized = 1;
734 }
735
736 if (defcontext_sid) {
737 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
738 rc = -EINVAL;
739 printk(KERN_WARNING "SELinux: defcontext option is "
740 "invalid for this filesystem type\n");
741 goto out;
742 }
743
744 if (defcontext_sid != sbsec->def_sid) {
745 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100746 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500747 if (rc)
748 goto out;
749 }
750
751 sbsec->def_sid = defcontext_sid;
752 }
753
754 rc = sb_finish_set_opts(sb);
755out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700756 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500758out_double_mount:
759 rc = -EINVAL;
760 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
761 "security settings for (dev %s, type %s)\n", sb->s_id, name);
762 goto out;
763}
764
Jeff Layton094f7b62013-04-01 08:14:24 -0400765static int selinux_cmp_sb_context(const struct super_block *oldsb,
766 const struct super_block *newsb)
767{
768 struct superblock_security_struct *old = oldsb->s_security;
769 struct superblock_security_struct *new = newsb->s_security;
770 char oldflags = old->flags & SE_MNTMASK;
771 char newflags = new->flags & SE_MNTMASK;
772
773 if (oldflags != newflags)
774 goto mismatch;
775 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
776 goto mismatch;
777 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
778 goto mismatch;
779 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
780 goto mismatch;
781 if (oldflags & ROOTCONTEXT_MNT) {
782 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
783 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
784 if (oldroot->sid != newroot->sid)
785 goto mismatch;
786 }
787 return 0;
788mismatch:
789 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
790 "different security settings for (dev %s, "
791 "type %s)\n", newsb->s_id, newsb->s_type->name);
792 return -EBUSY;
793}
794
795static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500796 struct super_block *newsb)
797{
798 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
799 struct superblock_security_struct *newsbsec = newsb->s_security;
800
801 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
802 int set_context = (oldsbsec->flags & CONTEXT_MNT);
803 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
804
Eric Paris0f5e6422008-04-21 16:24:11 -0400805 /*
806 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400807 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400808 */
Al Viroe8c26252010-03-23 06:36:54 -0400809 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400810 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500811
Eric Parisc9180a52007-11-30 13:00:35 -0500812 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500813 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500814
Jeff Layton094f7b62013-04-01 08:14:24 -0400815 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500816 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400817 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400818
Eric Parisc9180a52007-11-30 13:00:35 -0500819 mutex_lock(&newsbsec->lock);
820
821 newsbsec->flags = oldsbsec->flags;
822
823 newsbsec->sid = oldsbsec->sid;
824 newsbsec->def_sid = oldsbsec->def_sid;
825 newsbsec->behavior = oldsbsec->behavior;
826
827 if (set_context) {
828 u32 sid = oldsbsec->mntpoint_sid;
829
830 if (!set_fscontext)
831 newsbsec->sid = sid;
832 if (!set_rootcontext) {
833 struct inode *newinode = newsb->s_root->d_inode;
834 struct inode_security_struct *newisec = newinode->i_security;
835 newisec->sid = sid;
836 }
837 newsbsec->mntpoint_sid = sid;
838 }
839 if (set_rootcontext) {
840 const struct inode *oldinode = oldsb->s_root->d_inode;
841 const struct inode_security_struct *oldisec = oldinode->i_security;
842 struct inode *newinode = newsb->s_root->d_inode;
843 struct inode_security_struct *newisec = newinode->i_security;
844
845 newisec->sid = oldisec->sid;
846 }
847
848 sb_finish_set_opts(newsb);
849 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400850 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500851}
852
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200853static int selinux_parse_opts_str(char *options,
854 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500855{
Eric Parise0007522008-03-05 10:31:54 -0500856 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500857 char *context = NULL, *defcontext = NULL;
858 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500859 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500860
Eric Parise0007522008-03-05 10:31:54 -0500861 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500862
863 /* Standard string-based options. */
864 while ((p = strsep(&options, "|")) != NULL) {
865 int token;
866 substring_t args[MAX_OPT_ARGS];
867
868 if (!*p)
869 continue;
870
871 token = match_token(p, tokens, args);
872
873 switch (token) {
874 case Opt_context:
875 if (context || defcontext) {
876 rc = -EINVAL;
877 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
878 goto out_err;
879 }
880 context = match_strdup(&args[0]);
881 if (!context) {
882 rc = -ENOMEM;
883 goto out_err;
884 }
885 break;
886
887 case Opt_fscontext:
888 if (fscontext) {
889 rc = -EINVAL;
890 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
891 goto out_err;
892 }
893 fscontext = match_strdup(&args[0]);
894 if (!fscontext) {
895 rc = -ENOMEM;
896 goto out_err;
897 }
898 break;
899
900 case Opt_rootcontext:
901 if (rootcontext) {
902 rc = -EINVAL;
903 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
904 goto out_err;
905 }
906 rootcontext = match_strdup(&args[0]);
907 if (!rootcontext) {
908 rc = -ENOMEM;
909 goto out_err;
910 }
911 break;
912
913 case Opt_defcontext:
914 if (context || defcontext) {
915 rc = -EINVAL;
916 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
917 goto out_err;
918 }
919 defcontext = match_strdup(&args[0]);
920 if (!defcontext) {
921 rc = -ENOMEM;
922 goto out_err;
923 }
924 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500925 case Opt_labelsupport:
926 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500927 default:
928 rc = -EINVAL;
929 printk(KERN_WARNING "SELinux: unknown mount option\n");
930 goto out_err;
931
932 }
933 }
934
Eric Parise0007522008-03-05 10:31:54 -0500935 rc = -ENOMEM;
936 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
937 if (!opts->mnt_opts)
938 goto out_err;
939
940 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
941 if (!opts->mnt_opts_flags) {
942 kfree(opts->mnt_opts);
943 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500944 }
945
Eric Parise0007522008-03-05 10:31:54 -0500946 if (fscontext) {
947 opts->mnt_opts[num_mnt_opts] = fscontext;
948 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
949 }
950 if (context) {
951 opts->mnt_opts[num_mnt_opts] = context;
952 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
953 }
954 if (rootcontext) {
955 opts->mnt_opts[num_mnt_opts] = rootcontext;
956 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
957 }
958 if (defcontext) {
959 opts->mnt_opts[num_mnt_opts] = defcontext;
960 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
961 }
962
963 opts->num_mnt_opts = num_mnt_opts;
964 return 0;
965
Eric Parisc9180a52007-11-30 13:00:35 -0500966out_err:
967 kfree(context);
968 kfree(defcontext);
969 kfree(fscontext);
970 kfree(rootcontext);
971 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972}
Eric Parise0007522008-03-05 10:31:54 -0500973/*
974 * string mount options parsing and call set the sbsec
975 */
976static int superblock_doinit(struct super_block *sb, void *data)
977{
978 int rc = 0;
979 char *options = data;
980 struct security_mnt_opts opts;
981
982 security_init_mnt_opts(&opts);
983
984 if (!data)
985 goto out;
986
987 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
988
989 rc = selinux_parse_opts_str(options, &opts);
990 if (rc)
991 goto out_err;
992
993out:
994 rc = selinux_set_mnt_opts(sb, &opts);
995
996out_err:
997 security_free_mnt_opts(&opts);
998 return rc;
999}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Adrian Bunk3583a712008-07-22 20:21:23 +03001001static void selinux_write_opts(struct seq_file *m,
1002 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001003{
1004 int i;
1005 char *prefix;
1006
1007 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001008 char *has_comma;
1009
1010 if (opts->mnt_opts[i])
1011 has_comma = strchr(opts->mnt_opts[i], ',');
1012 else
1013 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001014
1015 switch (opts->mnt_opts_flags[i]) {
1016 case CONTEXT_MNT:
1017 prefix = CONTEXT_STR;
1018 break;
1019 case FSCONTEXT_MNT:
1020 prefix = FSCONTEXT_STR;
1021 break;
1022 case ROOTCONTEXT_MNT:
1023 prefix = ROOTCONTEXT_STR;
1024 break;
1025 case DEFCONTEXT_MNT:
1026 prefix = DEFCONTEXT_STR;
1027 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001028 case SE_SBLABELSUPP:
1029 seq_putc(m, ',');
1030 seq_puts(m, LABELSUPP_STR);
1031 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001032 default:
1033 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001034 return;
Eric Paris2069f452008-07-04 09:47:13 +10001035 };
1036 /* we need a comma before each option */
1037 seq_putc(m, ',');
1038 seq_puts(m, prefix);
1039 if (has_comma)
1040 seq_putc(m, '\"');
1041 seq_puts(m, opts->mnt_opts[i]);
1042 if (has_comma)
1043 seq_putc(m, '\"');
1044 }
1045}
1046
1047static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1048{
1049 struct security_mnt_opts opts;
1050 int rc;
1051
1052 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001053 if (rc) {
1054 /* before policy load we may get EINVAL, don't show anything */
1055 if (rc == -EINVAL)
1056 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001057 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001058 }
Eric Paris2069f452008-07-04 09:47:13 +10001059
1060 selinux_write_opts(m, &opts);
1061
1062 security_free_mnt_opts(&opts);
1063
1064 return rc;
1065}
1066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067static inline u16 inode_mode_to_security_class(umode_t mode)
1068{
1069 switch (mode & S_IFMT) {
1070 case S_IFSOCK:
1071 return SECCLASS_SOCK_FILE;
1072 case S_IFLNK:
1073 return SECCLASS_LNK_FILE;
1074 case S_IFREG:
1075 return SECCLASS_FILE;
1076 case S_IFBLK:
1077 return SECCLASS_BLK_FILE;
1078 case S_IFDIR:
1079 return SECCLASS_DIR;
1080 case S_IFCHR:
1081 return SECCLASS_CHR_FILE;
1082 case S_IFIFO:
1083 return SECCLASS_FIFO_FILE;
1084
1085 }
1086
1087 return SECCLASS_FILE;
1088}
1089
James Morris13402582005-09-30 14:24:34 -04001090static inline int default_protocol_stream(int protocol)
1091{
1092 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1093}
1094
1095static inline int default_protocol_dgram(int protocol)
1096{
1097 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1098}
1099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1101{
1102 switch (family) {
1103 case PF_UNIX:
1104 switch (type) {
1105 case SOCK_STREAM:
1106 case SOCK_SEQPACKET:
1107 return SECCLASS_UNIX_STREAM_SOCKET;
1108 case SOCK_DGRAM:
1109 return SECCLASS_UNIX_DGRAM_SOCKET;
1110 }
1111 break;
1112 case PF_INET:
1113 case PF_INET6:
1114 switch (type) {
1115 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001116 if (default_protocol_stream(protocol))
1117 return SECCLASS_TCP_SOCKET;
1118 else
1119 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001121 if (default_protocol_dgram(protocol))
1122 return SECCLASS_UDP_SOCKET;
1123 else
1124 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001125 case SOCK_DCCP:
1126 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001127 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 return SECCLASS_RAWIP_SOCKET;
1129 }
1130 break;
1131 case PF_NETLINK:
1132 switch (protocol) {
1133 case NETLINK_ROUTE:
1134 return SECCLASS_NETLINK_ROUTE_SOCKET;
1135 case NETLINK_FIREWALL:
1136 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001137 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1139 case NETLINK_NFLOG:
1140 return SECCLASS_NETLINK_NFLOG_SOCKET;
1141 case NETLINK_XFRM:
1142 return SECCLASS_NETLINK_XFRM_SOCKET;
1143 case NETLINK_SELINUX:
1144 return SECCLASS_NETLINK_SELINUX_SOCKET;
1145 case NETLINK_AUDIT:
1146 return SECCLASS_NETLINK_AUDIT_SOCKET;
1147 case NETLINK_IP6_FW:
1148 return SECCLASS_NETLINK_IP6FW_SOCKET;
1149 case NETLINK_DNRTMSG:
1150 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001151 case NETLINK_KOBJECT_UEVENT:
1152 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 default:
1154 return SECCLASS_NETLINK_SOCKET;
1155 }
1156 case PF_PACKET:
1157 return SECCLASS_PACKET_SOCKET;
1158 case PF_KEY:
1159 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001160 case PF_APPLETALK:
1161 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 }
1163
1164 return SECCLASS_SOCKET;
1165}
1166
1167#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001168static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 u16 tclass,
1170 u32 *sid)
1171{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001172 int rc;
1173 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Eric Paris828dfe12008-04-17 13:17:49 -04001175 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 if (!buffer)
1177 return -ENOMEM;
1178
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001179 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1180 if (IS_ERR(path))
1181 rc = PTR_ERR(path);
1182 else {
1183 /* each process gets a /proc/PID/ entry. Strip off the
1184 * PID part to get a valid selinux labeling.
1185 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1186 while (path[1] >= '0' && path[1] <= '9') {
1187 path[1] = '/';
1188 path++;
1189 }
1190 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 free_page((unsigned long)buffer);
1193 return rc;
1194}
1195#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001196static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 u16 tclass,
1198 u32 *sid)
1199{
1200 return -EINVAL;
1201}
1202#endif
1203
1204/* The inode's security attributes must be initialized before first use. */
1205static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1206{
1207 struct superblock_security_struct *sbsec = NULL;
1208 struct inode_security_struct *isec = inode->i_security;
1209 u32 sid;
1210 struct dentry *dentry;
1211#define INITCONTEXTLEN 255
1212 char *context = NULL;
1213 unsigned len = 0;
1214 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 if (isec->initialized)
1217 goto out;
1218
Eric Paris23970742006-09-25 23:32:01 -07001219 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001221 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001224 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 /* Defer initialization until selinux_complete_init,
1226 after the initial policy is loaded and the security
1227 server is ready to handle calls. */
1228 spin_lock(&sbsec->isec_lock);
1229 if (list_empty(&isec->list))
1230 list_add(&isec->list, &sbsec->isec_head);
1231 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001232 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234
1235 switch (sbsec->behavior) {
1236 case SECURITY_FS_USE_XATTR:
1237 if (!inode->i_op->getxattr) {
1238 isec->sid = sbsec->def_sid;
1239 break;
1240 }
1241
1242 /* Need a dentry, since the xattr API requires one.
1243 Life would be simpler if we could just pass the inode. */
1244 if (opt_dentry) {
1245 /* Called from d_instantiate or d_splice_alias. */
1246 dentry = dget(opt_dentry);
1247 } else {
1248 /* Called from selinux_complete_init, try to find a dentry. */
1249 dentry = d_find_alias(inode);
1250 }
1251 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001252 /*
1253 * this is can be hit on boot when a file is accessed
1254 * before the policy is loaded. When we load policy we
1255 * may find inodes that have no dentry on the
1256 * sbsec->isec_head list. No reason to complain as these
1257 * will get fixed up the next time we go through
1258 * inode_doinit with a dentry, before these inodes could
1259 * be used again by userspace.
1260 */
Eric Paris23970742006-09-25 23:32:01 -07001261 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 }
1263
1264 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001265 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 if (!context) {
1267 rc = -ENOMEM;
1268 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001269 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001271 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1273 context, len);
1274 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001275 kfree(context);
1276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 /* Need a larger buffer. Query for the right size. */
1278 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1279 NULL, 0);
1280 if (rc < 0) {
1281 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001282 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001285 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 if (!context) {
1287 rc = -ENOMEM;
1288 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001289 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001291 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 rc = inode->i_op->getxattr(dentry,
1293 XATTR_NAME_SELINUX,
1294 context, len);
1295 }
1296 dput(dentry);
1297 if (rc < 0) {
1298 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001299 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001300 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 -rc, inode->i_sb->s_id, inode->i_ino);
1302 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001303 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 }
1305 /* Map ENODATA to the default file SID */
1306 sid = sbsec->def_sid;
1307 rc = 0;
1308 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001309 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001310 sbsec->def_sid,
1311 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001313 char *dev = inode->i_sb->s_id;
1314 unsigned long ino = inode->i_ino;
1315
1316 if (rc == -EINVAL) {
1317 if (printk_ratelimit())
1318 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1319 "context=%s. This indicates you may need to relabel the inode or the "
1320 "filesystem in question.\n", ino, dev, context);
1321 } else {
1322 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1323 "returned %d for dev=%s ino=%ld\n",
1324 __func__, context, -rc, dev, ino);
1325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 kfree(context);
1327 /* Leave with the unlabeled SID */
1328 rc = 0;
1329 break;
1330 }
1331 }
1332 kfree(context);
1333 isec->sid = sid;
1334 break;
1335 case SECURITY_FS_USE_TASK:
1336 isec->sid = isec->task_sid;
1337 break;
1338 case SECURITY_FS_USE_TRANS:
1339 /* Default to the fs SID. */
1340 isec->sid = sbsec->sid;
1341
1342 /* Try to obtain a transition SID. */
1343 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001344 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1345 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001347 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 isec->sid = sid;
1349 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001350 case SECURITY_FS_USE_MNTPOINT:
1351 isec->sid = sbsec->mntpoint_sid;
1352 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001354 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 isec->sid = sbsec->sid;
1356
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001357 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001358 if (opt_dentry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001360 rc = selinux_proc_get_sid(opt_dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 isec->sclass,
1362 &sid);
1363 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001364 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 isec->sid = sid;
1366 }
1367 }
1368 break;
1369 }
1370
1371 isec->initialized = 1;
1372
Eric Paris23970742006-09-25 23:32:01 -07001373out_unlock:
1374 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375out:
1376 if (isec->sclass == SECCLASS_FILE)
1377 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 return rc;
1379}
1380
1381/* Convert a Linux signal to an access vector. */
1382static inline u32 signal_to_av(int sig)
1383{
1384 u32 perm = 0;
1385
1386 switch (sig) {
1387 case SIGCHLD:
1388 /* Commonly granted from child to parent. */
1389 perm = PROCESS__SIGCHLD;
1390 break;
1391 case SIGKILL:
1392 /* Cannot be caught or ignored */
1393 perm = PROCESS__SIGKILL;
1394 break;
1395 case SIGSTOP:
1396 /* Cannot be caught or ignored */
1397 perm = PROCESS__SIGSTOP;
1398 break;
1399 default:
1400 /* All other signals. */
1401 perm = PROCESS__SIGNAL;
1402 break;
1403 }
1404
1405 return perm;
1406}
1407
David Howells275bb412008-11-14 10:39:19 +11001408/*
David Howellsd84f4f92008-11-14 10:39:23 +11001409 * Check permission between a pair of credentials
1410 * fork check, ptrace check, etc.
1411 */
1412static int cred_has_perm(const struct cred *actor,
1413 const struct cred *target,
1414 u32 perms)
1415{
1416 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1417
1418 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1419}
1420
1421/*
David Howells88e67f32008-11-14 10:39:21 +11001422 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001423 * fork check, ptrace check, etc.
1424 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001425 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001426 */
1427static int task_has_perm(const struct task_struct *tsk1,
1428 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 u32 perms)
1430{
David Howells275bb412008-11-14 10:39:19 +11001431 const struct task_security_struct *__tsec1, *__tsec2;
1432 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
David Howells275bb412008-11-14 10:39:19 +11001434 rcu_read_lock();
1435 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1436 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1437 rcu_read_unlock();
1438 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439}
1440
David Howells3b11a1d2008-11-14 10:39:26 +11001441/*
1442 * Check permission between current and another task, e.g. signal checks,
1443 * fork check, ptrace check, etc.
1444 * current is the actor and tsk2 is the target
1445 * - this uses current's subjective creds
1446 */
1447static int current_has_perm(const struct task_struct *tsk,
1448 u32 perms)
1449{
1450 u32 sid, tsid;
1451
1452 sid = current_sid();
1453 tsid = task_sid(tsk);
1454 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1455}
1456
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001457#if CAP_LAST_CAP > 63
1458#error Fix SELinux to handle capabilities > 63.
1459#endif
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001462static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001463 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
Thomas Liu2bf49692009-07-14 12:14:09 -04001465 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001466 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001467 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001468 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001469 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001470 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Eric Paris50c205f2012-04-04 15:01:43 -04001472 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 ad.u.cap = cap;
1474
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001475 switch (CAP_TO_INDEX(cap)) {
1476 case 0:
1477 sclass = SECCLASS_CAPABILITY;
1478 break;
1479 case 1:
1480 sclass = SECCLASS_CAPABILITY2;
1481 break;
1482 default:
1483 printk(KERN_ERR
1484 "SELinux: out of range capability %d\n", cap);
1485 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001486 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001487 }
Eric Paris06112162008-11-11 22:02:50 +11001488
David Howells275bb412008-11-14 10:39:19 +11001489 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001490 if (audit == SECURITY_CAP_AUDIT) {
1491 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1492 if (rc2)
1493 return rc2;
1494 }
Eric Paris06112162008-11-11 22:02:50 +11001495 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496}
1497
1498/* Check whether a task is allowed to use a system operation. */
1499static int task_has_system(struct task_struct *tsk,
1500 u32 perms)
1501{
David Howells275bb412008-11-14 10:39:19 +11001502 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
David Howells275bb412008-11-14 10:39:19 +11001504 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 SECCLASS_SYSTEM, perms, NULL);
1506}
1507
1508/* Check whether a task has a particular permission to an inode.
1509 The 'adp' parameter is optional and allows other audit
1510 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001511static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 struct inode *inode,
1513 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001514 struct common_audit_data *adp,
1515 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001518 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
David Howellse0e81732009-09-02 09:13:40 +01001520 validate_creds(cred);
1521
Eric Paris828dfe12008-04-17 13:17:49 -04001522 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001523 return 0;
1524
David Howells88e67f32008-11-14 10:39:21 +11001525 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 isec = inode->i_security;
1527
Eric Paris9ade0cf2011-04-25 16:26:29 -04001528 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529}
1530
1531/* Same as inode_has_perm, but pass explicit audit data containing
1532 the dentry to help the auditing code to more easily generate the
1533 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001534static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 struct dentry *dentry,
1536 u32 av)
1537{
1538 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001539 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001540
Eric Paris50c205f2012-04-04 15:01:43 -04001541 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001542 ad.u.dentry = dentry;
1543 return inode_has_perm(cred, inode, av, &ad, 0);
1544}
1545
1546/* Same as inode_has_perm, but pass explicit audit data containing
1547 the path to help the auditing code to more easily generate the
1548 pathname if needed. */
1549static inline int path_has_perm(const struct cred *cred,
1550 struct path *path,
1551 u32 av)
1552{
1553 struct inode *inode = path->dentry->d_inode;
1554 struct common_audit_data ad;
1555
Eric Paris50c205f2012-04-04 15:01:43 -04001556 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001557 ad.u.path = *path;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001558 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559}
1560
1561/* Check whether a task can use an open file descriptor to
1562 access an inode in a given way. Check access to the
1563 descriptor itself, and then use dentry_has_perm to
1564 check a particular permission to the file.
1565 Access to the descriptor is implicitly granted if it
1566 has the same SID as the process. If av is zero, then
1567 access to the file is not checked, e.g. for cases
1568 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001569static int file_has_perm(const struct cred *cred,
1570 struct file *file,
1571 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001574 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001575 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001576 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 int rc;
1578
Eric Paris50c205f2012-04-04 15:01:43 -04001579 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001580 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
David Howells275bb412008-11-14 10:39:19 +11001582 if (sid != fsec->sid) {
1583 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 SECCLASS_FD,
1585 FD__USE,
1586 &ad);
1587 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001588 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 }
1590
1591 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001592 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001594 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
David Howells88e67f32008-11-14 10:39:21 +11001596out:
1597 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
1599
1600/* Check whether a task can create a file. */
1601static int may_create(struct inode *dir,
1602 struct dentry *dentry,
1603 u16 tclass)
1604{
Paul Moore5fb49872010-04-22 14:46:19 -04001605 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 struct inode_security_struct *dsec;
1607 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001608 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001609 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 int rc;
1611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 dsec = dir->i_security;
1613 sbsec = dir->i_sb->s_security;
1614
David Howells275bb412008-11-14 10:39:19 +11001615 sid = tsec->sid;
1616 newsid = tsec->create_sid;
1617
Eric Paris50c205f2012-04-04 15:01:43 -04001618 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001619 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
David Howells275bb412008-11-14 10:39:19 +11001621 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 DIR__ADD_NAME | DIR__SEARCH,
1623 &ad);
1624 if (rc)
1625 return rc;
1626
David P. Quigleycd895962009-01-16 09:22:04 -05001627 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001628 rc = security_transition_sid(sid, dsec->sid, tclass,
1629 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (rc)
1631 return rc;
1632 }
1633
David Howells275bb412008-11-14 10:39:19 +11001634 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (rc)
1636 return rc;
1637
1638 return avc_has_perm(newsid, sbsec->sid,
1639 SECCLASS_FILESYSTEM,
1640 FILESYSTEM__ASSOCIATE, &ad);
1641}
1642
Michael LeMay4eb582c2006-06-26 00:24:57 -07001643/* Check whether a task can create a key. */
1644static int may_create_key(u32 ksid,
1645 struct task_struct *ctx)
1646{
David Howells275bb412008-11-14 10:39:19 +11001647 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001648
David Howells275bb412008-11-14 10:39:19 +11001649 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001650}
1651
Eric Paris828dfe12008-04-17 13:17:49 -04001652#define MAY_LINK 0
1653#define MAY_UNLINK 1
1654#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
1656/* Check whether a task can link, unlink, or rmdir a file/directory. */
1657static int may_link(struct inode *dir,
1658 struct dentry *dentry,
1659 int kind)
1660
1661{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001663 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001664 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 u32 av;
1666 int rc;
1667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 dsec = dir->i_security;
1669 isec = dentry->d_inode->i_security;
1670
Eric Paris50c205f2012-04-04 15:01:43 -04001671 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001672 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 av = DIR__SEARCH;
1675 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001676 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 if (rc)
1678 return rc;
1679
1680 switch (kind) {
1681 case MAY_LINK:
1682 av = FILE__LINK;
1683 break;
1684 case MAY_UNLINK:
1685 av = FILE__UNLINK;
1686 break;
1687 case MAY_RMDIR:
1688 av = DIR__RMDIR;
1689 break;
1690 default:
Eric Paris744ba352008-04-17 11:52:44 -04001691 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1692 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 return 0;
1694 }
1695
David Howells275bb412008-11-14 10:39:19 +11001696 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 return rc;
1698}
1699
1700static inline int may_rename(struct inode *old_dir,
1701 struct dentry *old_dentry,
1702 struct inode *new_dir,
1703 struct dentry *new_dentry)
1704{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001706 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001707 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 u32 av;
1709 int old_is_dir, new_is_dir;
1710 int rc;
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 old_dsec = old_dir->i_security;
1713 old_isec = old_dentry->d_inode->i_security;
1714 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1715 new_dsec = new_dir->i_security;
1716
Eric Paris50c205f2012-04-04 15:01:43 -04001717 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Eric Parisa2694342011-04-25 13:10:27 -04001719 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001720 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1722 if (rc)
1723 return rc;
David Howells275bb412008-11-14 10:39:19 +11001724 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 old_isec->sclass, FILE__RENAME, &ad);
1726 if (rc)
1727 return rc;
1728 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001729 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 old_isec->sclass, DIR__REPARENT, &ad);
1731 if (rc)
1732 return rc;
1733 }
1734
Eric Parisa2694342011-04-25 13:10:27 -04001735 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 av = DIR__ADD_NAME | DIR__SEARCH;
1737 if (new_dentry->d_inode)
1738 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001739 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 if (rc)
1741 return rc;
1742 if (new_dentry->d_inode) {
1743 new_isec = new_dentry->d_inode->i_security;
1744 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001745 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 new_isec->sclass,
1747 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1748 if (rc)
1749 return rc;
1750 }
1751
1752 return 0;
1753}
1754
1755/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001756static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 struct super_block *sb,
1758 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001759 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001762 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001765 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766}
1767
1768/* Convert a Linux mode and permission mask to an access vector. */
1769static inline u32 file_mask_to_av(int mode, int mask)
1770{
1771 u32 av = 0;
1772
Al Virodba19c62011-07-25 20:49:29 -04001773 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 if (mask & MAY_EXEC)
1775 av |= FILE__EXECUTE;
1776 if (mask & MAY_READ)
1777 av |= FILE__READ;
1778
1779 if (mask & MAY_APPEND)
1780 av |= FILE__APPEND;
1781 else if (mask & MAY_WRITE)
1782 av |= FILE__WRITE;
1783
1784 } else {
1785 if (mask & MAY_EXEC)
1786 av |= DIR__SEARCH;
1787 if (mask & MAY_WRITE)
1788 av |= DIR__WRITE;
1789 if (mask & MAY_READ)
1790 av |= DIR__READ;
1791 }
1792
1793 return av;
1794}
1795
1796/* Convert a Linux file to an access vector. */
1797static inline u32 file_to_av(struct file *file)
1798{
1799 u32 av = 0;
1800
1801 if (file->f_mode & FMODE_READ)
1802 av |= FILE__READ;
1803 if (file->f_mode & FMODE_WRITE) {
1804 if (file->f_flags & O_APPEND)
1805 av |= FILE__APPEND;
1806 else
1807 av |= FILE__WRITE;
1808 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001809 if (!av) {
1810 /*
1811 * Special file opened with flags 3 for ioctl-only use.
1812 */
1813 av = FILE__IOCTL;
1814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816 return av;
1817}
1818
Eric Paris8b6a5a32008-10-29 17:06:46 -04001819/*
1820 * Convert a file to an access vector and include the correct open
1821 * open permission.
1822 */
1823static inline u32 open_file_to_av(struct file *file)
1824{
1825 u32 av = file_to_av(file);
1826
Eric Paris49b7b8d2010-07-23 11:44:09 -04001827 if (selinux_policycap_openperm)
1828 av |= FILE__OPEN;
1829
Eric Paris8b6a5a32008-10-29 17:06:46 -04001830 return av;
1831}
1832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833/* Hook functions begin here. */
1834
Ingo Molnar9e488582009-05-07 19:26:19 +10001835static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001836 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 int rc;
1839
Ingo Molnar9e488582009-05-07 19:26:19 +10001840 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (rc)
1842 return rc;
1843
Eric Paris69f594a2012-01-03 12:25:15 -05001844 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001845 u32 sid = current_sid();
1846 u32 csid = task_sid(child);
1847 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001848 }
1849
David Howells3b11a1d2008-11-14 10:39:26 +11001850 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001851}
1852
1853static int selinux_ptrace_traceme(struct task_struct *parent)
1854{
1855 int rc;
1856
Eric Paris200ac532009-02-12 15:01:04 -05001857 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001858 if (rc)
1859 return rc;
1860
1861 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862}
1863
1864static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001865 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866{
1867 int error;
1868
David Howells3b11a1d2008-11-14 10:39:26 +11001869 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 if (error)
1871 return error;
1872
Eric Paris200ac532009-02-12 15:01:04 -05001873 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874}
1875
David Howellsd84f4f92008-11-14 10:39:23 +11001876static int selinux_capset(struct cred *new, const struct cred *old,
1877 const kernel_cap_t *effective,
1878 const kernel_cap_t *inheritable,
1879 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880{
1881 int error;
1882
Eric Paris200ac532009-02-12 15:01:04 -05001883 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001884 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 if (error)
1886 return error;
1887
David Howellsd84f4f92008-11-14 10:39:23 +11001888 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889}
1890
James Morris5626d3e2009-01-30 10:05:06 +11001891/*
1892 * (This comment used to live with the selinux_task_setuid hook,
1893 * which was removed).
1894 *
1895 * Since setuid only affects the current process, and since the SELinux
1896 * controls are not based on the Linux identity attributes, SELinux does not
1897 * need to control this operation. However, SELinux does control the use of
1898 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1899 */
1900
Eric Paris6a9de492012-01-03 12:25:14 -05001901static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1902 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 int rc;
1905
Eric Paris6a9de492012-01-03 12:25:14 -05001906 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 if (rc)
1908 return rc;
1909
Eric Paris6a9de492012-01-03 12:25:14 -05001910 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911}
1912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1914{
David Howells88e67f32008-11-14 10:39:21 +11001915 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 int rc = 0;
1917
1918 if (!sb)
1919 return 0;
1920
1921 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001922 case Q_SYNC:
1923 case Q_QUOTAON:
1924 case Q_QUOTAOFF:
1925 case Q_SETINFO:
1926 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001927 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001928 break;
1929 case Q_GETFMT:
1930 case Q_GETINFO:
1931 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001932 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001933 break;
1934 default:
1935 rc = 0; /* let the kernel handle invalid cmds */
1936 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 }
1938 return rc;
1939}
1940
1941static int selinux_quota_on(struct dentry *dentry)
1942{
David Howells88e67f32008-11-14 10:39:21 +11001943 const struct cred *cred = current_cred();
1944
Eric Paris2875fa02011-04-28 16:04:24 -04001945 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946}
1947
Eric Paris12b30522010-11-15 18:36:29 -05001948static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949{
1950 int rc;
1951
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08001953 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
1954 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001955 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1956 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001957 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
1958 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
1959 /* Set level of messages printed to console */
1960 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04001961 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1962 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001963 case SYSLOG_ACTION_CLOSE: /* Close log */
1964 case SYSLOG_ACTION_OPEN: /* Open log */
1965 case SYSLOG_ACTION_READ: /* Read from log */
1966 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
1967 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001968 default:
1969 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1970 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 }
1972 return rc;
1973}
1974
1975/*
1976 * Check that a process has enough memory to allocate a new virtual
1977 * mapping. 0 means there is enough memory for the allocation to
1978 * succeed and -ENOMEM implies there is not.
1979 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 * Do not audit the selinux permission check, as this is applied to all
1981 * processes that allocate mappings.
1982 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001983static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984{
1985 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Eric Paris6a9de492012-01-03 12:25:14 -05001987 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00001988 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 if (rc == 0)
1990 cap_sys_admin = 1;
1991
Alan Cox34b4e4a2007-08-22 14:01:28 -07001992 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
1995/* binprm security operations */
1996
David Howellsa6f76f22008-11-14 10:39:24 +11001997static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998{
David Howellsa6f76f22008-11-14 10:39:24 +11001999 const struct task_security_struct *old_tsec;
2000 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002002 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002003 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 int rc;
2005
Eric Paris200ac532009-02-12 15:01:04 -05002006 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 if (rc)
2008 return rc;
2009
David Howellsa6f76f22008-11-14 10:39:24 +11002010 /* SELinux context only depends on initial program or script and not
2011 * the script interpreter */
2012 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 return 0;
2014
David Howellsa6f76f22008-11-14 10:39:24 +11002015 old_tsec = current_security();
2016 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 isec = inode->i_security;
2018
2019 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002020 new_tsec->sid = old_tsec->sid;
2021 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Michael LeMay28eba5b2006-06-27 02:53:42 -07002023 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002024 new_tsec->create_sid = 0;
2025 new_tsec->keycreate_sid = 0;
2026 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
David Howellsa6f76f22008-11-14 10:39:24 +11002028 if (old_tsec->exec_sid) {
2029 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002031 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002032
2033 /*
2034 * Minimize confusion: if no_new_privs and a transition is
2035 * explicitly requested, then fail the exec.
2036 */
2037 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2038 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 } else {
2040 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002041 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002042 SECCLASS_PROCESS, NULL,
2043 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 if (rc)
2045 return rc;
2046 }
2047
Eric Paris50c205f2012-04-04 15:01:43 -04002048 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002049 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002051 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2052 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002053 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
David Howellsa6f76f22008-11-14 10:39:24 +11002055 if (new_tsec->sid == old_tsec->sid) {
2056 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2058 if (rc)
2059 return rc;
2060 } else {
2061 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002062 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2064 if (rc)
2065 return rc;
2066
David Howellsa6f76f22008-11-14 10:39:24 +11002067 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2069 if (rc)
2070 return rc;
2071
David Howellsa6f76f22008-11-14 10:39:24 +11002072 /* Check for shared state */
2073 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2074 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2075 SECCLASS_PROCESS, PROCESS__SHARE,
2076 NULL);
2077 if (rc)
2078 return -EPERM;
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080
David Howellsa6f76f22008-11-14 10:39:24 +11002081 /* Make sure that anyone attempting to ptrace over a task that
2082 * changes its SID has the appropriate permit */
2083 if (bprm->unsafe &
2084 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2085 struct task_struct *tracer;
2086 struct task_security_struct *sec;
2087 u32 ptsid = 0;
2088
2089 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002090 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002091 if (likely(tracer != NULL)) {
2092 sec = __task_cred(tracer)->security;
2093 ptsid = sec->sid;
2094 }
2095 rcu_read_unlock();
2096
2097 if (ptsid != 0) {
2098 rc = avc_has_perm(ptsid, new_tsec->sid,
2099 SECCLASS_PROCESS,
2100 PROCESS__PTRACE, NULL);
2101 if (rc)
2102 return -EPERM;
2103 }
2104 }
2105
2106 /* Clear any possibly unsafe personality bits on exec: */
2107 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 }
2109
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 return 0;
2111}
2112
Eric Paris828dfe12008-04-17 13:17:49 -04002113static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114{
Paul Moore5fb49872010-04-22 14:46:19 -04002115 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002116 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 int atsecure = 0;
2118
David Howells275bb412008-11-14 10:39:19 +11002119 sid = tsec->sid;
2120 osid = tsec->osid;
2121
2122 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 /* Enable secure mode for SIDs transitions unless
2124 the noatsecure permission is granted between
2125 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002126 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002127 SECCLASS_PROCESS,
2128 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 }
2130
Eric Paris200ac532009-02-12 15:01:04 -05002131 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Al Viroc3c073f2012-08-21 22:32:06 -04002134static int match_file(const void *p, struct file *file, unsigned fd)
2135{
2136 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2137}
2138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002140static inline void flush_unauthorized_files(const struct cred *cred,
2141 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002144 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002145 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002146 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002148 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002150 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002151 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002152 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 /* Revalidate access to controlling tty.
Eric Paris602a8dd2012-04-04 15:01:42 -04002155 Use path_has_perm on the tty path directly rather
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 than using file_has_perm, as this particular open
2157 file may belong to another process and we are only
2158 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002159 file_priv = list_first_entry(&tty->tty_files,
2160 struct tty_file_private, list);
2161 file = file_priv->file;
Eric Paris602a8dd2012-04-04 15:01:42 -04002162 if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002163 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002165 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002166 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002168 /* Reset controlling tty. */
2169 if (drop_tty)
2170 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
2172 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002173 n = iterate_fd(files, 0, match_file, cred);
2174 if (!n) /* none found? */
2175 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Al Viroc3c073f2012-08-21 22:32:06 -04002177 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002178 if (IS_ERR(devnull))
2179 devnull = NULL;
2180 /* replace all the matching ones with this */
2181 do {
2182 replace_fd(n - 1, devnull, 0);
2183 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2184 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002185 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186}
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188/*
David Howellsa6f76f22008-11-14 10:39:24 +11002189 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 */
David Howellsa6f76f22008-11-14 10:39:24 +11002191static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192{
David Howellsa6f76f22008-11-14 10:39:24 +11002193 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 int rc, i;
2196
David Howellsa6f76f22008-11-14 10:39:24 +11002197 new_tsec = bprm->cred->security;
2198 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 return;
2200
2201 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002202 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
David Howellsa6f76f22008-11-14 10:39:24 +11002204 /* Always clear parent death signal on SID transitions. */
2205 current->pdeath_signal = 0;
2206
2207 /* Check whether the new SID can inherit resource limits from the old
2208 * SID. If not, reset all soft limits to the lower of the current
2209 * task's hard limit and the init task's soft limit.
2210 *
2211 * Note that the setting of hard limits (even to lower them) can be
2212 * controlled by the setrlimit check. The inclusion of the init task's
2213 * soft limit into the computation is to avoid resetting soft limits
2214 * higher than the default soft limit for cases where the default is
2215 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2216 */
2217 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2218 PROCESS__RLIMITINH, NULL);
2219 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002220 /* protect against do_prlimit() */
2221 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002222 for (i = 0; i < RLIM_NLIMITS; i++) {
2223 rlim = current->signal->rlim + i;
2224 initrlim = init_task.signal->rlim + i;
2225 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2226 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002227 task_unlock(current);
2228 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002229 }
2230}
2231
2232/*
2233 * Clean up the process immediately after the installation of new credentials
2234 * due to exec
2235 */
2236static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2237{
2238 const struct task_security_struct *tsec = current_security();
2239 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002240 u32 osid, sid;
2241 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002242
David Howellsa6f76f22008-11-14 10:39:24 +11002243 osid = tsec->osid;
2244 sid = tsec->sid;
2245
2246 if (sid == osid)
2247 return;
2248
2249 /* Check whether the new SID can inherit signal state from the old SID.
2250 * If not, clear itimers to avoid subsequent signal generation and
2251 * flush and unblock signals.
2252 *
2253 * This must occur _after_ the task SID has been updated so that any
2254 * kill done after the flush will be checked against the new SID.
2255 */
2256 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if (rc) {
2258 memset(&itimer, 0, sizeof itimer);
2259 for (i = 0; i < 3; i++)
2260 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002262 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2263 __flush_signals(current);
2264 flush_signal_handlers(current, 1);
2265 sigemptyset(&current->blocked);
2266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 spin_unlock_irq(&current->sighand->siglock);
2268 }
2269
David Howellsa6f76f22008-11-14 10:39:24 +11002270 /* Wake up the parent if it is waiting so that it can recheck
2271 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002272 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002273 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002274 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275}
2276
2277/* superblock security operations */
2278
2279static int selinux_sb_alloc_security(struct super_block *sb)
2280{
2281 return superblock_alloc_security(sb);
2282}
2283
2284static void selinux_sb_free_security(struct super_block *sb)
2285{
2286 superblock_free_security(sb);
2287}
2288
2289static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2290{
2291 if (plen > olen)
2292 return 0;
2293
2294 return !memcmp(prefix, option, plen);
2295}
2296
2297static inline int selinux_option(char *option, int len)
2298{
Eric Paris832cbd92008-04-01 13:24:09 -04002299 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2300 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2301 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002302 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2303 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304}
2305
2306static inline void take_option(char **to, char *from, int *first, int len)
2307{
2308 if (!*first) {
2309 **to = ',';
2310 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002311 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 *first = 0;
2313 memcpy(*to, from, len);
2314 *to += len;
2315}
2316
Eric Paris828dfe12008-04-17 13:17:49 -04002317static inline void take_selinux_option(char **to, char *from, int *first,
2318 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002319{
2320 int current_size = 0;
2321
2322 if (!*first) {
2323 **to = '|';
2324 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002325 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002326 *first = 0;
2327
2328 while (current_size < len) {
2329 if (*from != '"') {
2330 **to = *from;
2331 *to += 1;
2332 }
2333 from += 1;
2334 current_size += 1;
2335 }
2336}
2337
Eric Parise0007522008-03-05 10:31:54 -05002338static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339{
2340 int fnosec, fsec, rc = 0;
2341 char *in_save, *in_curr, *in_end;
2342 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002343 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
2345 in_curr = orig;
2346 sec_curr = copy;
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2349 if (!nosec) {
2350 rc = -ENOMEM;
2351 goto out;
2352 }
2353
2354 nosec_save = nosec;
2355 fnosec = fsec = 1;
2356 in_save = in_end = orig;
2357
2358 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002359 if (*in_end == '"')
2360 open_quote = !open_quote;
2361 if ((*in_end == ',' && open_quote == 0) ||
2362 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 int len = in_end - in_curr;
2364
2365 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002366 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 else
2368 take_option(&nosec, in_curr, &fnosec, len);
2369
2370 in_curr = in_end + 1;
2371 }
2372 } while (*in_end++);
2373
Eric Paris6931dfc2005-06-30 02:58:51 -07002374 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002375 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376out:
2377 return rc;
2378}
2379
Eric Paris026eb162011-03-03 16:09:14 -05002380static int selinux_sb_remount(struct super_block *sb, void *data)
2381{
2382 int rc, i, *flags;
2383 struct security_mnt_opts opts;
2384 char *secdata, **mount_options;
2385 struct superblock_security_struct *sbsec = sb->s_security;
2386
2387 if (!(sbsec->flags & SE_SBINITIALIZED))
2388 return 0;
2389
2390 if (!data)
2391 return 0;
2392
2393 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2394 return 0;
2395
2396 security_init_mnt_opts(&opts);
2397 secdata = alloc_secdata();
2398 if (!secdata)
2399 return -ENOMEM;
2400 rc = selinux_sb_copy_data(data, secdata);
2401 if (rc)
2402 goto out_free_secdata;
2403
2404 rc = selinux_parse_opts_str(secdata, &opts);
2405 if (rc)
2406 goto out_free_secdata;
2407
2408 mount_options = opts.mnt_opts;
2409 flags = opts.mnt_opts_flags;
2410
2411 for (i = 0; i < opts.num_mnt_opts; i++) {
2412 u32 sid;
2413 size_t len;
2414
2415 if (flags[i] == SE_SBLABELSUPP)
2416 continue;
2417 len = strlen(mount_options[i]);
2418 rc = security_context_to_sid(mount_options[i], len, &sid);
2419 if (rc) {
2420 printk(KERN_WARNING "SELinux: security_context_to_sid"
2421 "(%s) failed for (dev %s, type %s) errno=%d\n",
2422 mount_options[i], sb->s_id, sb->s_type->name, rc);
2423 goto out_free_opts;
2424 }
2425 rc = -EINVAL;
2426 switch (flags[i]) {
2427 case FSCONTEXT_MNT:
2428 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2429 goto out_bad_option;
2430 break;
2431 case CONTEXT_MNT:
2432 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2433 goto out_bad_option;
2434 break;
2435 case ROOTCONTEXT_MNT: {
2436 struct inode_security_struct *root_isec;
2437 root_isec = sb->s_root->d_inode->i_security;
2438
2439 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2440 goto out_bad_option;
2441 break;
2442 }
2443 case DEFCONTEXT_MNT:
2444 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2445 goto out_bad_option;
2446 break;
2447 default:
2448 goto out_free_opts;
2449 }
2450 }
2451
2452 rc = 0;
2453out_free_opts:
2454 security_free_mnt_opts(&opts);
2455out_free_secdata:
2456 free_secdata(secdata);
2457 return rc;
2458out_bad_option:
2459 printk(KERN_WARNING "SELinux: unable to change security options "
2460 "during remount (dev %s, type=%s)\n", sb->s_id,
2461 sb->s_type->name);
2462 goto out_free_opts;
2463}
2464
James Morris12204e22008-12-19 10:44:42 +11002465static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466{
David Howells88e67f32008-11-14 10:39:21 +11002467 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002468 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 int rc;
2470
2471 rc = superblock_doinit(sb, data);
2472 if (rc)
2473 return rc;
2474
James Morris74192242008-12-19 11:41:10 +11002475 /* Allow all mounts performed by the kernel */
2476 if (flags & MS_KERNMOUNT)
2477 return 0;
2478
Eric Paris50c205f2012-04-04 15:01:43 -04002479 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002480 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002481 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482}
2483
David Howells726c3342006-06-23 02:02:58 -07002484static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485{
David Howells88e67f32008-11-14 10:39:21 +11002486 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002487 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
Eric Paris50c205f2012-04-04 15:01:43 -04002489 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002490 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002491 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492}
2493
Al Viro808d4e32012-10-11 11:42:01 -04002494static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002495 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002496 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002497 unsigned long flags,
2498 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499{
David Howells88e67f32008-11-14 10:39:21 +11002500 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501
2502 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002503 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002504 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 else
Eric Paris2875fa02011-04-28 16:04:24 -04002506 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507}
2508
2509static int selinux_umount(struct vfsmount *mnt, int flags)
2510{
David Howells88e67f32008-11-14 10:39:21 +11002511 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
David Howells88e67f32008-11-14 10:39:21 +11002513 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002514 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515}
2516
2517/* inode security operations */
2518
2519static int selinux_inode_alloc_security(struct inode *inode)
2520{
2521 return inode_alloc_security(inode);
2522}
2523
2524static void selinux_inode_free_security(struct inode *inode)
2525{
2526 inode_free_security(inode);
2527}
2528
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002529static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002530 const struct qstr *qstr, char **name,
2531 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002532{
Paul Moore5fb49872010-04-22 14:46:19 -04002533 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002534 struct inode_security_struct *dsec;
2535 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002536 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002537 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002538 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002539
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002540 dsec = dir->i_security;
2541 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002542
David Howells275bb412008-11-14 10:39:19 +11002543 sid = tsec->sid;
2544 newsid = tsec->create_sid;
2545
Eric Paris415103f2010-12-02 16:13:40 -05002546 if ((sbsec->flags & SE_SBINITIALIZED) &&
2547 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2548 newsid = sbsec->mntpoint_sid;
2549 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002550 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002551 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002552 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002553 if (rc) {
2554 printk(KERN_WARNING "%s: "
2555 "security_transition_sid failed, rc=%d (dev=%s "
2556 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002557 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002558 -rc, inode->i_sb->s_id, inode->i_ino);
2559 return rc;
2560 }
2561 }
2562
Eric Paris296fddf2006-09-25 23:32:00 -07002563 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002564 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002565 struct inode_security_struct *isec = inode->i_security;
2566 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2567 isec->sid = newsid;
2568 isec->initialized = 1;
2569 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002570
David P. Quigleycd895962009-01-16 09:22:04 -05002571 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002572 return -EOPNOTSUPP;
2573
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002574 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002575 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002576 if (!namep)
2577 return -ENOMEM;
2578 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002579 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002580
2581 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002582 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002583 if (rc) {
2584 kfree(namep);
2585 return rc;
2586 }
2587 *value = context;
2588 *len = clen;
2589 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002590
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002591 return 0;
2592}
2593
Al Viro4acdaf22011-07-26 01:42:34 -04002594static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595{
2596 return may_create(dir, dentry, SECCLASS_FILE);
2597}
2598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2600{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 return may_link(dir, old_dentry, MAY_LINK);
2602}
2603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2605{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 return may_link(dir, dentry, MAY_UNLINK);
2607}
2608
2609static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2610{
2611 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2612}
2613
Al Viro18bb1db2011-07-26 01:41:39 -04002614static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615{
2616 return may_create(dir, dentry, SECCLASS_DIR);
2617}
2618
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2620{
2621 return may_link(dir, dentry, MAY_RMDIR);
2622}
2623
Al Viro1a67aaf2011-07-26 01:52:52 -04002624static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2627}
2628
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002630 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
2632 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2633}
2634
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635static int selinux_inode_readlink(struct dentry *dentry)
2636{
David Howells88e67f32008-11-14 10:39:21 +11002637 const struct cred *cred = current_cred();
2638
Eric Paris2875fa02011-04-28 16:04:24 -04002639 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640}
2641
2642static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2643{
David Howells88e67f32008-11-14 10:39:21 +11002644 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
Eric Paris2875fa02011-04-28 16:04:24 -04002646 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647}
2648
Eric Parisd4cf970d2012-04-04 15:01:42 -04002649static noinline int audit_inode_permission(struct inode *inode,
2650 u32 perms, u32 audited, u32 denied,
2651 unsigned flags)
2652{
2653 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002654 struct inode_security_struct *isec = inode->i_security;
2655 int rc;
2656
Eric Paris50c205f2012-04-04 15:01:43 -04002657 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002658 ad.u.inode = inode;
2659
2660 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
2661 audited, denied, &ad, flags);
2662 if (rc)
2663 return rc;
2664 return 0;
2665}
2666
Al Viroe74f71e2011-06-20 19:38:15 -04002667static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668{
David Howells88e67f32008-11-14 10:39:21 +11002669 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002670 u32 perms;
2671 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002672 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002673 struct inode_security_struct *isec;
2674 u32 sid;
2675 struct av_decision avd;
2676 int rc, rc2;
2677 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678
Eric Parisb782e0a2010-07-23 11:44:03 -04002679 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002680 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2681
Eric Parisb782e0a2010-07-23 11:44:03 -04002682 /* No permission to check. Existence test. */
2683 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685
Eric Paris2e334052012-04-04 15:01:42 -04002686 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002687
Eric Paris2e334052012-04-04 15:01:42 -04002688 if (unlikely(IS_PRIVATE(inode)))
2689 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002690
2691 perms = file_mask_to_av(inode->i_mode, mask);
2692
Eric Paris2e334052012-04-04 15:01:42 -04002693 sid = cred_sid(cred);
2694 isec = inode->i_security;
2695
2696 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2697 audited = avc_audit_required(perms, &avd, rc,
2698 from_access ? FILE__AUDIT_ACCESS : 0,
2699 &denied);
2700 if (likely(!audited))
2701 return rc;
2702
Eric Parisd4cf970d2012-04-04 15:01:42 -04002703 rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002704 if (rc2)
2705 return rc2;
2706 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707}
2708
2709static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2710{
David Howells88e67f32008-11-14 10:39:21 +11002711 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002712 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002713 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002715 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2716 if (ia_valid & ATTR_FORCE) {
2717 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2718 ATTR_FORCE);
2719 if (!ia_valid)
2720 return 0;
2721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002723 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2724 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002725 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
Eric Paris3d2195c2012-07-06 14:13:30 -04002727 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002728 av |= FILE__OPEN;
2729
2730 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
2733static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2734{
David Howells88e67f32008-11-14 10:39:21 +11002735 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002736 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002737
Eric Paris2875fa02011-04-28 16:04:24 -04002738 path.dentry = dentry;
2739 path.mnt = mnt;
2740
2741 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742}
2743
David Howells8f0cfa52008-04-29 00:59:41 -07002744static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002745{
David Howells88e67f32008-11-14 10:39:21 +11002746 const struct cred *cred = current_cred();
2747
Serge E. Hallynb5376772007-10-16 23:31:36 -07002748 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2749 sizeof XATTR_SECURITY_PREFIX - 1)) {
2750 if (!strcmp(name, XATTR_NAME_CAPS)) {
2751 if (!capable(CAP_SETFCAP))
2752 return -EPERM;
2753 } else if (!capable(CAP_SYS_ADMIN)) {
2754 /* A different attribute in the security namespace.
2755 Restrict to administrator. */
2756 return -EPERM;
2757 }
2758 }
2759
2760 /* Not an attribute we recognize, so just check the
2761 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002762 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002763}
2764
David Howells8f0cfa52008-04-29 00:59:41 -07002765static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2766 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 struct inode *inode = dentry->d_inode;
2769 struct inode_security_struct *isec = inode->i_security;
2770 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002771 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002772 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 int rc = 0;
2774
Serge E. Hallynb5376772007-10-16 23:31:36 -07002775 if (strcmp(name, XATTR_NAME_SELINUX))
2776 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002779 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 return -EOPNOTSUPP;
2781
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002782 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 return -EPERM;
2784
Eric Paris50c205f2012-04-04 15:01:43 -04002785 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002786 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787
David Howells275bb412008-11-14 10:39:19 +11002788 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 FILE__RELABELFROM, &ad);
2790 if (rc)
2791 return rc;
2792
2793 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002794 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002795 if (!capable(CAP_MAC_ADMIN)) {
2796 struct audit_buffer *ab;
2797 size_t audit_size;
2798 const char *str;
2799
2800 /* We strip a nul only if it is at the end, otherwise the
2801 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002802 if (value) {
2803 str = value;
2804 if (str[size - 1] == '\0')
2805 audit_size = size - 1;
2806 else
2807 audit_size = size;
2808 } else {
2809 str = "";
2810 audit_size = 0;
2811 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002812 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2813 audit_log_format(ab, "op=setxattr invalid_context=");
2814 audit_log_n_untrustedstring(ab, value, audit_size);
2815 audit_log_end(ab);
2816
Stephen Smalley12b29f32008-05-07 13:03:20 -04002817 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002818 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002819 rc = security_context_to_sid_force(value, size, &newsid);
2820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 if (rc)
2822 return rc;
2823
David Howells275bb412008-11-14 10:39:19 +11002824 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 FILE__RELABELTO, &ad);
2826 if (rc)
2827 return rc;
2828
David Howells275bb412008-11-14 10:39:19 +11002829 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002830 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 if (rc)
2832 return rc;
2833
2834 return avc_has_perm(newsid,
2835 sbsec->sid,
2836 SECCLASS_FILESYSTEM,
2837 FILESYSTEM__ASSOCIATE,
2838 &ad);
2839}
2840
David Howells8f0cfa52008-04-29 00:59:41 -07002841static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002842 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002843 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
2845 struct inode *inode = dentry->d_inode;
2846 struct inode_security_struct *isec = inode->i_security;
2847 u32 newsid;
2848 int rc;
2849
2850 if (strcmp(name, XATTR_NAME_SELINUX)) {
2851 /* Not an attribute we recognize, so nothing to do. */
2852 return;
2853 }
2854
Stephen Smalley12b29f32008-05-07 13:03:20 -04002855 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002857 printk(KERN_ERR "SELinux: unable to map context to SID"
2858 "for (%s, %lu), rc=%d\n",
2859 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 return;
2861 }
2862
2863 isec->sid = newsid;
2864 return;
2865}
2866
David Howells8f0cfa52008-04-29 00:59:41 -07002867static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
David Howells88e67f32008-11-14 10:39:21 +11002869 const struct cred *cred = current_cred();
2870
Eric Paris2875fa02011-04-28 16:04:24 -04002871 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
Eric Paris828dfe12008-04-17 13:17:49 -04002874static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875{
David Howells88e67f32008-11-14 10:39:21 +11002876 const struct cred *cred = current_cred();
2877
Eric Paris2875fa02011-04-28 16:04:24 -04002878 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879}
2880
David Howells8f0cfa52008-04-29 00:59:41 -07002881static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002883 if (strcmp(name, XATTR_NAME_SELINUX))
2884 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885
2886 /* No one is allowed to remove a SELinux security label.
2887 You can change the label, but all data must be labeled. */
2888 return -EACCES;
2889}
2890
James Morrisd381d8a2005-10-30 14:59:22 -08002891/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002892 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002893 *
2894 * Permission check is handled by selinux_inode_getxattr hook.
2895 */
David P. Quigley42492592008-02-04 22:29:39 -08002896static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897{
David P. Quigley42492592008-02-04 22:29:39 -08002898 u32 size;
2899 int error;
2900 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002903 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2904 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002906 /*
2907 * If the caller has CAP_MAC_ADMIN, then get the raw context
2908 * value even if it is not defined by current policy; otherwise,
2909 * use the in-core value under current policy.
2910 * Use the non-auditing forms of the permission checks since
2911 * getxattr may be called by unprivileged processes commonly
2912 * and lack of permission just means that we fall back to the
2913 * in-core context value, not a denial.
2914 */
Eric Paris6a9de492012-01-03 12:25:14 -05002915 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002916 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002917 if (!error)
2918 error = security_sid_to_context_force(isec->sid, &context,
2919 &size);
2920 else
2921 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002922 if (error)
2923 return error;
2924 error = size;
2925 if (alloc) {
2926 *buffer = context;
2927 goto out_nofree;
2928 }
2929 kfree(context);
2930out_nofree:
2931 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932}
2933
2934static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002935 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936{
2937 struct inode_security_struct *isec = inode->i_security;
2938 u32 newsid;
2939 int rc;
2940
2941 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2942 return -EOPNOTSUPP;
2943
2944 if (!value || !size)
2945 return -EACCES;
2946
Eric Paris828dfe12008-04-17 13:17:49 -04002947 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 if (rc)
2949 return rc;
2950
2951 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04002952 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 return 0;
2954}
2955
2956static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2957{
2958 const int len = sizeof(XATTR_NAME_SELINUX);
2959 if (buffer && len <= buffer_size)
2960 memcpy(buffer, XATTR_NAME_SELINUX, len);
2961 return len;
2962}
2963
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02002964static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2965{
2966 struct inode_security_struct *isec = inode->i_security;
2967 *secid = isec->sid;
2968}
2969
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970/* file security operations */
2971
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002972static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973{
David Howells88e67f32008-11-14 10:39:21 +11002974 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05002975 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2978 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2979 mask |= MAY_APPEND;
2980
Paul Moore389fb8002009-03-27 17:10:34 -04002981 return file_has_perm(cred, file,
2982 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983}
2984
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002985static int selinux_file_permission(struct file *file, int mask)
2986{
Al Viro496ad9a2013-01-23 17:07:38 -05002987 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04002988 struct file_security_struct *fsec = file->f_security;
2989 struct inode_security_struct *isec = inode->i_security;
2990 u32 sid = current_sid();
2991
Paul Moore389fb8002009-03-27 17:10:34 -04002992 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002993 /* No permission to check. Existence test. */
2994 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002995
Stephen Smalley20dda182009-06-22 14:54:53 -04002996 if (sid == fsec->sid && fsec->isid == isec->sid &&
2997 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04002998 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04002999 return 0;
3000
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003001 return selinux_revalidate_file_permission(file, mask);
3002}
3003
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004static int selinux_file_alloc_security(struct file *file)
3005{
3006 return file_alloc_security(file);
3007}
3008
3009static void selinux_file_free_security(struct file *file)
3010{
3011 file_free_security(file);
3012}
3013
3014static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3015 unsigned long arg)
3016{
David Howells88e67f32008-11-14 10:39:21 +11003017 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003018 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
Eric Paris0b24dcb2011-02-25 15:39:20 -05003020 switch (cmd) {
3021 case FIONREAD:
3022 /* fall through */
3023 case FIBMAP:
3024 /* fall through */
3025 case FIGETBSZ:
3026 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003027 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003028 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003029 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003030 error = file_has_perm(cred, file, FILE__GETATTR);
3031 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Al Viro2f99c362012-03-23 16:04:05 -04003033 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003034 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003035 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003036 error = file_has_perm(cred, file, FILE__SETATTR);
3037 break;
3038
3039 /* sys_ioctl() checks */
3040 case FIONBIO:
3041 /* fall through */
3042 case FIOASYNC:
3043 error = file_has_perm(cred, file, 0);
3044 break;
3045
3046 case KDSKBENT:
3047 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003048 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3049 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003050 break;
3051
3052 /* default case assumes that the command will go
3053 * to the file's ioctl() function.
3054 */
3055 default:
3056 error = file_has_perm(cred, file, FILE__IOCTL);
3057 }
3058 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059}
3060
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003061static int default_noexec;
3062
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3064{
David Howells88e67f32008-11-14 10:39:21 +11003065 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003066 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003067
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003068 if (default_noexec &&
3069 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 /*
3071 * We are making executable an anonymous mapping or a
3072 * private file mapping that will also be writable.
3073 * This has an additional check.
3074 */
David Howellsd84f4f92008-11-14 10:39:23 +11003075 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003077 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
3080 if (file) {
3081 /* read access is always possible with a mapping */
3082 u32 av = FILE__READ;
3083
3084 /* write access only matters if the mapping is shared */
3085 if (shared && (prot & PROT_WRITE))
3086 av |= FILE__WRITE;
3087
3088 if (prot & PROT_EXEC)
3089 av |= FILE__EXECUTE;
3090
David Howells88e67f32008-11-14 10:39:21 +11003091 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 }
David Howellsd84f4f92008-11-14 10:39:23 +11003093
3094error:
3095 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096}
3097
Al Viroe5467852012-05-30 13:30:51 -04003098static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099{
Eric Parised032182007-06-28 15:55:21 -04003100 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003101 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
Eric Paris84336d1a2009-07-31 12:54:05 -04003103 /*
3104 * notice that we are intentionally putting the SELinux check before
3105 * the secondary cap_file_mmap check. This is such a likely attempt
3106 * at bad behaviour/exploit that we always want to get the AVC, even
3107 * if DAC would have also denied the operation.
3108 */
Eric Parisa2551df2009-07-31 12:54:11 -04003109 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003110 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3111 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003112 if (rc)
3113 return rc;
3114 }
3115
3116 /* do DAC check on address space usage */
Al Viroe5467852012-05-30 13:30:51 -04003117 return cap_mmap_addr(addr);
3118}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Al Viroe5467852012-05-30 13:30:51 -04003120static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3121 unsigned long prot, unsigned long flags)
3122{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 if (selinux_checkreqprot)
3124 prot = reqprot;
3125
3126 return file_map_prot_check(file, prot,
3127 (flags & MAP_TYPE) == MAP_SHARED);
3128}
3129
3130static int selinux_file_mprotect(struct vm_area_struct *vma,
3131 unsigned long reqprot,
3132 unsigned long prot)
3133{
David Howells88e67f32008-11-14 10:39:21 +11003134 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135
3136 if (selinux_checkreqprot)
3137 prot = reqprot;
3138
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003139 if (default_noexec &&
3140 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003141 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003142 if (vma->vm_start >= vma->vm_mm->start_brk &&
3143 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003144 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003145 } else if (!vma->vm_file &&
3146 vma->vm_start <= vma->vm_mm->start_stack &&
3147 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003148 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003149 } else if (vma->vm_file && vma->anon_vma) {
3150 /*
3151 * We are making executable a file mapping that has
3152 * had some COW done. Since pages might have been
3153 * written, check ability to execute the possibly
3154 * modified content. This typically should only
3155 * occur for text relocations.
3156 */
David Howellsd84f4f92008-11-14 10:39:23 +11003157 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003158 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003159 if (rc)
3160 return rc;
3161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3164}
3165
3166static int selinux_file_lock(struct file *file, unsigned int cmd)
3167{
David Howells88e67f32008-11-14 10:39:21 +11003168 const struct cred *cred = current_cred();
3169
3170 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171}
3172
3173static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3174 unsigned long arg)
3175{
David Howells88e67f32008-11-14 10:39:21 +11003176 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 int err = 0;
3178
3179 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003180 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003181 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003182 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003184 }
3185 /* fall through */
3186 case F_SETOWN:
3187 case F_SETSIG:
3188 case F_GETFL:
3189 case F_GETOWN:
3190 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003191 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003192 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003193 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003194 break;
3195 case F_GETLK:
3196 case F_SETLK:
3197 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003199 case F_GETLK64:
3200 case F_SETLK64:
3201 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202#endif
David Howells88e67f32008-11-14 10:39:21 +11003203 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003204 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 }
3206
3207 return err;
3208}
3209
3210static int selinux_file_set_fowner(struct file *file)
3211{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 struct file_security_struct *fsec;
3213
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003215 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216
3217 return 0;
3218}
3219
3220static int selinux_file_send_sigiotask(struct task_struct *tsk,
3221 struct fown_struct *fown, int signum)
3222{
Eric Paris828dfe12008-04-17 13:17:49 -04003223 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003224 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 struct file_security_struct *fsec;
3227
3228 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003229 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 fsec = file->f_security;
3232
3233 if (!signum)
3234 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3235 else
3236 perm = signal_to_av(signum);
3237
David Howells275bb412008-11-14 10:39:19 +11003238 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 SECCLASS_PROCESS, perm, NULL);
3240}
3241
3242static int selinux_file_receive(struct file *file)
3243{
David Howells88e67f32008-11-14 10:39:21 +11003244 const struct cred *cred = current_cred();
3245
3246 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247}
3248
Eric Paris83d49852012-04-04 13:45:40 -04003249static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003250{
3251 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003252 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003253
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003254 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003255 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003256 /*
3257 * Save inode label and policy sequence number
3258 * at open-time so that selinux_file_permission
3259 * can determine whether revalidation is necessary.
3260 * Task label is already saved in the file security
3261 * struct as its SID.
3262 */
3263 fsec->isid = isec->sid;
3264 fsec->pseqno = avc_policy_seqno();
3265 /*
3266 * Since the inode label or policy seqno may have changed
3267 * between the selinux_inode_permission check and the saving
3268 * of state above, recheck that access is still permitted.
3269 * Otherwise, access might never be revalidated against the
3270 * new inode label or new policy.
3271 * This check is not redundant - do not remove.
3272 */
Eric Paris602a8dd2012-04-04 15:01:42 -04003273 return path_has_perm(cred, &file->f_path, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003274}
3275
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276/* task security operations */
3277
3278static int selinux_task_create(unsigned long clone_flags)
3279{
David Howells3b11a1d2008-11-14 10:39:26 +11003280 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281}
3282
David Howellsf1752ee2008-11-14 10:39:17 +11003283/*
David Howellsee18d642009-09-02 09:14:21 +01003284 * allocate the SELinux part of blank credentials
3285 */
3286static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3287{
3288 struct task_security_struct *tsec;
3289
3290 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3291 if (!tsec)
3292 return -ENOMEM;
3293
3294 cred->security = tsec;
3295 return 0;
3296}
3297
3298/*
David Howellsf1752ee2008-11-14 10:39:17 +11003299 * detach and free the LSM part of a set of credentials
3300 */
3301static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302{
David Howellsf1752ee2008-11-14 10:39:17 +11003303 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003304
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003305 /*
3306 * cred->security == NULL if security_cred_alloc_blank() or
3307 * security_prepare_creds() returned an error.
3308 */
3309 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003310 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003311 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312}
3313
David Howellsd84f4f92008-11-14 10:39:23 +11003314/*
3315 * prepare a new set of credentials for modification
3316 */
3317static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3318 gfp_t gfp)
3319{
3320 const struct task_security_struct *old_tsec;
3321 struct task_security_struct *tsec;
3322
3323 old_tsec = old->security;
3324
3325 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3326 if (!tsec)
3327 return -ENOMEM;
3328
3329 new->security = tsec;
3330 return 0;
3331}
3332
3333/*
David Howellsee18d642009-09-02 09:14:21 +01003334 * transfer the SELinux data to a blank set of creds
3335 */
3336static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3337{
3338 const struct task_security_struct *old_tsec = old->security;
3339 struct task_security_struct *tsec = new->security;
3340
3341 *tsec = *old_tsec;
3342}
3343
3344/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003345 * set the security data for a kernel service
3346 * - all the creation contexts are set to unlabelled
3347 */
3348static int selinux_kernel_act_as(struct cred *new, u32 secid)
3349{
3350 struct task_security_struct *tsec = new->security;
3351 u32 sid = current_sid();
3352 int ret;
3353
3354 ret = avc_has_perm(sid, secid,
3355 SECCLASS_KERNEL_SERVICE,
3356 KERNEL_SERVICE__USE_AS_OVERRIDE,
3357 NULL);
3358 if (ret == 0) {
3359 tsec->sid = secid;
3360 tsec->create_sid = 0;
3361 tsec->keycreate_sid = 0;
3362 tsec->sockcreate_sid = 0;
3363 }
3364 return ret;
3365}
3366
3367/*
3368 * set the file creation context in a security record to the same as the
3369 * objective context of the specified inode
3370 */
3371static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3372{
3373 struct inode_security_struct *isec = inode->i_security;
3374 struct task_security_struct *tsec = new->security;
3375 u32 sid = current_sid();
3376 int ret;
3377
3378 ret = avc_has_perm(sid, isec->sid,
3379 SECCLASS_KERNEL_SERVICE,
3380 KERNEL_SERVICE__CREATE_FILES_AS,
3381 NULL);
3382
3383 if (ret == 0)
3384 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003385 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003386}
3387
Eric Parisdd8dbf22009-11-03 16:35:32 +11003388static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003389{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003390 u32 sid;
3391 struct common_audit_data ad;
3392
3393 sid = task_sid(current);
3394
Eric Paris50c205f2012-04-04 15:01:43 -04003395 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003396 ad.u.kmod_name = kmod_name;
3397
3398 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3399 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003400}
3401
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3403{
David Howells3b11a1d2008-11-14 10:39:26 +11003404 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405}
3406
3407static int selinux_task_getpgid(struct task_struct *p)
3408{
David Howells3b11a1d2008-11-14 10:39:26 +11003409 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410}
3411
3412static int selinux_task_getsid(struct task_struct *p)
3413{
David Howells3b11a1d2008-11-14 10:39:26 +11003414 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415}
3416
David Quigleyf9008e42006-06-30 01:55:46 -07003417static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3418{
David Howells275bb412008-11-14 10:39:19 +11003419 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003420}
3421
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422static int selinux_task_setnice(struct task_struct *p, int nice)
3423{
3424 int rc;
3425
Eric Paris200ac532009-02-12 15:01:04 -05003426 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 if (rc)
3428 return rc;
3429
David Howells3b11a1d2008-11-14 10:39:26 +11003430 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431}
3432
James Morris03e68062006-06-23 02:03:58 -07003433static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3434{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003435 int rc;
3436
Eric Paris200ac532009-02-12 15:01:04 -05003437 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003438 if (rc)
3439 return rc;
3440
David Howells3b11a1d2008-11-14 10:39:26 +11003441 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003442}
3443
David Quigleya1836a42006-06-30 01:55:49 -07003444static int selinux_task_getioprio(struct task_struct *p)
3445{
David Howells3b11a1d2008-11-14 10:39:26 +11003446 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003447}
3448
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003449static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3450 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003452 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
3454 /* Control the ability to change the hard limit (whether
3455 lowering or raising it), so that the hard limit can
3456 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003457 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003459 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
3461 return 0;
3462}
3463
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003464static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003466 int rc;
3467
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003468 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003469 if (rc)
3470 return rc;
3471
David Howells3b11a1d2008-11-14 10:39:26 +11003472 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473}
3474
3475static int selinux_task_getscheduler(struct task_struct *p)
3476{
David Howells3b11a1d2008-11-14 10:39:26 +11003477 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478}
3479
David Quigley35601542006-06-23 02:04:01 -07003480static int selinux_task_movememory(struct task_struct *p)
3481{
David Howells3b11a1d2008-11-14 10:39:26 +11003482 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003483}
3484
David Quigleyf9008e42006-06-30 01:55:46 -07003485static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3486 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487{
3488 u32 perm;
3489 int rc;
3490
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491 if (!sig)
3492 perm = PROCESS__SIGNULL; /* null signal; existence test */
3493 else
3494 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003495 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003496 rc = avc_has_perm(secid, task_sid(p),
3497 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003498 else
David Howells3b11a1d2008-11-14 10:39:26 +11003499 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003500 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501}
3502
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503static int selinux_task_wait(struct task_struct *p)
3504{
Eric Paris8a535142007-10-22 16:10:31 -04003505 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508static void selinux_task_to_inode(struct task_struct *p,
3509 struct inode *inode)
3510{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003512 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
David Howells275bb412008-11-14 10:39:19 +11003514 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516}
3517
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003519static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003520 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521{
3522 int offset, ihlen, ret = -EINVAL;
3523 struct iphdr _iph, *ih;
3524
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003525 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3527 if (ih == NULL)
3528 goto out;
3529
3530 ihlen = ih->ihl * 4;
3531 if (ihlen < sizeof(_iph))
3532 goto out;
3533
Eric Paris48c62af2012-04-02 13:15:44 -04003534 ad->u.net->v4info.saddr = ih->saddr;
3535 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 ret = 0;
3537
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003538 if (proto)
3539 *proto = ih->protocol;
3540
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003542 case IPPROTO_TCP: {
3543 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
Eric Paris828dfe12008-04-17 13:17:49 -04003545 if (ntohs(ih->frag_off) & IP_OFFSET)
3546 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547
3548 offset += ihlen;
3549 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3550 if (th == NULL)
3551 break;
3552
Eric Paris48c62af2012-04-02 13:15:44 -04003553 ad->u.net->sport = th->source;
3554 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557
Eric Paris828dfe12008-04-17 13:17:49 -04003558 case IPPROTO_UDP: {
3559 struct udphdr _udph, *uh;
3560
3561 if (ntohs(ih->frag_off) & IP_OFFSET)
3562 break;
3563
3564 offset += ihlen;
3565 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3566 if (uh == NULL)
3567 break;
3568
Eric Paris48c62af2012-04-02 13:15:44 -04003569 ad->u.net->sport = uh->source;
3570 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003571 break;
3572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573
James Morris2ee92d42006-11-13 16:09:01 -08003574 case IPPROTO_DCCP: {
3575 struct dccp_hdr _dccph, *dh;
3576
3577 if (ntohs(ih->frag_off) & IP_OFFSET)
3578 break;
3579
3580 offset += ihlen;
3581 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3582 if (dh == NULL)
3583 break;
3584
Eric Paris48c62af2012-04-02 13:15:44 -04003585 ad->u.net->sport = dh->dccph_sport;
3586 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003587 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003588 }
James Morris2ee92d42006-11-13 16:09:01 -08003589
Eric Paris828dfe12008-04-17 13:17:49 -04003590 default:
3591 break;
3592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593out:
3594 return ret;
3595}
3596
3597#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3598
3599/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003600static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003601 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602{
3603 u8 nexthdr;
3604 int ret = -EINVAL, offset;
3605 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003606 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003608 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3610 if (ip6 == NULL)
3611 goto out;
3612
Eric Paris48c62af2012-04-02 13:15:44 -04003613 ad->u.net->v6info.saddr = ip6->saddr;
3614 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 ret = 0;
3616
3617 nexthdr = ip6->nexthdr;
3618 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003619 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 if (offset < 0)
3621 goto out;
3622
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003623 if (proto)
3624 *proto = nexthdr;
3625
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 switch (nexthdr) {
3627 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003628 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
3630 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3631 if (th == NULL)
3632 break;
3633
Eric Paris48c62af2012-04-02 13:15:44 -04003634 ad->u.net->sport = th->source;
3635 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 break;
3637 }
3638
3639 case IPPROTO_UDP: {
3640 struct udphdr _udph, *uh;
3641
3642 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3643 if (uh == NULL)
3644 break;
3645
Eric Paris48c62af2012-04-02 13:15:44 -04003646 ad->u.net->sport = uh->source;
3647 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 break;
3649 }
3650
James Morris2ee92d42006-11-13 16:09:01 -08003651 case IPPROTO_DCCP: {
3652 struct dccp_hdr _dccph, *dh;
3653
3654 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3655 if (dh == NULL)
3656 break;
3657
Eric Paris48c62af2012-04-02 13:15:44 -04003658 ad->u.net->sport = dh->dccph_sport;
3659 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003660 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003661 }
James Morris2ee92d42006-11-13 16:09:01 -08003662
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663 /* includes fragments */
3664 default:
3665 break;
3666 }
3667out:
3668 return ret;
3669}
3670
3671#endif /* IPV6 */
3672
Thomas Liu2bf49692009-07-14 12:14:09 -04003673static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003674 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675{
David Howellscf9481e2008-07-27 21:31:07 +10003676 char *addrp;
3677 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Eric Paris48c62af2012-04-02 13:15:44 -04003679 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003681 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003682 if (ret)
3683 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003684 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3685 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003686 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
3688#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3689 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003690 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003691 if (ret)
3692 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003693 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3694 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003695 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696#endif /* IPV6 */
3697 default:
David Howellscf9481e2008-07-27 21:31:07 +10003698 addrp = NULL;
3699 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 }
3701
David Howellscf9481e2008-07-27 21:31:07 +10003702parse_error:
3703 printk(KERN_WARNING
3704 "SELinux: failure in selinux_parse_skb(),"
3705 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003707
3708okay:
3709 if (_addrp)
3710 *_addrp = addrp;
3711 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712}
3713
Paul Moore4f6a9932007-03-01 14:35:22 -05003714/**
Paul Moore220deb92008-01-29 08:38:23 -05003715 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003716 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003717 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003718 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003719 *
3720 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003721 * Check the various different forms of network peer labeling and determine
3722 * the peer label/SID for the packet; most of the magic actually occurs in
3723 * the security server function security_net_peersid_cmp(). The function
3724 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3725 * or -EACCES if @sid is invalid due to inconsistencies with the different
3726 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003727 *
3728 */
Paul Moore220deb92008-01-29 08:38:23 -05003729static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003730{
Paul Moore71f1cb02008-01-29 08:51:16 -05003731 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003732 u32 xfrm_sid;
3733 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003734 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003735
Paul Moorebed4d7e2013-07-23 17:38:40 -04003736 err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
3737 if (unlikely(err))
3738 return -EACCES;
3739 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3740 if (unlikely(err))
3741 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003742
Paul Moore71f1cb02008-01-29 08:51:16 -05003743 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3744 if (unlikely(err)) {
3745 printk(KERN_WARNING
3746 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3747 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003748 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003749 }
Paul Moore220deb92008-01-29 08:38:23 -05003750
3751 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003752}
3753
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003755
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003756static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3757 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003758{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003759 if (tsec->sockcreate_sid > SECSID_NULL) {
3760 *socksid = tsec->sockcreate_sid;
3761 return 0;
3762 }
3763
3764 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3765 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003766}
3767
Paul Moore253bfae2010-04-22 14:46:19 -04003768static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769{
Paul Moore253bfae2010-04-22 14:46:19 -04003770 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003771 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003772 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003773 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
Paul Moore253bfae2010-04-22 14:46:19 -04003775 if (sksec->sid == SECINITSID_KERNEL)
3776 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Eric Paris50c205f2012-04-04 15:01:43 -04003778 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003779 ad.u.net = &net;
3780 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781
Paul Moore253bfae2010-04-22 14:46:19 -04003782 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783}
3784
3785static int selinux_socket_create(int family, int type,
3786 int protocol, int kern)
3787{
Paul Moore5fb49872010-04-22 14:46:19 -04003788 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003789 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003790 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003791 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
3793 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003794 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
David Howells275bb412008-11-14 10:39:19 +11003796 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003797 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3798 if (rc)
3799 return rc;
3800
Paul Moored4f2d972010-04-22 14:46:18 -04003801 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802}
3803
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003804static int selinux_socket_post_create(struct socket *sock, int family,
3805 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806{
Paul Moore5fb49872010-04-22 14:46:19 -04003807 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003808 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003809 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003810 int err = 0;
3811
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003812 isec->sclass = socket_type_to_security_class(family, type, protocol);
3813
David Howells275bb412008-11-14 10:39:19 +11003814 if (kern)
3815 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003816 else {
3817 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3818 if (err)
3819 return err;
3820 }
David Howells275bb412008-11-14 10:39:19 +11003821
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 isec->initialized = 1;
3823
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003824 if (sock->sk) {
3825 sksec = sock->sk->sk_security;
3826 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003827 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04003828 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003829 }
3830
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003831 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832}
3833
3834/* Range of port numbers used to automatically bind.
3835 Need to determine whether we should perform a name_bind
3836 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
3838static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3839{
Paul Moore253bfae2010-04-22 14:46:19 -04003840 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 u16 family;
3842 int err;
3843
Paul Moore253bfae2010-04-22 14:46:19 -04003844 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 if (err)
3846 goto out;
3847
3848 /*
3849 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003850 * Multiple address binding for SCTP is not supported yet: we just
3851 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 */
Paul Moore253bfae2010-04-22 14:46:19 -04003853 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 if (family == PF_INET || family == PF_INET6) {
3855 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04003856 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003857 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003858 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 struct sockaddr_in *addr4 = NULL;
3860 struct sockaddr_in6 *addr6 = NULL;
3861 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10003862 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 if (family == PF_INET) {
3865 addr4 = (struct sockaddr_in *)address;
3866 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 addrp = (char *)&addr4->sin_addr.s_addr;
3868 } else {
3869 addr6 = (struct sockaddr_in6 *)address;
3870 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 addrp = (char *)&addr6->sin6_addr.s6_addr;
3872 }
3873
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003874 if (snum) {
3875 int low, high;
3876
3877 inet_get_local_port_range(&low, &high);
3878
3879 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003880 err = sel_netport_sid(sk->sk_protocol,
3881 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003882 if (err)
3883 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04003884 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003885 ad.u.net = &net;
3886 ad.u.net->sport = htons(snum);
3887 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04003888 err = avc_has_perm(sksec->sid, sid,
3889 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003890 SOCKET__NAME_BIND, &ad);
3891 if (err)
3892 goto out;
3893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 }
Eric Paris828dfe12008-04-17 13:17:49 -04003895
Paul Moore253bfae2010-04-22 14:46:19 -04003896 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003897 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 node_perm = TCP_SOCKET__NODE_BIND;
3899 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003900
James Morris13402582005-09-30 14:24:34 -04003901 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 node_perm = UDP_SOCKET__NODE_BIND;
3903 break;
James Morris2ee92d42006-11-13 16:09:01 -08003904
3905 case SECCLASS_DCCP_SOCKET:
3906 node_perm = DCCP_SOCKET__NODE_BIND;
3907 break;
3908
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 default:
3910 node_perm = RAWIP_SOCKET__NODE_BIND;
3911 break;
3912 }
Eric Paris828dfe12008-04-17 13:17:49 -04003913
Paul Moore224dfbd2008-01-29 08:38:13 -05003914 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 if (err)
3916 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003917
Eric Paris50c205f2012-04-04 15:01:43 -04003918 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003919 ad.u.net = &net;
3920 ad.u.net->sport = htons(snum);
3921 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04003924 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 else
Eric Paris48c62af2012-04-02 13:15:44 -04003926 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
Paul Moore253bfae2010-04-22 14:46:19 -04003928 err = avc_has_perm(sksec->sid, sid,
3929 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 if (err)
3931 goto out;
3932 }
3933out:
3934 return err;
3935}
3936
3937static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3938{
Paul Moore014ab192008-10-10 10:16:33 -04003939 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04003940 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 int err;
3942
Paul Moore253bfae2010-04-22 14:46:19 -04003943 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 if (err)
3945 return err;
3946
3947 /*
James Morris2ee92d42006-11-13 16:09:01 -08003948 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 */
Paul Moore253bfae2010-04-22 14:46:19 -04003950 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3951 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04003952 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003953 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 struct sockaddr_in *addr4 = NULL;
3955 struct sockaddr_in6 *addr6 = NULL;
3956 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003957 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
3959 if (sk->sk_family == PF_INET) {
3960 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003961 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 return -EINVAL;
3963 snum = ntohs(addr4->sin_port);
3964 } else {
3965 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003966 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 return -EINVAL;
3968 snum = ntohs(addr6->sin6_port);
3969 }
3970
Paul Moore3e112172008-04-10 10:48:14 -04003971 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 if (err)
3973 goto out;
3974
Paul Moore253bfae2010-04-22 14:46:19 -04003975 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08003976 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3977
Eric Paris50c205f2012-04-04 15:01:43 -04003978 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003979 ad.u.net = &net;
3980 ad.u.net->dport = htons(snum);
3981 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04003982 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 if (err)
3984 goto out;
3985 }
3986
Paul Moore014ab192008-10-10 10:16:33 -04003987 err = selinux_netlbl_socket_connect(sk, address);
3988
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989out:
3990 return err;
3991}
3992
3993static int selinux_socket_listen(struct socket *sock, int backlog)
3994{
Paul Moore253bfae2010-04-22 14:46:19 -04003995 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996}
3997
3998static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3999{
4000 int err;
4001 struct inode_security_struct *isec;
4002 struct inode_security_struct *newisec;
4003
Paul Moore253bfae2010-04-22 14:46:19 -04004004 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 if (err)
4006 return err;
4007
4008 newisec = SOCK_INODE(newsock)->i_security;
4009
4010 isec = SOCK_INODE(sock)->i_security;
4011 newisec->sclass = isec->sclass;
4012 newisec->sid = isec->sid;
4013 newisec->initialized = 1;
4014
4015 return 0;
4016}
4017
4018static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004019 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020{
Paul Moore253bfae2010-04-22 14:46:19 -04004021 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022}
4023
4024static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4025 int size, int flags)
4026{
Paul Moore253bfae2010-04-22 14:46:19 -04004027 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028}
4029
4030static int selinux_socket_getsockname(struct socket *sock)
4031{
Paul Moore253bfae2010-04-22 14:46:19 -04004032 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033}
4034
4035static int selinux_socket_getpeername(struct socket *sock)
4036{
Paul Moore253bfae2010-04-22 14:46:19 -04004037 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038}
4039
Eric Paris828dfe12008-04-17 13:17:49 -04004040static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041{
Paul Mooref8687af2006-10-30 15:22:15 -08004042 int err;
4043
Paul Moore253bfae2010-04-22 14:46:19 -04004044 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004045 if (err)
4046 return err;
4047
4048 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049}
4050
4051static int selinux_socket_getsockopt(struct socket *sock, int level,
4052 int optname)
4053{
Paul Moore253bfae2010-04-22 14:46:19 -04004054 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
4057static int selinux_socket_shutdown(struct socket *sock, int how)
4058{
Paul Moore253bfae2010-04-22 14:46:19 -04004059 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060}
4061
David S. Miller3610cda2011-01-05 15:38:53 -08004062static int selinux_socket_unix_stream_connect(struct sock *sock,
4063 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 struct sock *newsk)
4065{
David S. Miller3610cda2011-01-05 15:38:53 -08004066 struct sk_security_struct *sksec_sock = sock->sk_security;
4067 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004068 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004069 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004070 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 int err;
4072
Eric Paris50c205f2012-04-04 15:01:43 -04004073 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004074 ad.u.net = &net;
4075 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076
Paul Moore4d1e2452010-04-22 14:46:18 -04004077 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4078 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4080 if (err)
4081 return err;
4082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004084 sksec_new->peer_sid = sksec_sock->sid;
4085 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4086 &sksec_new->sid);
4087 if (err)
4088 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004089
Paul Moore4d1e2452010-04-22 14:46:18 -04004090 /* connecting socket */
4091 sksec_sock->peer_sid = sksec_new->sid;
4092
4093 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094}
4095
4096static int selinux_socket_unix_may_send(struct socket *sock,
4097 struct socket *other)
4098{
Paul Moore253bfae2010-04-22 14:46:19 -04004099 struct sk_security_struct *ssec = sock->sk->sk_security;
4100 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004101 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004102 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Eric Paris50c205f2012-04-04 15:01:43 -04004104 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004105 ad.u.net = &net;
4106 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Paul Moore253bfae2010-04-22 14:46:19 -04004108 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4109 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110}
4111
Paul Mooreeffad8d2008-01-29 08:49:27 -05004112static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4113 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004114 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004115{
4116 int err;
4117 u32 if_sid;
4118 u32 node_sid;
4119
4120 err = sel_netif_sid(ifindex, &if_sid);
4121 if (err)
4122 return err;
4123 err = avc_has_perm(peer_sid, if_sid,
4124 SECCLASS_NETIF, NETIF__INGRESS, ad);
4125 if (err)
4126 return err;
4127
4128 err = sel_netnode_sid(addrp, family, &node_sid);
4129 if (err)
4130 return err;
4131 return avc_has_perm(peer_sid, node_sid,
4132 SECCLASS_NODE, NODE__RECVFROM, ad);
4133}
4134
Paul Moore220deb92008-01-29 08:38:23 -05004135static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004136 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004137{
Paul Moore277d3422008-12-31 12:54:11 -05004138 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004139 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004140 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004141 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004142 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004143 char *addrp;
4144
Eric Paris50c205f2012-04-04 15:01:43 -04004145 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004146 ad.u.net = &net;
4147 ad.u.net->netif = skb->skb_iif;
4148 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004149 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4150 if (err)
4151 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004152
Paul Moore58bfbb52009-03-27 17:10:41 -04004153 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004154 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004155 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004156 if (err)
4157 return err;
4158 }
Paul Moore220deb92008-01-29 08:38:23 -05004159
Steffen Klassertb9679a72011-02-23 12:55:21 +01004160 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4161 if (err)
4162 return err;
4163 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004164
James Morris4e5ab4c2006-06-09 00:33:33 -07004165 return err;
4166}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004167
James Morris4e5ab4c2006-06-09 00:33:33 -07004168static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4169{
Paul Moore220deb92008-01-29 08:38:23 -05004170 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004171 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004172 u16 family = sk->sk_family;
4173 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004174 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004175 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004176 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004177 u8 secmark_active;
4178 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004179
James Morris4e5ab4c2006-06-09 00:33:33 -07004180 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004181 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004182
4183 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004184 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004185 family = PF_INET;
4186
Paul Moored8395c82008-10-10 10:16:30 -04004187 /* If any sort of compatibility mode is enabled then handoff processing
4188 * to the selinux_sock_rcv_skb_compat() function to deal with the
4189 * special handling. We do this in an attempt to keep this function
4190 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004191 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004192 return selinux_sock_rcv_skb_compat(sk, skb, family);
4193
4194 secmark_active = selinux_secmark_enabled();
4195 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4196 if (!secmark_active && !peerlbl_active)
4197 return 0;
4198
Eric Paris50c205f2012-04-04 15:01:43 -04004199 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004200 ad.u.net = &net;
4201 ad.u.net->netif = skb->skb_iif;
4202 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004203 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004204 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004205 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004206
Paul Moored8395c82008-10-10 10:16:30 -04004207 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004208 u32 peer_sid;
4209
4210 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4211 if (err)
4212 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004213 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004214 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004215 if (err) {
4216 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004217 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004218 }
Paul Moored621d352008-01-29 08:43:36 -05004219 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4220 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004221 if (err)
4222 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004223 }
4224
Paul Moored8395c82008-10-10 10:16:30 -04004225 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004226 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4227 PACKET__RECV, &ad);
4228 if (err)
4229 return err;
4230 }
4231
Paul Moored621d352008-01-29 08:43:36 -05004232 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233}
4234
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004235static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4236 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237{
4238 int err = 0;
4239 char *scontext;
4240 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004241 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004242 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243
Paul Moore253bfae2010-04-22 14:46:19 -04004244 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4245 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004246 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004247 if (peer_sid == SECSID_NULL)
4248 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004250 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004252 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
4254 if (scontext_len > len) {
4255 err = -ERANGE;
4256 goto out_len;
4257 }
4258
4259 if (copy_to_user(optval, scontext, scontext_len))
4260 err = -EFAULT;
4261
4262out_len:
4263 if (put_user(scontext_len, optlen))
4264 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 return err;
4267}
4268
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004269static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004270{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004271 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004272 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004273
Paul Mooreaa862902008-10-10 10:16:29 -04004274 if (skb && skb->protocol == htons(ETH_P_IP))
4275 family = PF_INET;
4276 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4277 family = PF_INET6;
4278 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004279 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004280 else
4281 goto out;
4282
4283 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004284 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004285 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004286 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004287
Paul Moore75e22912008-01-29 08:38:04 -05004288out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004289 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004290 if (peer_secid == SECSID_NULL)
4291 return -EINVAL;
4292 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004293}
4294
Al Viro7d877f32005-10-21 03:20:43 -04004295static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296{
Paul Moore84914b72010-04-22 14:46:18 -04004297 struct sk_security_struct *sksec;
4298
4299 sksec = kzalloc(sizeof(*sksec), priority);
4300 if (!sksec)
4301 return -ENOMEM;
4302
4303 sksec->peer_sid = SECINITSID_UNLABELED;
4304 sksec->sid = SECINITSID_UNLABELED;
4305 selinux_netlbl_sk_security_reset(sksec);
4306 sk->sk_security = sksec;
4307
4308 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309}
4310
4311static void selinux_sk_free_security(struct sock *sk)
4312{
Paul Moore84914b72010-04-22 14:46:18 -04004313 struct sk_security_struct *sksec = sk->sk_security;
4314
4315 sk->sk_security = NULL;
4316 selinux_netlbl_sk_security_free(sksec);
4317 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318}
4319
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004320static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4321{
Eric Parisdd3e7832010-04-07 15:08:46 -04004322 struct sk_security_struct *sksec = sk->sk_security;
4323 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004324
Eric Parisdd3e7832010-04-07 15:08:46 -04004325 newsksec->sid = sksec->sid;
4326 newsksec->peer_sid = sksec->peer_sid;
4327 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004328
Eric Parisdd3e7832010-04-07 15:08:46 -04004329 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004330}
4331
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004332static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004333{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004334 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004335 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004336 else {
4337 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004338
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004339 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004340 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004341}
4342
Eric Paris828dfe12008-04-17 13:17:49 -04004343static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004344{
4345 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4346 struct sk_security_struct *sksec = sk->sk_security;
4347
David Woodhouse2148ccc2006-09-29 15:50:25 -07004348 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4349 sk->sk_family == PF_UNIX)
4350 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004351 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004352}
4353
Adrian Bunk9a673e52006-08-15 00:03:53 -07004354static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4355 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004356{
4357 struct sk_security_struct *sksec = sk->sk_security;
4358 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004359 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004360 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004361 u32 peersid;
4362
Paul Mooreaa862902008-10-10 10:16:29 -04004363 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4364 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4365 family = PF_INET;
4366
4367 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004368 if (err)
4369 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004370 if (peersid == SECSID_NULL) {
4371 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004372 req->peer_secid = SECSID_NULL;
Paul Moore389fb8002009-03-27 17:10:34 -04004373 } else {
4374 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4375 if (err)
4376 return err;
4377 req->secid = newsid;
4378 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004379 }
4380
Paul Moore389fb8002009-03-27 17:10:34 -04004381 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004382}
4383
Adrian Bunk9a673e52006-08-15 00:03:53 -07004384static void selinux_inet_csk_clone(struct sock *newsk,
4385 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004386{
4387 struct sk_security_struct *newsksec = newsk->sk_security;
4388
4389 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004390 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004391 /* NOTE: Ideally, we should also get the isec->sid for the
4392 new socket in sync, but we don't have the isec available yet.
4393 So we will wait until sock_graft to do it, by which
4394 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004395
Paul Moore9f2ad662006-11-17 17:38:53 -05004396 /* We don't need to take any sort of lock here as we are the only
4397 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004398 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004399}
4400
Paul Moore014ab192008-10-10 10:16:33 -04004401static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004402{
Paul Mooreaa862902008-10-10 10:16:29 -04004403 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004404 struct sk_security_struct *sksec = sk->sk_security;
4405
Paul Mooreaa862902008-10-10 10:16:29 -04004406 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4407 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4408 family = PF_INET;
4409
4410 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004411}
4412
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004413static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4414{
4415 skb_set_owner_w(skb, sk);
4416}
4417
Eric Paris2606fd12010-10-13 16:24:41 -04004418static int selinux_secmark_relabel_packet(u32 sid)
4419{
4420 const struct task_security_struct *__tsec;
4421 u32 tsid;
4422
4423 __tsec = current_security();
4424 tsid = __tsec->sid;
4425
4426 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4427}
4428
4429static void selinux_secmark_refcount_inc(void)
4430{
4431 atomic_inc(&selinux_secmark_refcount);
4432}
4433
4434static void selinux_secmark_refcount_dec(void)
4435{
4436 atomic_dec(&selinux_secmark_refcount);
4437}
4438
Adrian Bunk9a673e52006-08-15 00:03:53 -07004439static void selinux_req_classify_flow(const struct request_sock *req,
4440 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004441{
David S. Miller1d28f422011-03-12 00:29:39 -05004442 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004443}
4444
Paul Moore5dbbaf22013-01-14 07:12:19 +00004445static int selinux_tun_dev_alloc_security(void **security)
4446{
4447 struct tun_security_struct *tunsec;
4448
4449 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4450 if (!tunsec)
4451 return -ENOMEM;
4452 tunsec->sid = current_sid();
4453
4454 *security = tunsec;
4455 return 0;
4456}
4457
4458static void selinux_tun_dev_free_security(void *security)
4459{
4460 kfree(security);
4461}
4462
Paul Mooreed6d76e2009-08-28 18:12:49 -04004463static int selinux_tun_dev_create(void)
4464{
4465 u32 sid = current_sid();
4466
4467 /* we aren't taking into account the "sockcreate" SID since the socket
4468 * that is being created here is not a socket in the traditional sense,
4469 * instead it is a private sock, accessible only to the kernel, and
4470 * representing a wide range of network traffic spanning multiple
4471 * connections unlike traditional sockets - check the TUN driver to
4472 * get a better understanding of why this socket is special */
4473
4474 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4475 NULL);
4476}
4477
Paul Moore5dbbaf22013-01-14 07:12:19 +00004478static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004479{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004480 struct tun_security_struct *tunsec = security;
4481
4482 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4483 TUN_SOCKET__ATTACH_QUEUE, NULL);
4484}
4485
4486static int selinux_tun_dev_attach(struct sock *sk, void *security)
4487{
4488 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004489 struct sk_security_struct *sksec = sk->sk_security;
4490
4491 /* we don't currently perform any NetLabel based labeling here and it
4492 * isn't clear that we would want to do so anyway; while we could apply
4493 * labeling without the support of the TUN user the resulting labeled
4494 * traffic from the other end of the connection would almost certainly
4495 * cause confusion to the TUN user that had no idea network labeling
4496 * protocols were being used */
4497
Paul Moore5dbbaf22013-01-14 07:12:19 +00004498 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004499 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004500
4501 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004502}
4503
Paul Moore5dbbaf22013-01-14 07:12:19 +00004504static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004505{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004506 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004507 u32 sid = current_sid();
4508 int err;
4509
Paul Moore5dbbaf22013-01-14 07:12:19 +00004510 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004511 TUN_SOCKET__RELABELFROM, NULL);
4512 if (err)
4513 return err;
4514 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4515 TUN_SOCKET__RELABELTO, NULL);
4516 if (err)
4517 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004518 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004519
4520 return 0;
4521}
4522
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4524{
4525 int err = 0;
4526 u32 perm;
4527 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004528 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004529
Hong zhi guo77954982013-03-27 06:49:35 +00004530 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 err = -EINVAL;
4532 goto out;
4533 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004534 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004535
Paul Moore253bfae2010-04-22 14:46:19 -04004536 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 if (err) {
4538 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004539 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 "SELinux: unrecognized netlink message"
4541 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004542 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004543 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 err = 0;
4545 }
4546
4547 /* Ignore */
4548 if (err == -ENOENT)
4549 err = 0;
4550 goto out;
4551 }
4552
Paul Moore253bfae2010-04-22 14:46:19 -04004553 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554out:
4555 return err;
4556}
4557
4558#ifdef CONFIG_NETFILTER
4559
Paul Mooreeffad8d2008-01-29 08:49:27 -05004560static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4561 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562{
Paul Mooredfaebe92008-10-10 10:16:31 -04004563 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004564 char *addrp;
4565 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004566 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004567 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004568 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004569 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004570 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004571
Paul Mooreeffad8d2008-01-29 08:49:27 -05004572 if (!selinux_policycap_netpeer)
4573 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004574
Paul Mooreeffad8d2008-01-29 08:49:27 -05004575 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004576 netlbl_active = netlbl_enabled();
4577 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004578 if (!secmark_active && !peerlbl_active)
4579 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004580
Paul Moored8395c82008-10-10 10:16:30 -04004581 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4582 return NF_DROP;
4583
Eric Paris50c205f2012-04-04 15:01:43 -04004584 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004585 ad.u.net = &net;
4586 ad.u.net->netif = ifindex;
4587 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004588 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4589 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590
Paul Mooredfaebe92008-10-10 10:16:31 -04004591 if (peerlbl_active) {
4592 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4593 peer_sid, &ad);
4594 if (err) {
4595 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004596 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004597 }
4598 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004599
4600 if (secmark_active)
4601 if (avc_has_perm(peer_sid, skb->secmark,
4602 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4603 return NF_DROP;
4604
Paul Moore948bf852008-10-10 10:16:32 -04004605 if (netlbl_active)
4606 /* we do this in the FORWARD path and not the POST_ROUTING
4607 * path because we want to make sure we apply the necessary
4608 * labeling before IPsec is applied so we can leverage AH
4609 * protection */
4610 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4611 return NF_DROP;
4612
Paul Mooreeffad8d2008-01-29 08:49:27 -05004613 return NF_ACCEPT;
4614}
4615
4616static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4617 struct sk_buff *skb,
4618 const struct net_device *in,
4619 const struct net_device *out,
4620 int (*okfn)(struct sk_buff *))
4621{
4622 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4623}
4624
4625#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4626static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4627 struct sk_buff *skb,
4628 const struct net_device *in,
4629 const struct net_device *out,
4630 int (*okfn)(struct sk_buff *))
4631{
4632 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4633}
4634#endif /* IPV6 */
4635
Paul Moore948bf852008-10-10 10:16:32 -04004636static unsigned int selinux_ip_output(struct sk_buff *skb,
4637 u16 family)
4638{
4639 u32 sid;
4640
4641 if (!netlbl_enabled())
4642 return NF_ACCEPT;
4643
4644 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4645 * because we want to make sure we apply the necessary labeling
4646 * before IPsec is applied so we can leverage AH protection */
4647 if (skb->sk) {
4648 struct sk_security_struct *sksec = skb->sk->sk_security;
4649 sid = sksec->sid;
4650 } else
4651 sid = SECINITSID_KERNEL;
4652 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4653 return NF_DROP;
4654
4655 return NF_ACCEPT;
4656}
4657
4658static unsigned int selinux_ipv4_output(unsigned int hooknum,
4659 struct sk_buff *skb,
4660 const struct net_device *in,
4661 const struct net_device *out,
4662 int (*okfn)(struct sk_buff *))
4663{
4664 return selinux_ip_output(skb, PF_INET);
4665}
4666
Paul Mooreeffad8d2008-01-29 08:49:27 -05004667static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4668 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004669 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004670{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004671 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004672 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004673 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004674 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004675 char *addrp;
4676 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004677
Paul Mooreeffad8d2008-01-29 08:49:27 -05004678 if (sk == NULL)
4679 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004680 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004681
Eric Paris50c205f2012-04-04 15:01:43 -04004682 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004683 ad.u.net = &net;
4684 ad.u.net->netif = ifindex;
4685 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004686 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4687 return NF_DROP;
4688
Paul Moore58bfbb52009-03-27 17:10:41 -04004689 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004690 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004691 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004692 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004693
Steffen Klassertb9679a72011-02-23 12:55:21 +01004694 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4695 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004696
Paul Mooreeffad8d2008-01-29 08:49:27 -05004697 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698}
4699
Paul Mooreeffad8d2008-01-29 08:49:27 -05004700static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4701 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004703 u32 secmark_perm;
4704 u32 peer_sid;
4705 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004706 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004707 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004708 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004709 u8 secmark_active;
4710 u8 peerlbl_active;
4711
Paul Mooreeffad8d2008-01-29 08:49:27 -05004712 /* If any sort of compatibility mode is enabled then handoff processing
4713 * to the selinux_ip_postroute_compat() function to deal with the
4714 * special handling. We do this in an attempt to keep this function
4715 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004716 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004717 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004718#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004719 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4720 * packet transformation so allow the packet to pass without any checks
4721 * since we'll have another chance to perform access control checks
4722 * when the packet is on it's final way out.
4723 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4724 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004725 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004726 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004727#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004728 secmark_active = selinux_secmark_enabled();
4729 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4730 if (!secmark_active && !peerlbl_active)
4731 return NF_ACCEPT;
4732
Paul Moored8395c82008-10-10 10:16:30 -04004733 /* if the packet is being forwarded then get the peer label from the
4734 * packet itself; otherwise check to see if it is from a local
4735 * application or the kernel, if from an application get the peer label
4736 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004737 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004738 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004739 if (skb->skb_iif) {
4740 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004741 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004742 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004743 } else {
4744 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004745 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004746 }
Paul Moored8395c82008-10-10 10:16:30 -04004747 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004748 struct sk_security_struct *sksec = sk->sk_security;
4749 peer_sid = sksec->sid;
4750 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004751 }
4752
Eric Paris50c205f2012-04-04 15:01:43 -04004753 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004754 ad.u.net = &net;
4755 ad.u.net->netif = ifindex;
4756 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004757 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004758 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004759
Paul Mooreeffad8d2008-01-29 08:49:27 -05004760 if (secmark_active)
4761 if (avc_has_perm(peer_sid, skb->secmark,
4762 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004763 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004764
4765 if (peerlbl_active) {
4766 u32 if_sid;
4767 u32 node_sid;
4768
4769 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004770 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004771 if (avc_has_perm(peer_sid, if_sid,
4772 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004773 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004774
4775 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004776 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004777 if (avc_has_perm(peer_sid, node_sid,
4778 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004779 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004780 }
4781
4782 return NF_ACCEPT;
4783}
4784
4785static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4786 struct sk_buff *skb,
4787 const struct net_device *in,
4788 const struct net_device *out,
4789 int (*okfn)(struct sk_buff *))
4790{
4791 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792}
4793
4794#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004795static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4796 struct sk_buff *skb,
4797 const struct net_device *in,
4798 const struct net_device *out,
4799 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004800{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004801 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004802}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803#endif /* IPV6 */
4804
4805#endif /* CONFIG_NETFILTER */
4806
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4808{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 int err;
4810
Eric Paris200ac532009-02-12 15:01:04 -05004811 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812 if (err)
4813 return err;
4814
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004815 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004816}
4817
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818static int ipc_alloc_security(struct task_struct *task,
4819 struct kern_ipc_perm *perm,
4820 u16 sclass)
4821{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004823 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824
James Morris89d155e2005-10-30 14:59:21 -08004825 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 if (!isec)
4827 return -ENOMEM;
4828
David Howells275bb412008-11-14 10:39:19 +11004829 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11004831 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832 perm->security = isec;
4833
4834 return 0;
4835}
4836
4837static void ipc_free_security(struct kern_ipc_perm *perm)
4838{
4839 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840 perm->security = NULL;
4841 kfree(isec);
4842}
4843
4844static int msg_msg_alloc_security(struct msg_msg *msg)
4845{
4846 struct msg_security_struct *msec;
4847
James Morris89d155e2005-10-30 14:59:21 -08004848 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849 if (!msec)
4850 return -ENOMEM;
4851
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852 msec->sid = SECINITSID_UNLABELED;
4853 msg->security = msec;
4854
4855 return 0;
4856}
4857
4858static void msg_msg_free_security(struct msg_msg *msg)
4859{
4860 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861
4862 msg->security = NULL;
4863 kfree(msec);
4864}
4865
4866static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004867 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004870 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004871 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004872
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873 isec = ipc_perms->security;
4874
Eric Paris50c205f2012-04-04 15:01:43 -04004875 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876 ad.u.ipc_id = ipc_perms->key;
4877
David Howells275bb412008-11-14 10:39:19 +11004878 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004879}
4880
4881static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4882{
4883 return msg_msg_alloc_security(msg);
4884}
4885
4886static void selinux_msg_msg_free_security(struct msg_msg *msg)
4887{
4888 msg_msg_free_security(msg);
4889}
4890
4891/* message queue security operations */
4892static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4893{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004895 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004896 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897 int rc;
4898
4899 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4900 if (rc)
4901 return rc;
4902
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 isec = msq->q_perm.security;
4904
Eric Paris50c205f2012-04-04 15:01:43 -04004905 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04004906 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907
David Howells275bb412008-11-14 10:39:19 +11004908 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909 MSGQ__CREATE, &ad);
4910 if (rc) {
4911 ipc_free_security(&msq->q_perm);
4912 return rc;
4913 }
4914 return 0;
4915}
4916
4917static void selinux_msg_queue_free_security(struct msg_queue *msq)
4918{
4919 ipc_free_security(&msq->q_perm);
4920}
4921
4922static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4923{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004925 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004926 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928 isec = msq->q_perm.security;
4929
Eric Paris50c205f2012-04-04 15:01:43 -04004930 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931 ad.u.ipc_id = msq->q_perm.key;
4932
David Howells275bb412008-11-14 10:39:19 +11004933 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934 MSGQ__ASSOCIATE, &ad);
4935}
4936
4937static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4938{
4939 int err;
4940 int perms;
4941
Eric Paris828dfe12008-04-17 13:17:49 -04004942 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 case IPC_INFO:
4944 case MSG_INFO:
4945 /* No specific object, just general system-wide information. */
4946 return task_has_system(current, SYSTEM__IPC_INFO);
4947 case IPC_STAT:
4948 case MSG_STAT:
4949 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4950 break;
4951 case IPC_SET:
4952 perms = MSGQ__SETATTR;
4953 break;
4954 case IPC_RMID:
4955 perms = MSGQ__DESTROY;
4956 break;
4957 default:
4958 return 0;
4959 }
4960
Stephen Smalley6af963f2005-05-01 08:58:39 -07004961 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 return err;
4963}
4964
4965static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4966{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 struct ipc_security_struct *isec;
4968 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004969 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004970 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 int rc;
4972
Linus Torvalds1da177e2005-04-16 15:20:36 -07004973 isec = msq->q_perm.security;
4974 msec = msg->security;
4975
4976 /*
4977 * First time through, need to assign label to the message
4978 */
4979 if (msec->sid == SECINITSID_UNLABELED) {
4980 /*
4981 * Compute new sid based on current process and
4982 * message queue this message will be stored in
4983 */
David Howells275bb412008-11-14 10:39:19 +11004984 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05004985 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986 if (rc)
4987 return rc;
4988 }
4989
Eric Paris50c205f2012-04-04 15:01:43 -04004990 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991 ad.u.ipc_id = msq->q_perm.key;
4992
4993 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11004994 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995 MSGQ__WRITE, &ad);
4996 if (!rc)
4997 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11004998 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
4999 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 if (!rc)
5001 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005002 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5003 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004
5005 return rc;
5006}
5007
5008static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5009 struct task_struct *target,
5010 long type, int mode)
5011{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 struct ipc_security_struct *isec;
5013 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005014 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005015 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016 int rc;
5017
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 isec = msq->q_perm.security;
5019 msec = msg->security;
5020
Eric Paris50c205f2012-04-04 15:01:43 -04005021 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005022 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
David Howells275bb412008-11-14 10:39:19 +11005024 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025 SECCLASS_MSGQ, MSGQ__READ, &ad);
5026 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005027 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028 SECCLASS_MSG, MSG__RECEIVE, &ad);
5029 return rc;
5030}
5031
5032/* Shared Memory security operations */
5033static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5034{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005036 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005037 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038 int rc;
5039
5040 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5041 if (rc)
5042 return rc;
5043
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 isec = shp->shm_perm.security;
5045
Eric Paris50c205f2012-04-04 15:01:43 -04005046 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005047 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048
David Howells275bb412008-11-14 10:39:19 +11005049 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 SHM__CREATE, &ad);
5051 if (rc) {
5052 ipc_free_security(&shp->shm_perm);
5053 return rc;
5054 }
5055 return 0;
5056}
5057
5058static void selinux_shm_free_security(struct shmid_kernel *shp)
5059{
5060 ipc_free_security(&shp->shm_perm);
5061}
5062
5063static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5064{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005066 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005067 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 isec = shp->shm_perm.security;
5070
Eric Paris50c205f2012-04-04 15:01:43 -04005071 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072 ad.u.ipc_id = shp->shm_perm.key;
5073
David Howells275bb412008-11-14 10:39:19 +11005074 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075 SHM__ASSOCIATE, &ad);
5076}
5077
5078/* Note, at this point, shp is locked down */
5079static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5080{
5081 int perms;
5082 int err;
5083
Eric Paris828dfe12008-04-17 13:17:49 -04005084 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 case IPC_INFO:
5086 case SHM_INFO:
5087 /* No specific object, just general system-wide information. */
5088 return task_has_system(current, SYSTEM__IPC_INFO);
5089 case IPC_STAT:
5090 case SHM_STAT:
5091 perms = SHM__GETATTR | SHM__ASSOCIATE;
5092 break;
5093 case IPC_SET:
5094 perms = SHM__SETATTR;
5095 break;
5096 case SHM_LOCK:
5097 case SHM_UNLOCK:
5098 perms = SHM__LOCK;
5099 break;
5100 case IPC_RMID:
5101 perms = SHM__DESTROY;
5102 break;
5103 default:
5104 return 0;
5105 }
5106
Stephen Smalley6af963f2005-05-01 08:58:39 -07005107 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108 return err;
5109}
5110
5111static int selinux_shm_shmat(struct shmid_kernel *shp,
5112 char __user *shmaddr, int shmflg)
5113{
5114 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
5116 if (shmflg & SHM_RDONLY)
5117 perms = SHM__READ;
5118 else
5119 perms = SHM__READ | SHM__WRITE;
5120
Stephen Smalley6af963f2005-05-01 08:58:39 -07005121 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122}
5123
5124/* Semaphore security operations */
5125static int selinux_sem_alloc_security(struct sem_array *sma)
5126{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005128 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005129 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 int rc;
5131
5132 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5133 if (rc)
5134 return rc;
5135
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136 isec = sma->sem_perm.security;
5137
Eric Paris50c205f2012-04-04 15:01:43 -04005138 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005139 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
David Howells275bb412008-11-14 10:39:19 +11005141 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142 SEM__CREATE, &ad);
5143 if (rc) {
5144 ipc_free_security(&sma->sem_perm);
5145 return rc;
5146 }
5147 return 0;
5148}
5149
5150static void selinux_sem_free_security(struct sem_array *sma)
5151{
5152 ipc_free_security(&sma->sem_perm);
5153}
5154
5155static int selinux_sem_associate(struct sem_array *sma, int semflg)
5156{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005158 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005159 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Linus Torvalds1da177e2005-04-16 15:20:36 -07005161 isec = sma->sem_perm.security;
5162
Eric Paris50c205f2012-04-04 15:01:43 -04005163 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164 ad.u.ipc_id = sma->sem_perm.key;
5165
David Howells275bb412008-11-14 10:39:19 +11005166 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167 SEM__ASSOCIATE, &ad);
5168}
5169
5170/* Note, at this point, sma is locked down */
5171static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5172{
5173 int err;
5174 u32 perms;
5175
Eric Paris828dfe12008-04-17 13:17:49 -04005176 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177 case IPC_INFO:
5178 case SEM_INFO:
5179 /* No specific object, just general system-wide information. */
5180 return task_has_system(current, SYSTEM__IPC_INFO);
5181 case GETPID:
5182 case GETNCNT:
5183 case GETZCNT:
5184 perms = SEM__GETATTR;
5185 break;
5186 case GETVAL:
5187 case GETALL:
5188 perms = SEM__READ;
5189 break;
5190 case SETVAL:
5191 case SETALL:
5192 perms = SEM__WRITE;
5193 break;
5194 case IPC_RMID:
5195 perms = SEM__DESTROY;
5196 break;
5197 case IPC_SET:
5198 perms = SEM__SETATTR;
5199 break;
5200 case IPC_STAT:
5201 case SEM_STAT:
5202 perms = SEM__GETATTR | SEM__ASSOCIATE;
5203 break;
5204 default:
5205 return 0;
5206 }
5207
Stephen Smalley6af963f2005-05-01 08:58:39 -07005208 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 return err;
5210}
5211
5212static int selinux_sem_semop(struct sem_array *sma,
5213 struct sembuf *sops, unsigned nsops, int alter)
5214{
5215 u32 perms;
5216
5217 if (alter)
5218 perms = SEM__READ | SEM__WRITE;
5219 else
5220 perms = SEM__READ;
5221
Stephen Smalley6af963f2005-05-01 08:58:39 -07005222 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223}
5224
5225static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5226{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227 u32 av = 0;
5228
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229 av = 0;
5230 if (flag & S_IRUGO)
5231 av |= IPC__UNIX_READ;
5232 if (flag & S_IWUGO)
5233 av |= IPC__UNIX_WRITE;
5234
5235 if (av == 0)
5236 return 0;
5237
Stephen Smalley6af963f2005-05-01 08:58:39 -07005238 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239}
5240
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005241static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5242{
5243 struct ipc_security_struct *isec = ipcp->security;
5244 *secid = isec->sid;
5245}
5246
Eric Paris828dfe12008-04-17 13:17:49 -04005247static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248{
5249 if (inode)
5250 inode_doinit_with_dentry(inode, dentry);
5251}
5252
5253static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005254 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255{
David Howells275bb412008-11-14 10:39:19 +11005256 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005257 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005259 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260
5261 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005262 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263 if (error)
5264 return error;
5265 }
5266
David Howells275bb412008-11-14 10:39:19 +11005267 rcu_read_lock();
5268 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
5270 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005271 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005273 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005275 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005277 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005278 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005279 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005280 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005281 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 else
David Howells275bb412008-11-14 10:39:19 +11005283 goto invalid;
5284 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285
5286 if (!sid)
5287 return 0;
5288
Al Viro04ff9702007-03-12 16:17:58 +00005289 error = security_sid_to_context(sid, value, &len);
5290 if (error)
5291 return error;
5292 return len;
David Howells275bb412008-11-14 10:39:19 +11005293
5294invalid:
5295 rcu_read_unlock();
5296 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297}
5298
5299static int selinux_setprocattr(struct task_struct *p,
5300 char *name, void *value, size_t size)
5301{
5302 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005303 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005304 struct cred *new;
5305 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306 int error;
5307 char *str = value;
5308
5309 if (current != p) {
5310 /* SELinux only allows a process to change its own
5311 security attributes. */
5312 return -EACCES;
5313 }
5314
5315 /*
5316 * Basic control over ability to set these attributes at all.
5317 * current == p, but we'll pass them separately in case the
5318 * above restriction is ever removed.
5319 */
5320 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005321 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005323 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005324 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005325 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005326 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005327 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005329 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330 else
5331 error = -EINVAL;
5332 if (error)
5333 return error;
5334
5335 /* Obtain a SID for the context, if one was specified. */
5336 if (size && str[1] && str[1] != '\n') {
5337 if (str[size-1] == '\n') {
5338 str[size-1] = 0;
5339 size--;
5340 }
5341 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005342 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005343 if (!capable(CAP_MAC_ADMIN)) {
5344 struct audit_buffer *ab;
5345 size_t audit_size;
5346
5347 /* We strip a nul only if it is at the end, otherwise the
5348 * context contains a nul and we should audit that */
5349 if (str[size - 1] == '\0')
5350 audit_size = size - 1;
5351 else
5352 audit_size = size;
5353 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5354 audit_log_format(ab, "op=fscreate invalid_context=");
5355 audit_log_n_untrustedstring(ab, value, audit_size);
5356 audit_log_end(ab);
5357
Stephen Smalley12b29f32008-05-07 13:03:20 -04005358 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005359 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005360 error = security_context_to_sid_force(value, size,
5361 &sid);
5362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363 if (error)
5364 return error;
5365 }
5366
David Howellsd84f4f92008-11-14 10:39:23 +11005367 new = prepare_creds();
5368 if (!new)
5369 return -ENOMEM;
5370
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 /* Permission checking based on the specified context is
5372 performed during the actual operation (execve,
5373 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005374 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 checks and may_create for the file creation checks. The
5376 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005377 tsec = new->security;
5378 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005380 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005382 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005383 error = may_create_key(sid, p);
5384 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005385 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005386 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005387 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005388 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005389 } else if (!strcmp(name, "current")) {
5390 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005392 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005393
David Howellsd84f4f92008-11-14 10:39:23 +11005394 /* Only allow single threaded processes to change context */
5395 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005396 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005397 error = security_bounded_transition(tsec->sid, sid);
5398 if (error)
5399 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401
5402 /* Check permissions for the transition. */
5403 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005404 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005406 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407
5408 /* Check for ptracing, and update the task SID if ok.
5409 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005410 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005412 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005413 if (tracer)
5414 ptsid = task_sid(tracer);
5415 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416
David Howellsd84f4f92008-11-14 10:39:23 +11005417 if (tracer) {
5418 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5419 PROCESS__PTRACE, NULL);
5420 if (error)
5421 goto abort_change;
5422 }
5423
5424 tsec->sid = sid;
5425 } else {
5426 error = -EINVAL;
5427 goto abort_change;
5428 }
5429
5430 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005432
5433abort_change:
5434 abort_creds(new);
5435 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436}
5437
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005438static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5439{
5440 return security_sid_to_context(secid, secdata, seclen);
5441}
5442
David Howells7bf570d2008-04-29 20:52:51 +01005443static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005444{
5445 return security_context_to_sid(secdata, seclen, secid);
5446}
5447
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005448static void selinux_release_secctx(char *secdata, u32 seclen)
5449{
Paul Moore088999e2007-08-01 11:12:58 -04005450 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005451}
5452
David P. Quigley1ee65e32009-09-03 14:25:57 -04005453/*
5454 * called with inode->i_mutex locked
5455 */
5456static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5457{
5458 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5459}
5460
5461/*
5462 * called with inode->i_mutex locked
5463 */
5464static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5465{
5466 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5467}
5468
5469static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5470{
5471 int len = 0;
5472 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5473 ctx, true);
5474 if (len < 0)
5475 return len;
5476 *ctxlen = len;
5477 return 0;
5478}
Michael LeMayd7200242006-06-22 14:47:17 -07005479#ifdef CONFIG_KEYS
5480
David Howellsd84f4f92008-11-14 10:39:23 +11005481static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005482 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005483{
David Howellsd84f4f92008-11-14 10:39:23 +11005484 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005485 struct key_security_struct *ksec;
5486
5487 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5488 if (!ksec)
5489 return -ENOMEM;
5490
David Howellsd84f4f92008-11-14 10:39:23 +11005491 tsec = cred->security;
5492 if (tsec->keycreate_sid)
5493 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005494 else
David Howellsd84f4f92008-11-14 10:39:23 +11005495 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005496
David Howells275bb412008-11-14 10:39:19 +11005497 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005498 return 0;
5499}
5500
5501static void selinux_key_free(struct key *k)
5502{
5503 struct key_security_struct *ksec = k->security;
5504
5505 k->security = NULL;
5506 kfree(ksec);
5507}
5508
5509static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005510 const struct cred *cred,
5511 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005512{
5513 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005514 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005515 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005516
5517 /* if no specific permissions are requested, we skip the
5518 permission check. No serious, additional covert channels
5519 appear to be created. */
5520 if (perm == 0)
5521 return 0;
5522
David Howellsd84f4f92008-11-14 10:39:23 +11005523 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005524
5525 key = key_ref_to_ptr(key_ref);
5526 ksec = key->security;
5527
5528 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005529}
5530
David Howells70a5bb72008-04-29 01:01:26 -07005531static int selinux_key_getsecurity(struct key *key, char **_buffer)
5532{
5533 struct key_security_struct *ksec = key->security;
5534 char *context = NULL;
5535 unsigned len;
5536 int rc;
5537
5538 rc = security_sid_to_context(ksec->sid, &context, &len);
5539 if (!rc)
5540 rc = len;
5541 *_buffer = context;
5542 return rc;
5543}
5544
Michael LeMayd7200242006-06-22 14:47:17 -07005545#endif
5546
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005548 .name = "selinux",
5549
Ingo Molnar9e488582009-05-07 19:26:19 +10005550 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005551 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005553 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554 .capable = selinux_capable,
5555 .quotactl = selinux_quotactl,
5556 .quota_on = selinux_quota_on,
5557 .syslog = selinux_syslog,
5558 .vm_enough_memory = selinux_vm_enough_memory,
5559
5560 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561
David Howellsa6f76f22008-11-14 10:39:24 +11005562 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005563 .bprm_committing_creds = selinux_bprm_committing_creds,
5564 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565 .bprm_secureexec = selinux_bprm_secureexec,
5566
5567 .sb_alloc_security = selinux_sb_alloc_security,
5568 .sb_free_security = selinux_sb_free_security,
5569 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005570 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005571 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005572 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 .sb_statfs = selinux_sb_statfs,
5574 .sb_mount = selinux_mount,
5575 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005576 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005577 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005578 .sb_parse_opts_str = selinux_parse_opts_str,
5579
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
5581 .inode_alloc_security = selinux_inode_alloc_security,
5582 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005583 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 .inode_unlink = selinux_inode_unlink,
5587 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589 .inode_rmdir = selinux_inode_rmdir,
5590 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005591 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592 .inode_readlink = selinux_inode_readlink,
5593 .inode_follow_link = selinux_inode_follow_link,
5594 .inode_permission = selinux_inode_permission,
5595 .inode_setattr = selinux_inode_setattr,
5596 .inode_getattr = selinux_inode_getattr,
5597 .inode_setxattr = selinux_inode_setxattr,
5598 .inode_post_setxattr = selinux_inode_post_setxattr,
5599 .inode_getxattr = selinux_inode_getxattr,
5600 .inode_listxattr = selinux_inode_listxattr,
5601 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005602 .inode_getsecurity = selinux_inode_getsecurity,
5603 .inode_setsecurity = selinux_inode_setsecurity,
5604 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005605 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606
5607 .file_permission = selinux_file_permission,
5608 .file_alloc_security = selinux_file_alloc_security,
5609 .file_free_security = selinux_file_free_security,
5610 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005611 .mmap_file = selinux_mmap_file,
5612 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 .file_mprotect = selinux_file_mprotect,
5614 .file_lock = selinux_file_lock,
5615 .file_fcntl = selinux_file_fcntl,
5616 .file_set_fowner = selinux_file_set_fowner,
5617 .file_send_sigiotask = selinux_file_send_sigiotask,
5618 .file_receive = selinux_file_receive,
5619
Eric Paris83d49852012-04-04 13:45:40 -04005620 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005621
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005623 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005624 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005625 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005626 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005627 .kernel_act_as = selinux_kernel_act_as,
5628 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005629 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 .task_setpgid = selinux_task_setpgid,
5631 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005632 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005633 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005635 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005636 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 .task_setrlimit = selinux_task_setrlimit,
5638 .task_setscheduler = selinux_task_setscheduler,
5639 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005640 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641 .task_kill = selinux_task_kill,
5642 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005643 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644
5645 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005646 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
5648 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5649 .msg_msg_free_security = selinux_msg_msg_free_security,
5650
5651 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5652 .msg_queue_free_security = selinux_msg_queue_free_security,
5653 .msg_queue_associate = selinux_msg_queue_associate,
5654 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5655 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5656 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5657
5658 .shm_alloc_security = selinux_shm_alloc_security,
5659 .shm_free_security = selinux_shm_free_security,
5660 .shm_associate = selinux_shm_associate,
5661 .shm_shmctl = selinux_shm_shmctl,
5662 .shm_shmat = selinux_shm_shmat,
5663
Eric Paris828dfe12008-04-17 13:17:49 -04005664 .sem_alloc_security = selinux_sem_alloc_security,
5665 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666 .sem_associate = selinux_sem_associate,
5667 .sem_semctl = selinux_sem_semctl,
5668 .sem_semop = selinux_sem_semop,
5669
Eric Paris828dfe12008-04-17 13:17:49 -04005670 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671
Eric Paris828dfe12008-04-17 13:17:49 -04005672 .getprocattr = selinux_getprocattr,
5673 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005675 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005676 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005677 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005678 .inode_notifysecctx = selinux_inode_notifysecctx,
5679 .inode_setsecctx = selinux_inode_setsecctx,
5680 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005681
Eric Paris828dfe12008-04-17 13:17:49 -04005682 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683 .unix_may_send = selinux_socket_unix_may_send,
5684
5685 .socket_create = selinux_socket_create,
5686 .socket_post_create = selinux_socket_post_create,
5687 .socket_bind = selinux_socket_bind,
5688 .socket_connect = selinux_socket_connect,
5689 .socket_listen = selinux_socket_listen,
5690 .socket_accept = selinux_socket_accept,
5691 .socket_sendmsg = selinux_socket_sendmsg,
5692 .socket_recvmsg = selinux_socket_recvmsg,
5693 .socket_getsockname = selinux_socket_getsockname,
5694 .socket_getpeername = selinux_socket_getpeername,
5695 .socket_getsockopt = selinux_socket_getsockopt,
5696 .socket_setsockopt = selinux_socket_setsockopt,
5697 .socket_shutdown = selinux_socket_shutdown,
5698 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005699 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5700 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701 .sk_alloc_security = selinux_sk_alloc_security,
5702 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005703 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005704 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005705 .sock_graft = selinux_sock_graft,
5706 .inet_conn_request = selinux_inet_conn_request,
5707 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005708 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005709 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5710 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5711 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005712 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005713 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5714 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005715 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005716 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005717 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005718 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005719 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005720
5721#ifdef CONFIG_SECURITY_NETWORK_XFRM
5722 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5723 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5724 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005725 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Paul Moore2e5aa862013-07-23 17:38:38 -04005726 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5727 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005728 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005729 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005730 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005731 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005732 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005734
5735#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005736 .key_alloc = selinux_key_alloc,
5737 .key_free = selinux_key_free,
5738 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005739 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005740#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005741
5742#ifdef CONFIG_AUDIT
5743 .audit_rule_init = selinux_audit_rule_init,
5744 .audit_rule_known = selinux_audit_rule_known,
5745 .audit_rule_match = selinux_audit_rule_match,
5746 .audit_rule_free = selinux_audit_rule_free,
5747#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748};
5749
5750static __init int selinux_init(void)
5751{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005752 if (!security_module_enable(&selinux_ops)) {
5753 selinux_enabled = 0;
5754 return 0;
5755 }
5756
Linus Torvalds1da177e2005-04-16 15:20:36 -07005757 if (!selinux_enabled) {
5758 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5759 return 0;
5760 }
5761
5762 printk(KERN_INFO "SELinux: Initializing.\n");
5763
5764 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005765 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005767 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5768
James Morris7cae7e22006-03-22 00:09:22 -08005769 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5770 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005771 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772 avc_init();
5773
Eric Paris828dfe12008-04-17 13:17:49 -04005774 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775 panic("SELinux: Unable to register with kernel.\n");
5776
Eric Paris828dfe12008-04-17 13:17:49 -04005777 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005778 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005779 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005780 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005781
Linus Torvalds1da177e2005-04-16 15:20:36 -07005782 return 0;
5783}
5784
Al Viroe8c26252010-03-23 06:36:54 -04005785static void delayed_superblock_init(struct super_block *sb, void *unused)
5786{
5787 superblock_doinit(sb, NULL);
5788}
5789
Linus Torvalds1da177e2005-04-16 15:20:36 -07005790void selinux_complete_init(void)
5791{
Eric Parisfadcdb42007-02-22 18:11:31 -05005792 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793
5794 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005795 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005796 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797}
5798
5799/* SELinux requires early initialization in order to label
5800 all processes and objects when they are created. */
5801security_initcall(selinux_init);
5802
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005803#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804
Paul Mooreeffad8d2008-01-29 08:49:27 -05005805static struct nf_hook_ops selinux_ipv4_ops[] = {
5806 {
5807 .hook = selinux_ipv4_postroute,
5808 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005809 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005810 .hooknum = NF_INET_POST_ROUTING,
5811 .priority = NF_IP_PRI_SELINUX_LAST,
5812 },
5813 {
5814 .hook = selinux_ipv4_forward,
5815 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005816 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005817 .hooknum = NF_INET_FORWARD,
5818 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005819 },
5820 {
5821 .hook = selinux_ipv4_output,
5822 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005823 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04005824 .hooknum = NF_INET_LOCAL_OUT,
5825 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827};
5828
5829#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5830
Paul Mooreeffad8d2008-01-29 08:49:27 -05005831static struct nf_hook_ops selinux_ipv6_ops[] = {
5832 {
5833 .hook = selinux_ipv6_postroute,
5834 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005835 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005836 .hooknum = NF_INET_POST_ROUTING,
5837 .priority = NF_IP6_PRI_SELINUX_LAST,
5838 },
5839 {
5840 .hook = selinux_ipv6_forward,
5841 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005842 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005843 .hooknum = NF_INET_FORWARD,
5844 .priority = NF_IP6_PRI_SELINUX_FIRST,
5845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846};
5847
5848#endif /* IPV6 */
5849
5850static int __init selinux_nf_ip_init(void)
5851{
5852 int err = 0;
5853
5854 if (!selinux_enabled)
5855 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005856
5857 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5858
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005859 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5860 if (err)
5861 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862
5863#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005864 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5865 if (err)
5866 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005868
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869out:
5870 return err;
5871}
5872
5873__initcall(selinux_nf_ip_init);
5874
5875#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5876static void selinux_nf_ip_exit(void)
5877{
Eric Parisfadcdb42007-02-22 18:11:31 -05005878 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005880 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005882 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883#endif /* IPV6 */
5884}
5885#endif
5886
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005887#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
5889#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5890#define selinux_nf_ip_exit()
5891#endif
5892
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005893#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894
5895#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005896static int selinux_disabled;
5897
Linus Torvalds1da177e2005-04-16 15:20:36 -07005898int selinux_disable(void)
5899{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900 if (ss_initialized) {
5901 /* Not permitted after initial policy load. */
5902 return -EINVAL;
5903 }
5904
5905 if (selinux_disabled) {
5906 /* Only do this once. */
5907 return -EINVAL;
5908 }
5909
5910 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5911
5912 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005913 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08005915 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916
Eric Parisaf8ff042009-09-20 21:23:01 -04005917 /* Try to destroy the avc node cache */
5918 avc_disable();
5919
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920 /* Unregister netfilter hooks. */
5921 selinux_nf_ip_exit();
5922
5923 /* Unregister selinuxfs. */
5924 exit_sel_fs();
5925
5926 return 0;
5927}
5928#endif