blob: ec15a5694b9e8d703233711f126f244b54c3b945 [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
Eric Parisc9180a52007-11-30 13:00:35 -0500390 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500391 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500393 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500394 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 sb->s_id, sb->s_type->name,
396 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Eric Pariseadcabc2012-08-24 15:59:14 -0400398 sbsec->flags |= SE_SBINITIALIZED;
399 if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
400 sbsec->behavior == SECURITY_FS_USE_TRANS ||
401 sbsec->behavior == SECURITY_FS_USE_TASK)
402 sbsec->flags |= SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500403
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400404 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
405 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
Eric Paris12f348b2012-10-09 10:56:25 -0400406 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400407
Stephen Smalley5c73fce2013-07-23 17:38:41 -0400408 /*
409 * Special handling for rootfs. Is genfs but supports
410 * setting SELinux context on in-core inodes.
411 */
412 if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
Eric Paris12f348b2012-10-09 10:56:25 -0400413 sbsec->flags |= SBLABEL_MNT;
Stephen Smalley5c73fce2013-07-23 17:38:41 -0400414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500416 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 /* Initialize any other inodes associated with the superblock, e.g.
419 inodes created prior to initial policy load or inodes created
420 during get_sb by a pseudo filesystem that directly
421 populates itself. */
422 spin_lock(&sbsec->isec_lock);
423next_inode:
424 if (!list_empty(&sbsec->isec_head)) {
425 struct inode_security_struct *isec =
426 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500427 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 struct inode *inode = isec->inode;
429 spin_unlock(&sbsec->isec_lock);
430 inode = igrab(inode);
431 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500432 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 inode_doinit(inode);
434 iput(inode);
435 }
436 spin_lock(&sbsec->isec_lock);
437 list_del_init(&isec->list);
438 goto next_inode;
439 }
440 spin_unlock(&sbsec->isec_lock);
441out:
Eric Parisc9180a52007-11-30 13:00:35 -0500442 return rc;
443}
444
445/*
446 * This function should allow an FS to ask what it's mount security
447 * options were so it can use those later for submounts, displaying
448 * mount options, or whatever.
449 */
450static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500451 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500452{
453 int rc = 0, i;
454 struct superblock_security_struct *sbsec = sb->s_security;
455 char *context = NULL;
456 u32 len;
457 char tmp;
458
Eric Parise0007522008-03-05 10:31:54 -0500459 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500460
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500461 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500462 return -EINVAL;
463
464 if (!ss_initialized)
465 return -EINVAL;
466
Eric Parisaf8e50c2012-08-24 15:59:00 -0400467 /* make sure we always check enough bits to cover the mask */
468 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
469
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500470 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500471 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400472 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500473 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500474 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500475 tmp >>= 1;
476 }
477
Eric Parise0007522008-03-05 10:31:54 -0500478 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
479 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500480 rc = -ENOMEM;
481 goto out_free;
482 }
483
Eric Parise0007522008-03-05 10:31:54 -0500484 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
485 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500486 rc = -ENOMEM;
487 goto out_free;
488 }
489
490 i = 0;
491 if (sbsec->flags & FSCONTEXT_MNT) {
492 rc = security_sid_to_context(sbsec->sid, &context, &len);
493 if (rc)
494 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500495 opts->mnt_opts[i] = context;
496 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500497 }
498 if (sbsec->flags & CONTEXT_MNT) {
499 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
500 if (rc)
501 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500502 opts->mnt_opts[i] = context;
503 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500504 }
505 if (sbsec->flags & DEFCONTEXT_MNT) {
506 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
507 if (rc)
508 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500509 opts->mnt_opts[i] = context;
510 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500511 }
512 if (sbsec->flags & ROOTCONTEXT_MNT) {
513 struct inode *root = sbsec->sb->s_root->d_inode;
514 struct inode_security_struct *isec = root->i_security;
515
516 rc = security_sid_to_context(isec->sid, &context, &len);
517 if (rc)
518 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500519 opts->mnt_opts[i] = context;
520 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500521 }
Eric Paris12f348b2012-10-09 10:56:25 -0400522 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500523 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400524 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500525 }
Eric Parisc9180a52007-11-30 13:00:35 -0500526
Eric Parise0007522008-03-05 10:31:54 -0500527 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500528
529 return 0;
530
531out_free:
Eric Parise0007522008-03-05 10:31:54 -0500532 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500533 return rc;
534}
535
536static int bad_option(struct superblock_security_struct *sbsec, char flag,
537 u32 old_sid, u32 new_sid)
538{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500539 char mnt_flags = sbsec->flags & SE_MNTMASK;
540
Eric Parisc9180a52007-11-30 13:00:35 -0500541 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500542 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500543 if (!(sbsec->flags & flag) ||
544 (old_sid != new_sid))
545 return 1;
546
547 /* check if we were passed the same options twice,
548 * aka someone passed context=a,context=b
549 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500550 if (!(sbsec->flags & SE_SBINITIALIZED))
551 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500552 return 1;
553 return 0;
554}
Eric Parise0007522008-03-05 10:31:54 -0500555
Eric Parisc9180a52007-11-30 13:00:35 -0500556/*
557 * Allow filesystems with binary mount data to explicitly set mount point
558 * labeling information.
559 */
Eric Parise0007522008-03-05 10:31:54 -0500560static int selinux_set_mnt_opts(struct super_block *sb,
561 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500562{
David Howells275bb412008-11-14 10:39:19 +1100563 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500564 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500565 struct superblock_security_struct *sbsec = sb->s_security;
566 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000567 struct inode *inode = sbsec->sb->s_root->d_inode;
568 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
570 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500571 char **mount_options = opts->mnt_opts;
572 int *flags = opts->mnt_opts_flags;
573 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500574
575 mutex_lock(&sbsec->lock);
576
577 if (!ss_initialized) {
578 if (!num_opts) {
579 /* Defer initialization until selinux_complete_init,
580 after the initial policy is loaded and the security
581 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500582 goto out;
583 }
584 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400585 printk(KERN_WARNING "SELinux: Unable to set superblock options "
586 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500587 goto out;
588 }
589
590 /*
Eric Parise0007522008-03-05 10:31:54 -0500591 * Binary mount data FS will come through this function twice. Once
592 * from an explicit call and once from the generic calls from the vfs.
593 * Since the generic VFS calls will not contain any security mount data
594 * we need to skip the double mount verification.
595 *
596 * This does open a hole in which we will not notice if the first
597 * mount using this sb set explict options and a second mount using
598 * this sb does not set any security options. (The first options
599 * will be used for both mounts)
600 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500601 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500602 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400603 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500604
605 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500606 * parse the mount options, check if they are valid sids.
607 * also check if someone is trying to mount the same sb more
608 * than once with different security options.
609 */
610 for (i = 0; i < num_opts; i++) {
611 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500612
Eric Paris12f348b2012-10-09 10:56:25 -0400613 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500614 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500615 rc = security_context_to_sid(mount_options[i],
616 strlen(mount_options[i]), &sid);
617 if (rc) {
618 printk(KERN_WARNING "SELinux: security_context_to_sid"
619 "(%s) failed for (dev %s, type %s) errno=%d\n",
620 mount_options[i], sb->s_id, name, rc);
621 goto out;
622 }
623 switch (flags[i]) {
624 case FSCONTEXT_MNT:
625 fscontext_sid = sid;
626
627 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
628 fscontext_sid))
629 goto out_double_mount;
630
631 sbsec->flags |= FSCONTEXT_MNT;
632 break;
633 case CONTEXT_MNT:
634 context_sid = sid;
635
636 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
637 context_sid))
638 goto out_double_mount;
639
640 sbsec->flags |= CONTEXT_MNT;
641 break;
642 case ROOTCONTEXT_MNT:
643 rootcontext_sid = sid;
644
645 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
646 rootcontext_sid))
647 goto out_double_mount;
648
649 sbsec->flags |= ROOTCONTEXT_MNT;
650
651 break;
652 case DEFCONTEXT_MNT:
653 defcontext_sid = sid;
654
655 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
656 defcontext_sid))
657 goto out_double_mount;
658
659 sbsec->flags |= DEFCONTEXT_MNT;
660
661 break;
662 default:
663 rc = -EINVAL;
664 goto out;
665 }
666 }
667
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500668 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500669 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500670 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500671 goto out_double_mount;
672 rc = 0;
673 goto out;
674 }
675
James Morris089be432008-07-15 18:32:49 +1000676 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500677 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500678
679 /* Determine the labeling behavior to use for this filesystem type. */
Eric Parisa64c54c2012-08-24 15:59:07 -0400680 rc = security_fs_use(sb);
Eric Parisc9180a52007-11-30 13:00:35 -0500681 if (rc) {
682 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000683 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500684 goto out;
685 }
686
687 /* sets the context of the superblock for the fs being mounted. */
688 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100689 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500690 if (rc)
691 goto out;
692
693 sbsec->sid = fscontext_sid;
694 }
695
696 /*
697 * Switch to using mount point labeling behavior.
698 * sets the label used on all file below the mountpoint, and will set
699 * the superblock context if not already set.
700 */
701 if (context_sid) {
702 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100703 rc = may_context_mount_sb_relabel(context_sid, sbsec,
704 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500705 if (rc)
706 goto out;
707 sbsec->sid = context_sid;
708 } else {
David Howells275bb412008-11-14 10:39:19 +1100709 rc = may_context_mount_inode_relabel(context_sid, sbsec,
710 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500711 if (rc)
712 goto out;
713 }
714 if (!rootcontext_sid)
715 rootcontext_sid = context_sid;
716
717 sbsec->mntpoint_sid = context_sid;
718 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
719 }
720
721 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100722 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
723 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500724 if (rc)
725 goto out;
726
727 root_isec->sid = rootcontext_sid;
728 root_isec->initialized = 1;
729 }
730
731 if (defcontext_sid) {
732 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
733 rc = -EINVAL;
734 printk(KERN_WARNING "SELinux: defcontext option is "
735 "invalid for this filesystem type\n");
736 goto out;
737 }
738
739 if (defcontext_sid != sbsec->def_sid) {
740 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100741 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500742 if (rc)
743 goto out;
744 }
745
746 sbsec->def_sid = defcontext_sid;
747 }
748
749 rc = sb_finish_set_opts(sb);
750out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700751 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500753out_double_mount:
754 rc = -EINVAL;
755 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
756 "security settings for (dev %s, type %s)\n", sb->s_id, name);
757 goto out;
758}
759
Jeff Layton094f7b62013-04-01 08:14:24 -0400760static int selinux_cmp_sb_context(const struct super_block *oldsb,
761 const struct super_block *newsb)
762{
763 struct superblock_security_struct *old = oldsb->s_security;
764 struct superblock_security_struct *new = newsb->s_security;
765 char oldflags = old->flags & SE_MNTMASK;
766 char newflags = new->flags & SE_MNTMASK;
767
768 if (oldflags != newflags)
769 goto mismatch;
770 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
771 goto mismatch;
772 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
773 goto mismatch;
774 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
775 goto mismatch;
776 if (oldflags & ROOTCONTEXT_MNT) {
777 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
778 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
779 if (oldroot->sid != newroot->sid)
780 goto mismatch;
781 }
782 return 0;
783mismatch:
784 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
785 "different security settings for (dev %s, "
786 "type %s)\n", newsb->s_id, newsb->s_type->name);
787 return -EBUSY;
788}
789
790static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500791 struct super_block *newsb)
792{
793 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
794 struct superblock_security_struct *newsbsec = newsb->s_security;
795
796 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
797 int set_context = (oldsbsec->flags & CONTEXT_MNT);
798 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
799
Eric Paris0f5e6422008-04-21 16:24:11 -0400800 /*
801 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400802 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400803 */
Al Viroe8c26252010-03-23 06:36:54 -0400804 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400805 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500806
Eric Parisc9180a52007-11-30 13:00:35 -0500807 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500808 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500809
Jeff Layton094f7b62013-04-01 08:14:24 -0400810 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500811 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400812 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400813
Eric Parisc9180a52007-11-30 13:00:35 -0500814 mutex_lock(&newsbsec->lock);
815
816 newsbsec->flags = oldsbsec->flags;
817
818 newsbsec->sid = oldsbsec->sid;
819 newsbsec->def_sid = oldsbsec->def_sid;
820 newsbsec->behavior = oldsbsec->behavior;
821
822 if (set_context) {
823 u32 sid = oldsbsec->mntpoint_sid;
824
825 if (!set_fscontext)
826 newsbsec->sid = sid;
827 if (!set_rootcontext) {
828 struct inode *newinode = newsb->s_root->d_inode;
829 struct inode_security_struct *newisec = newinode->i_security;
830 newisec->sid = sid;
831 }
832 newsbsec->mntpoint_sid = sid;
833 }
834 if (set_rootcontext) {
835 const struct inode *oldinode = oldsb->s_root->d_inode;
836 const struct inode_security_struct *oldisec = oldinode->i_security;
837 struct inode *newinode = newsb->s_root->d_inode;
838 struct inode_security_struct *newisec = newinode->i_security;
839
840 newisec->sid = oldisec->sid;
841 }
842
843 sb_finish_set_opts(newsb);
844 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400845 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500846}
847
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200848static int selinux_parse_opts_str(char *options,
849 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500850{
Eric Parise0007522008-03-05 10:31:54 -0500851 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500852 char *context = NULL, *defcontext = NULL;
853 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500854 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500855
Eric Parise0007522008-03-05 10:31:54 -0500856 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500857
858 /* Standard string-based options. */
859 while ((p = strsep(&options, "|")) != NULL) {
860 int token;
861 substring_t args[MAX_OPT_ARGS];
862
863 if (!*p)
864 continue;
865
866 token = match_token(p, tokens, args);
867
868 switch (token) {
869 case Opt_context:
870 if (context || defcontext) {
871 rc = -EINVAL;
872 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
873 goto out_err;
874 }
875 context = match_strdup(&args[0]);
876 if (!context) {
877 rc = -ENOMEM;
878 goto out_err;
879 }
880 break;
881
882 case Opt_fscontext:
883 if (fscontext) {
884 rc = -EINVAL;
885 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
886 goto out_err;
887 }
888 fscontext = match_strdup(&args[0]);
889 if (!fscontext) {
890 rc = -ENOMEM;
891 goto out_err;
892 }
893 break;
894
895 case Opt_rootcontext:
896 if (rootcontext) {
897 rc = -EINVAL;
898 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
899 goto out_err;
900 }
901 rootcontext = match_strdup(&args[0]);
902 if (!rootcontext) {
903 rc = -ENOMEM;
904 goto out_err;
905 }
906 break;
907
908 case Opt_defcontext:
909 if (context || defcontext) {
910 rc = -EINVAL;
911 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
912 goto out_err;
913 }
914 defcontext = match_strdup(&args[0]);
915 if (!defcontext) {
916 rc = -ENOMEM;
917 goto out_err;
918 }
919 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500920 case Opt_labelsupport:
921 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500922 default:
923 rc = -EINVAL;
924 printk(KERN_WARNING "SELinux: unknown mount option\n");
925 goto out_err;
926
927 }
928 }
929
Eric Parise0007522008-03-05 10:31:54 -0500930 rc = -ENOMEM;
931 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
932 if (!opts->mnt_opts)
933 goto out_err;
934
935 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
936 if (!opts->mnt_opts_flags) {
937 kfree(opts->mnt_opts);
938 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500939 }
940
Eric Parise0007522008-03-05 10:31:54 -0500941 if (fscontext) {
942 opts->mnt_opts[num_mnt_opts] = fscontext;
943 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
944 }
945 if (context) {
946 opts->mnt_opts[num_mnt_opts] = context;
947 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
948 }
949 if (rootcontext) {
950 opts->mnt_opts[num_mnt_opts] = rootcontext;
951 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
952 }
953 if (defcontext) {
954 opts->mnt_opts[num_mnt_opts] = defcontext;
955 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
956 }
957
958 opts->num_mnt_opts = num_mnt_opts;
959 return 0;
960
Eric Parisc9180a52007-11-30 13:00:35 -0500961out_err:
962 kfree(context);
963 kfree(defcontext);
964 kfree(fscontext);
965 kfree(rootcontext);
966 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967}
Eric Parise0007522008-03-05 10:31:54 -0500968/*
969 * string mount options parsing and call set the sbsec
970 */
971static int superblock_doinit(struct super_block *sb, void *data)
972{
973 int rc = 0;
974 char *options = data;
975 struct security_mnt_opts opts;
976
977 security_init_mnt_opts(&opts);
978
979 if (!data)
980 goto out;
981
982 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
983
984 rc = selinux_parse_opts_str(options, &opts);
985 if (rc)
986 goto out_err;
987
988out:
989 rc = selinux_set_mnt_opts(sb, &opts);
990
991out_err:
992 security_free_mnt_opts(&opts);
993 return rc;
994}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
Adrian Bunk3583a712008-07-22 20:21:23 +0300996static void selinux_write_opts(struct seq_file *m,
997 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000998{
999 int i;
1000 char *prefix;
1001
1002 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001003 char *has_comma;
1004
1005 if (opts->mnt_opts[i])
1006 has_comma = strchr(opts->mnt_opts[i], ',');
1007 else
1008 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001009
1010 switch (opts->mnt_opts_flags[i]) {
1011 case CONTEXT_MNT:
1012 prefix = CONTEXT_STR;
1013 break;
1014 case FSCONTEXT_MNT:
1015 prefix = FSCONTEXT_STR;
1016 break;
1017 case ROOTCONTEXT_MNT:
1018 prefix = ROOTCONTEXT_STR;
1019 break;
1020 case DEFCONTEXT_MNT:
1021 prefix = DEFCONTEXT_STR;
1022 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001023 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001024 seq_putc(m, ',');
1025 seq_puts(m, LABELSUPP_STR);
1026 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001027 default:
1028 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001029 return;
Eric Paris2069f452008-07-04 09:47:13 +10001030 };
1031 /* we need a comma before each option */
1032 seq_putc(m, ',');
1033 seq_puts(m, prefix);
1034 if (has_comma)
1035 seq_putc(m, '\"');
1036 seq_puts(m, opts->mnt_opts[i]);
1037 if (has_comma)
1038 seq_putc(m, '\"');
1039 }
1040}
1041
1042static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1043{
1044 struct security_mnt_opts opts;
1045 int rc;
1046
1047 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001048 if (rc) {
1049 /* before policy load we may get EINVAL, don't show anything */
1050 if (rc == -EINVAL)
1051 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001052 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001053 }
Eric Paris2069f452008-07-04 09:47:13 +10001054
1055 selinux_write_opts(m, &opts);
1056
1057 security_free_mnt_opts(&opts);
1058
1059 return rc;
1060}
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062static inline u16 inode_mode_to_security_class(umode_t mode)
1063{
1064 switch (mode & S_IFMT) {
1065 case S_IFSOCK:
1066 return SECCLASS_SOCK_FILE;
1067 case S_IFLNK:
1068 return SECCLASS_LNK_FILE;
1069 case S_IFREG:
1070 return SECCLASS_FILE;
1071 case S_IFBLK:
1072 return SECCLASS_BLK_FILE;
1073 case S_IFDIR:
1074 return SECCLASS_DIR;
1075 case S_IFCHR:
1076 return SECCLASS_CHR_FILE;
1077 case S_IFIFO:
1078 return SECCLASS_FIFO_FILE;
1079
1080 }
1081
1082 return SECCLASS_FILE;
1083}
1084
James Morris13402582005-09-30 14:24:34 -04001085static inline int default_protocol_stream(int protocol)
1086{
1087 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1088}
1089
1090static inline int default_protocol_dgram(int protocol)
1091{
1092 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1093}
1094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1096{
1097 switch (family) {
1098 case PF_UNIX:
1099 switch (type) {
1100 case SOCK_STREAM:
1101 case SOCK_SEQPACKET:
1102 return SECCLASS_UNIX_STREAM_SOCKET;
1103 case SOCK_DGRAM:
1104 return SECCLASS_UNIX_DGRAM_SOCKET;
1105 }
1106 break;
1107 case PF_INET:
1108 case PF_INET6:
1109 switch (type) {
1110 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001111 if (default_protocol_stream(protocol))
1112 return SECCLASS_TCP_SOCKET;
1113 else
1114 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001116 if (default_protocol_dgram(protocol))
1117 return SECCLASS_UDP_SOCKET;
1118 else
1119 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001120 case SOCK_DCCP:
1121 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001122 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 return SECCLASS_RAWIP_SOCKET;
1124 }
1125 break;
1126 case PF_NETLINK:
1127 switch (protocol) {
1128 case NETLINK_ROUTE:
1129 return SECCLASS_NETLINK_ROUTE_SOCKET;
1130 case NETLINK_FIREWALL:
1131 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001132 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1134 case NETLINK_NFLOG:
1135 return SECCLASS_NETLINK_NFLOG_SOCKET;
1136 case NETLINK_XFRM:
1137 return SECCLASS_NETLINK_XFRM_SOCKET;
1138 case NETLINK_SELINUX:
1139 return SECCLASS_NETLINK_SELINUX_SOCKET;
1140 case NETLINK_AUDIT:
1141 return SECCLASS_NETLINK_AUDIT_SOCKET;
1142 case NETLINK_IP6_FW:
1143 return SECCLASS_NETLINK_IP6FW_SOCKET;
1144 case NETLINK_DNRTMSG:
1145 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001146 case NETLINK_KOBJECT_UEVENT:
1147 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 default:
1149 return SECCLASS_NETLINK_SOCKET;
1150 }
1151 case PF_PACKET:
1152 return SECCLASS_PACKET_SOCKET;
1153 case PF_KEY:
1154 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001155 case PF_APPLETALK:
1156 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 }
1158
1159 return SECCLASS_SOCKET;
1160}
1161
1162#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001163static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 u16 tclass,
1165 u32 *sid)
1166{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001167 int rc;
1168 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Eric Paris828dfe12008-04-17 13:17:49 -04001170 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if (!buffer)
1172 return -ENOMEM;
1173
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001174 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1175 if (IS_ERR(path))
1176 rc = PTR_ERR(path);
1177 else {
1178 /* each process gets a /proc/PID/ entry. Strip off the
1179 * PID part to get a valid selinux labeling.
1180 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1181 while (path[1] >= '0' && path[1] <= '9') {
1182 path[1] = '/';
1183 path++;
1184 }
1185 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 free_page((unsigned long)buffer);
1188 return rc;
1189}
1190#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001191static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 u16 tclass,
1193 u32 *sid)
1194{
1195 return -EINVAL;
1196}
1197#endif
1198
1199/* The inode's security attributes must be initialized before first use. */
1200static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1201{
1202 struct superblock_security_struct *sbsec = NULL;
1203 struct inode_security_struct *isec = inode->i_security;
1204 u32 sid;
1205 struct dentry *dentry;
1206#define INITCONTEXTLEN 255
1207 char *context = NULL;
1208 unsigned len = 0;
1209 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 if (isec->initialized)
1212 goto out;
1213
Eric Paris23970742006-09-25 23:32:01 -07001214 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001216 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001219 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 /* Defer initialization until selinux_complete_init,
1221 after the initial policy is loaded and the security
1222 server is ready to handle calls. */
1223 spin_lock(&sbsec->isec_lock);
1224 if (list_empty(&isec->list))
1225 list_add(&isec->list, &sbsec->isec_head);
1226 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001227 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229
1230 switch (sbsec->behavior) {
1231 case SECURITY_FS_USE_XATTR:
1232 if (!inode->i_op->getxattr) {
1233 isec->sid = sbsec->def_sid;
1234 break;
1235 }
1236
1237 /* Need a dentry, since the xattr API requires one.
1238 Life would be simpler if we could just pass the inode. */
1239 if (opt_dentry) {
1240 /* Called from d_instantiate or d_splice_alias. */
1241 dentry = dget(opt_dentry);
1242 } else {
1243 /* Called from selinux_complete_init, try to find a dentry. */
1244 dentry = d_find_alias(inode);
1245 }
1246 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001247 /*
1248 * this is can be hit on boot when a file is accessed
1249 * before the policy is loaded. When we load policy we
1250 * may find inodes that have no dentry on the
1251 * sbsec->isec_head list. No reason to complain as these
1252 * will get fixed up the next time we go through
1253 * inode_doinit with a dentry, before these inodes could
1254 * be used again by userspace.
1255 */
Eric Paris23970742006-09-25 23:32:01 -07001256 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 }
1258
1259 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001260 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 if (!context) {
1262 rc = -ENOMEM;
1263 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001264 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001266 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1268 context, len);
1269 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001270 kfree(context);
1271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 /* Need a larger buffer. Query for the right size. */
1273 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1274 NULL, 0);
1275 if (rc < 0) {
1276 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001277 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001280 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 if (!context) {
1282 rc = -ENOMEM;
1283 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001284 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001286 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 rc = inode->i_op->getxattr(dentry,
1288 XATTR_NAME_SELINUX,
1289 context, len);
1290 }
1291 dput(dentry);
1292 if (rc < 0) {
1293 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001294 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001295 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 -rc, inode->i_sb->s_id, inode->i_ino);
1297 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001298 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300 /* Map ENODATA to the default file SID */
1301 sid = sbsec->def_sid;
1302 rc = 0;
1303 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001304 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001305 sbsec->def_sid,
1306 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001308 char *dev = inode->i_sb->s_id;
1309 unsigned long ino = inode->i_ino;
1310
1311 if (rc == -EINVAL) {
1312 if (printk_ratelimit())
1313 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1314 "context=%s. This indicates you may need to relabel the inode or the "
1315 "filesystem in question.\n", ino, dev, context);
1316 } else {
1317 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1318 "returned %d for dev=%s ino=%ld\n",
1319 __func__, context, -rc, dev, ino);
1320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 kfree(context);
1322 /* Leave with the unlabeled SID */
1323 rc = 0;
1324 break;
1325 }
1326 }
1327 kfree(context);
1328 isec->sid = sid;
1329 break;
1330 case SECURITY_FS_USE_TASK:
1331 isec->sid = isec->task_sid;
1332 break;
1333 case SECURITY_FS_USE_TRANS:
1334 /* Default to the fs SID. */
1335 isec->sid = sbsec->sid;
1336
1337 /* Try to obtain a transition SID. */
1338 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001339 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1340 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001342 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 isec->sid = sid;
1344 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001345 case SECURITY_FS_USE_MNTPOINT:
1346 isec->sid = sbsec->mntpoint_sid;
1347 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001349 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 isec->sid = sbsec->sid;
1351
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001352 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001353 if (opt_dentry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001355 rc = selinux_proc_get_sid(opt_dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 isec->sclass,
1357 &sid);
1358 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001359 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 isec->sid = sid;
1361 }
1362 }
1363 break;
1364 }
1365
1366 isec->initialized = 1;
1367
Eric Paris23970742006-09-25 23:32:01 -07001368out_unlock:
1369 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370out:
1371 if (isec->sclass == SECCLASS_FILE)
1372 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return rc;
1374}
1375
1376/* Convert a Linux signal to an access vector. */
1377static inline u32 signal_to_av(int sig)
1378{
1379 u32 perm = 0;
1380
1381 switch (sig) {
1382 case SIGCHLD:
1383 /* Commonly granted from child to parent. */
1384 perm = PROCESS__SIGCHLD;
1385 break;
1386 case SIGKILL:
1387 /* Cannot be caught or ignored */
1388 perm = PROCESS__SIGKILL;
1389 break;
1390 case SIGSTOP:
1391 /* Cannot be caught or ignored */
1392 perm = PROCESS__SIGSTOP;
1393 break;
1394 default:
1395 /* All other signals. */
1396 perm = PROCESS__SIGNAL;
1397 break;
1398 }
1399
1400 return perm;
1401}
1402
David Howells275bb412008-11-14 10:39:19 +11001403/*
David Howellsd84f4f92008-11-14 10:39:23 +11001404 * Check permission between a pair of credentials
1405 * fork check, ptrace check, etc.
1406 */
1407static int cred_has_perm(const struct cred *actor,
1408 const struct cred *target,
1409 u32 perms)
1410{
1411 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1412
1413 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1414}
1415
1416/*
David Howells88e67f32008-11-14 10:39:21 +11001417 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001418 * fork check, ptrace check, etc.
1419 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001420 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001421 */
1422static int task_has_perm(const struct task_struct *tsk1,
1423 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 u32 perms)
1425{
David Howells275bb412008-11-14 10:39:19 +11001426 const struct task_security_struct *__tsec1, *__tsec2;
1427 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
David Howells275bb412008-11-14 10:39:19 +11001429 rcu_read_lock();
1430 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1431 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1432 rcu_read_unlock();
1433 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434}
1435
David Howells3b11a1d2008-11-14 10:39:26 +11001436/*
1437 * Check permission between current and another task, e.g. signal checks,
1438 * fork check, ptrace check, etc.
1439 * current is the actor and tsk2 is the target
1440 * - this uses current's subjective creds
1441 */
1442static int current_has_perm(const struct task_struct *tsk,
1443 u32 perms)
1444{
1445 u32 sid, tsid;
1446
1447 sid = current_sid();
1448 tsid = task_sid(tsk);
1449 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1450}
1451
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001452#if CAP_LAST_CAP > 63
1453#error Fix SELinux to handle capabilities > 63.
1454#endif
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001457static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001458 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459{
Thomas Liu2bf49692009-07-14 12:14:09 -04001460 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001461 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001462 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001463 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001464 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001465 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Eric Paris50c205f2012-04-04 15:01:43 -04001467 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 ad.u.cap = cap;
1469
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001470 switch (CAP_TO_INDEX(cap)) {
1471 case 0:
1472 sclass = SECCLASS_CAPABILITY;
1473 break;
1474 case 1:
1475 sclass = SECCLASS_CAPABILITY2;
1476 break;
1477 default:
1478 printk(KERN_ERR
1479 "SELinux: out of range capability %d\n", cap);
1480 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001481 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001482 }
Eric Paris06112162008-11-11 22:02:50 +11001483
David Howells275bb412008-11-14 10:39:19 +11001484 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001485 if (audit == SECURITY_CAP_AUDIT) {
1486 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1487 if (rc2)
1488 return rc2;
1489 }
Eric Paris06112162008-11-11 22:02:50 +11001490 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491}
1492
1493/* Check whether a task is allowed to use a system operation. */
1494static int task_has_system(struct task_struct *tsk,
1495 u32 perms)
1496{
David Howells275bb412008-11-14 10:39:19 +11001497 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
David Howells275bb412008-11-14 10:39:19 +11001499 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 SECCLASS_SYSTEM, perms, NULL);
1501}
1502
1503/* Check whether a task has a particular permission to an inode.
1504 The 'adp' parameter is optional and allows other audit
1505 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001506static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 struct inode *inode,
1508 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001509 struct common_audit_data *adp,
1510 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001513 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
David Howellse0e81732009-09-02 09:13:40 +01001515 validate_creds(cred);
1516
Eric Paris828dfe12008-04-17 13:17:49 -04001517 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001518 return 0;
1519
David Howells88e67f32008-11-14 10:39:21 +11001520 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 isec = inode->i_security;
1522
Eric Paris9ade0cf2011-04-25 16:26:29 -04001523 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524}
1525
1526/* Same as inode_has_perm, but pass explicit audit data containing
1527 the dentry to help the auditing code to more easily generate the
1528 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001529static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 struct dentry *dentry,
1531 u32 av)
1532{
1533 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001534 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001535
Eric Paris50c205f2012-04-04 15:01:43 -04001536 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001537 ad.u.dentry = dentry;
1538 return inode_has_perm(cred, inode, av, &ad, 0);
1539}
1540
1541/* Same as inode_has_perm, but pass explicit audit data containing
1542 the path to help the auditing code to more easily generate the
1543 pathname if needed. */
1544static inline int path_has_perm(const struct cred *cred,
1545 struct path *path,
1546 u32 av)
1547{
1548 struct inode *inode = path->dentry->d_inode;
1549 struct common_audit_data ad;
1550
Eric Paris50c205f2012-04-04 15:01:43 -04001551 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001552 ad.u.path = *path;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001553 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554}
1555
1556/* Check whether a task can use an open file descriptor to
1557 access an inode in a given way. Check access to the
1558 descriptor itself, and then use dentry_has_perm to
1559 check a particular permission to the file.
1560 Access to the descriptor is implicitly granted if it
1561 has the same SID as the process. If av is zero, then
1562 access to the file is not checked, e.g. for cases
1563 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001564static int file_has_perm(const struct cred *cred,
1565 struct file *file,
1566 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001569 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001570 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001571 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 int rc;
1573
Eric Paris50c205f2012-04-04 15:01:43 -04001574 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001575 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
David Howells275bb412008-11-14 10:39:19 +11001577 if (sid != fsec->sid) {
1578 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 SECCLASS_FD,
1580 FD__USE,
1581 &ad);
1582 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001583 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 }
1585
1586 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001587 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001589 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
David Howells88e67f32008-11-14 10:39:21 +11001591out:
1592 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593}
1594
1595/* Check whether a task can create a file. */
1596static int may_create(struct inode *dir,
1597 struct dentry *dentry,
1598 u16 tclass)
1599{
Paul Moore5fb49872010-04-22 14:46:19 -04001600 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 struct inode_security_struct *dsec;
1602 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001603 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001604 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 int rc;
1606
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 dsec = dir->i_security;
1608 sbsec = dir->i_sb->s_security;
1609
David Howells275bb412008-11-14 10:39:19 +11001610 sid = tsec->sid;
1611 newsid = tsec->create_sid;
1612
Eric Paris50c205f2012-04-04 15:01:43 -04001613 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001614 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
David Howells275bb412008-11-14 10:39:19 +11001616 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 DIR__ADD_NAME | DIR__SEARCH,
1618 &ad);
1619 if (rc)
1620 return rc;
1621
Eric Paris12f348b2012-10-09 10:56:25 -04001622 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001623 rc = security_transition_sid(sid, dsec->sid, tclass,
1624 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 if (rc)
1626 return rc;
1627 }
1628
David Howells275bb412008-11-14 10:39:19 +11001629 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (rc)
1631 return rc;
1632
1633 return avc_has_perm(newsid, sbsec->sid,
1634 SECCLASS_FILESYSTEM,
1635 FILESYSTEM__ASSOCIATE, &ad);
1636}
1637
Michael LeMay4eb582c2006-06-26 00:24:57 -07001638/* Check whether a task can create a key. */
1639static int may_create_key(u32 ksid,
1640 struct task_struct *ctx)
1641{
David Howells275bb412008-11-14 10:39:19 +11001642 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001643
David Howells275bb412008-11-14 10:39:19 +11001644 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001645}
1646
Eric Paris828dfe12008-04-17 13:17:49 -04001647#define MAY_LINK 0
1648#define MAY_UNLINK 1
1649#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
1651/* Check whether a task can link, unlink, or rmdir a file/directory. */
1652static int may_link(struct inode *dir,
1653 struct dentry *dentry,
1654 int kind)
1655
1656{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001658 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001659 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 u32 av;
1661 int rc;
1662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 dsec = dir->i_security;
1664 isec = dentry->d_inode->i_security;
1665
Eric Paris50c205f2012-04-04 15:01:43 -04001666 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001667 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 av = DIR__SEARCH;
1670 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001671 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 if (rc)
1673 return rc;
1674
1675 switch (kind) {
1676 case MAY_LINK:
1677 av = FILE__LINK;
1678 break;
1679 case MAY_UNLINK:
1680 av = FILE__UNLINK;
1681 break;
1682 case MAY_RMDIR:
1683 av = DIR__RMDIR;
1684 break;
1685 default:
Eric Paris744ba352008-04-17 11:52:44 -04001686 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1687 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 return 0;
1689 }
1690
David Howells275bb412008-11-14 10:39:19 +11001691 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 return rc;
1693}
1694
1695static inline int may_rename(struct inode *old_dir,
1696 struct dentry *old_dentry,
1697 struct inode *new_dir,
1698 struct dentry *new_dentry)
1699{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001701 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001702 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 u32 av;
1704 int old_is_dir, new_is_dir;
1705 int rc;
1706
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 old_dsec = old_dir->i_security;
1708 old_isec = old_dentry->d_inode->i_security;
1709 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1710 new_dsec = new_dir->i_security;
1711
Eric Paris50c205f2012-04-04 15:01:43 -04001712 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
Eric Parisa2694342011-04-25 13:10:27 -04001714 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001715 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1717 if (rc)
1718 return rc;
David Howells275bb412008-11-14 10:39:19 +11001719 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 old_isec->sclass, FILE__RENAME, &ad);
1721 if (rc)
1722 return rc;
1723 if (old_is_dir && new_dir != old_dir) {
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, DIR__REPARENT, &ad);
1726 if (rc)
1727 return rc;
1728 }
1729
Eric Parisa2694342011-04-25 13:10:27 -04001730 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 av = DIR__ADD_NAME | DIR__SEARCH;
1732 if (new_dentry->d_inode)
1733 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001734 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if (rc)
1736 return rc;
1737 if (new_dentry->d_inode) {
1738 new_isec = new_dentry->d_inode->i_security;
1739 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001740 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 new_isec->sclass,
1742 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1743 if (rc)
1744 return rc;
1745 }
1746
1747 return 0;
1748}
1749
1750/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001751static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 struct super_block *sb,
1753 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001754 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001757 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001760 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761}
1762
1763/* Convert a Linux mode and permission mask to an access vector. */
1764static inline u32 file_mask_to_av(int mode, int mask)
1765{
1766 u32 av = 0;
1767
Al Virodba19c62011-07-25 20:49:29 -04001768 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 if (mask & MAY_EXEC)
1770 av |= FILE__EXECUTE;
1771 if (mask & MAY_READ)
1772 av |= FILE__READ;
1773
1774 if (mask & MAY_APPEND)
1775 av |= FILE__APPEND;
1776 else if (mask & MAY_WRITE)
1777 av |= FILE__WRITE;
1778
1779 } else {
1780 if (mask & MAY_EXEC)
1781 av |= DIR__SEARCH;
1782 if (mask & MAY_WRITE)
1783 av |= DIR__WRITE;
1784 if (mask & MAY_READ)
1785 av |= DIR__READ;
1786 }
1787
1788 return av;
1789}
1790
1791/* Convert a Linux file to an access vector. */
1792static inline u32 file_to_av(struct file *file)
1793{
1794 u32 av = 0;
1795
1796 if (file->f_mode & FMODE_READ)
1797 av |= FILE__READ;
1798 if (file->f_mode & FMODE_WRITE) {
1799 if (file->f_flags & O_APPEND)
1800 av |= FILE__APPEND;
1801 else
1802 av |= FILE__WRITE;
1803 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001804 if (!av) {
1805 /*
1806 * Special file opened with flags 3 for ioctl-only use.
1807 */
1808 av = FILE__IOCTL;
1809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
1811 return av;
1812}
1813
Eric Paris8b6a5a32008-10-29 17:06:46 -04001814/*
1815 * Convert a file to an access vector and include the correct open
1816 * open permission.
1817 */
1818static inline u32 open_file_to_av(struct file *file)
1819{
1820 u32 av = file_to_av(file);
1821
Eric Paris49b7b8d2010-07-23 11:44:09 -04001822 if (selinux_policycap_openperm)
1823 av |= FILE__OPEN;
1824
Eric Paris8b6a5a32008-10-29 17:06:46 -04001825 return av;
1826}
1827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828/* Hook functions begin here. */
1829
Ingo Molnar9e488582009-05-07 19:26:19 +10001830static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001831 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 int rc;
1834
Ingo Molnar9e488582009-05-07 19:26:19 +10001835 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 if (rc)
1837 return rc;
1838
Eric Paris69f594a2012-01-03 12:25:15 -05001839 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001840 u32 sid = current_sid();
1841 u32 csid = task_sid(child);
1842 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001843 }
1844
David Howells3b11a1d2008-11-14 10:39:26 +11001845 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001846}
1847
1848static int selinux_ptrace_traceme(struct task_struct *parent)
1849{
1850 int rc;
1851
Eric Paris200ac532009-02-12 15:01:04 -05001852 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001853 if (rc)
1854 return rc;
1855
1856 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857}
1858
1859static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001860 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
1862 int error;
1863
David Howells3b11a1d2008-11-14 10:39:26 +11001864 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 if (error)
1866 return error;
1867
Eric Paris200ac532009-02-12 15:01:04 -05001868 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869}
1870
David Howellsd84f4f92008-11-14 10:39:23 +11001871static int selinux_capset(struct cred *new, const struct cred *old,
1872 const kernel_cap_t *effective,
1873 const kernel_cap_t *inheritable,
1874 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875{
1876 int error;
1877
Eric Paris200ac532009-02-12 15:01:04 -05001878 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001879 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 if (error)
1881 return error;
1882
David Howellsd84f4f92008-11-14 10:39:23 +11001883 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884}
1885
James Morris5626d3e2009-01-30 10:05:06 +11001886/*
1887 * (This comment used to live with the selinux_task_setuid hook,
1888 * which was removed).
1889 *
1890 * Since setuid only affects the current process, and since the SELinux
1891 * controls are not based on the Linux identity attributes, SELinux does not
1892 * need to control this operation. However, SELinux does control the use of
1893 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1894 */
1895
Eric Paris6a9de492012-01-03 12:25:14 -05001896static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1897 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
1899 int rc;
1900
Eric Paris6a9de492012-01-03 12:25:14 -05001901 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 if (rc)
1903 return rc;
1904
Eric Paris6a9de492012-01-03 12:25:14 -05001905 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906}
1907
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1909{
David Howells88e67f32008-11-14 10:39:21 +11001910 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 int rc = 0;
1912
1913 if (!sb)
1914 return 0;
1915
1916 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001917 case Q_SYNC:
1918 case Q_QUOTAON:
1919 case Q_QUOTAOFF:
1920 case Q_SETINFO:
1921 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001922 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001923 break;
1924 case Q_GETFMT:
1925 case Q_GETINFO:
1926 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001927 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001928 break;
1929 default:
1930 rc = 0; /* let the kernel handle invalid cmds */
1931 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
1933 return rc;
1934}
1935
1936static int selinux_quota_on(struct dentry *dentry)
1937{
David Howells88e67f32008-11-14 10:39:21 +11001938 const struct cred *cred = current_cred();
1939
Eric Paris2875fa02011-04-28 16:04:24 -04001940 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941}
1942
Eric Paris12b30522010-11-15 18:36:29 -05001943static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944{
1945 int rc;
1946
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08001948 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
1949 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001950 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1951 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001952 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
1953 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
1954 /* Set level of messages printed to console */
1955 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04001956 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1957 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001958 case SYSLOG_ACTION_CLOSE: /* Close log */
1959 case SYSLOG_ACTION_OPEN: /* Open log */
1960 case SYSLOG_ACTION_READ: /* Read from log */
1961 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
1962 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001963 default:
1964 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1965 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 }
1967 return rc;
1968}
1969
1970/*
1971 * Check that a process has enough memory to allocate a new virtual
1972 * mapping. 0 means there is enough memory for the allocation to
1973 * succeed and -ENOMEM implies there is not.
1974 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 * Do not audit the selinux permission check, as this is applied to all
1976 * processes that allocate mappings.
1977 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001978static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979{
1980 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
Eric Paris6a9de492012-01-03 12:25:14 -05001982 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00001983 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 if (rc == 0)
1985 cap_sys_admin = 1;
1986
Alan Cox34b4e4a2007-08-22 14:01:28 -07001987 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988}
1989
1990/* binprm security operations */
1991
David Howellsa6f76f22008-11-14 10:39:24 +11001992static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993{
David Howellsa6f76f22008-11-14 10:39:24 +11001994 const struct task_security_struct *old_tsec;
1995 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001997 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05001998 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 int rc;
2000
Eric Paris200ac532009-02-12 15:01:04 -05002001 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 if (rc)
2003 return rc;
2004
David Howellsa6f76f22008-11-14 10:39:24 +11002005 /* SELinux context only depends on initial program or script and not
2006 * the script interpreter */
2007 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 return 0;
2009
David Howellsa6f76f22008-11-14 10:39:24 +11002010 old_tsec = current_security();
2011 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 isec = inode->i_security;
2013
2014 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002015 new_tsec->sid = old_tsec->sid;
2016 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Michael LeMay28eba5b2006-06-27 02:53:42 -07002018 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002019 new_tsec->create_sid = 0;
2020 new_tsec->keycreate_sid = 0;
2021 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
David Howellsa6f76f22008-11-14 10:39:24 +11002023 if (old_tsec->exec_sid) {
2024 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002026 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002027
2028 /*
2029 * Minimize confusion: if no_new_privs and a transition is
2030 * explicitly requested, then fail the exec.
2031 */
2032 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2033 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 } else {
2035 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002036 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002037 SECCLASS_PROCESS, NULL,
2038 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 if (rc)
2040 return rc;
2041 }
2042
Eric Paris50c205f2012-04-04 15:01:43 -04002043 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002044 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002046 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2047 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002048 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
David Howellsa6f76f22008-11-14 10:39:24 +11002050 if (new_tsec->sid == old_tsec->sid) {
2051 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2053 if (rc)
2054 return rc;
2055 } else {
2056 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002057 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2059 if (rc)
2060 return rc;
2061
David Howellsa6f76f22008-11-14 10:39:24 +11002062 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2064 if (rc)
2065 return rc;
2066
David Howellsa6f76f22008-11-14 10:39:24 +11002067 /* Check for shared state */
2068 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2069 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2070 SECCLASS_PROCESS, PROCESS__SHARE,
2071 NULL);
2072 if (rc)
2073 return -EPERM;
2074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
David Howellsa6f76f22008-11-14 10:39:24 +11002076 /* Make sure that anyone attempting to ptrace over a task that
2077 * changes its SID has the appropriate permit */
2078 if (bprm->unsafe &
2079 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2080 struct task_struct *tracer;
2081 struct task_security_struct *sec;
2082 u32 ptsid = 0;
2083
2084 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002085 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002086 if (likely(tracer != NULL)) {
2087 sec = __task_cred(tracer)->security;
2088 ptsid = sec->sid;
2089 }
2090 rcu_read_unlock();
2091
2092 if (ptsid != 0) {
2093 rc = avc_has_perm(ptsid, new_tsec->sid,
2094 SECCLASS_PROCESS,
2095 PROCESS__PTRACE, NULL);
2096 if (rc)
2097 return -EPERM;
2098 }
2099 }
2100
2101 /* Clear any possibly unsafe personality bits on exec: */
2102 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
2104
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 return 0;
2106}
2107
Eric Paris828dfe12008-04-17 13:17:49 -04002108static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109{
Paul Moore5fb49872010-04-22 14:46:19 -04002110 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002111 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 int atsecure = 0;
2113
David Howells275bb412008-11-14 10:39:19 +11002114 sid = tsec->sid;
2115 osid = tsec->osid;
2116
2117 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 /* Enable secure mode for SIDs transitions unless
2119 the noatsecure permission is granted between
2120 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002121 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002122 SECCLASS_PROCESS,
2123 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125
Eric Paris200ac532009-02-12 15:01:04 -05002126 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127}
2128
Al Viroc3c073f2012-08-21 22:32:06 -04002129static int match_file(const void *p, struct file *file, unsigned fd)
2130{
2131 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2132}
2133
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002135static inline void flush_unauthorized_files(const struct cred *cred,
2136 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002139 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002140 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002141 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002143 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002145 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002146 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002147 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 /* Revalidate access to controlling tty.
Eric Paris602a8dd2012-04-04 15:01:42 -04002150 Use path_has_perm on the tty path directly rather
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 than using file_has_perm, as this particular open
2152 file may belong to another process and we are only
2153 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002154 file_priv = list_first_entry(&tty->tty_files,
2155 struct tty_file_private, list);
2156 file = file_priv->file;
Eric Paris602a8dd2012-04-04 15:01:42 -04002157 if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002158 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002160 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002161 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002163 /* Reset controlling tty. */
2164 if (drop_tty)
2165 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
2167 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002168 n = iterate_fd(files, 0, match_file, cred);
2169 if (!n) /* none found? */
2170 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
Al Viroc3c073f2012-08-21 22:32:06 -04002172 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002173 if (IS_ERR(devnull))
2174 devnull = NULL;
2175 /* replace all the matching ones with this */
2176 do {
2177 replace_fd(n - 1, devnull, 0);
2178 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2179 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002180 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181}
2182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183/*
David Howellsa6f76f22008-11-14 10:39:24 +11002184 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 */
David Howellsa6f76f22008-11-14 10:39:24 +11002186static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187{
David Howellsa6f76f22008-11-14 10:39:24 +11002188 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 int rc, i;
2191
David Howellsa6f76f22008-11-14 10:39:24 +11002192 new_tsec = bprm->cred->security;
2193 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 return;
2195
2196 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002197 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
David Howellsa6f76f22008-11-14 10:39:24 +11002199 /* Always clear parent death signal on SID transitions. */
2200 current->pdeath_signal = 0;
2201
2202 /* Check whether the new SID can inherit resource limits from the old
2203 * SID. If not, reset all soft limits to the lower of the current
2204 * task's hard limit and the init task's soft limit.
2205 *
2206 * Note that the setting of hard limits (even to lower them) can be
2207 * controlled by the setrlimit check. The inclusion of the init task's
2208 * soft limit into the computation is to avoid resetting soft limits
2209 * higher than the default soft limit for cases where the default is
2210 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2211 */
2212 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2213 PROCESS__RLIMITINH, NULL);
2214 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002215 /* protect against do_prlimit() */
2216 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002217 for (i = 0; i < RLIM_NLIMITS; i++) {
2218 rlim = current->signal->rlim + i;
2219 initrlim = init_task.signal->rlim + i;
2220 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2221 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002222 task_unlock(current);
2223 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002224 }
2225}
2226
2227/*
2228 * Clean up the process immediately after the installation of new credentials
2229 * due to exec
2230 */
2231static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2232{
2233 const struct task_security_struct *tsec = current_security();
2234 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002235 u32 osid, sid;
2236 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002237
David Howellsa6f76f22008-11-14 10:39:24 +11002238 osid = tsec->osid;
2239 sid = tsec->sid;
2240
2241 if (sid == osid)
2242 return;
2243
2244 /* Check whether the new SID can inherit signal state from the old SID.
2245 * If not, clear itimers to avoid subsequent signal generation and
2246 * flush and unblock signals.
2247 *
2248 * This must occur _after_ the task SID has been updated so that any
2249 * kill done after the flush will be checked against the new SID.
2250 */
2251 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 if (rc) {
2253 memset(&itimer, 0, sizeof itimer);
2254 for (i = 0; i < 3; i++)
2255 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002257 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2258 __flush_signals(current);
2259 flush_signal_handlers(current, 1);
2260 sigemptyset(&current->blocked);
2261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 spin_unlock_irq(&current->sighand->siglock);
2263 }
2264
David Howellsa6f76f22008-11-14 10:39:24 +11002265 /* Wake up the parent if it is waiting so that it can recheck
2266 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002267 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002268 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002269 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270}
2271
2272/* superblock security operations */
2273
2274static int selinux_sb_alloc_security(struct super_block *sb)
2275{
2276 return superblock_alloc_security(sb);
2277}
2278
2279static void selinux_sb_free_security(struct super_block *sb)
2280{
2281 superblock_free_security(sb);
2282}
2283
2284static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2285{
2286 if (plen > olen)
2287 return 0;
2288
2289 return !memcmp(prefix, option, plen);
2290}
2291
2292static inline int selinux_option(char *option, int len)
2293{
Eric Paris832cbd92008-04-01 13:24:09 -04002294 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2295 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2296 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002297 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2298 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299}
2300
2301static inline void take_option(char **to, char *from, int *first, int len)
2302{
2303 if (!*first) {
2304 **to = ',';
2305 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002306 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 *first = 0;
2308 memcpy(*to, from, len);
2309 *to += len;
2310}
2311
Eric Paris828dfe12008-04-17 13:17:49 -04002312static inline void take_selinux_option(char **to, char *from, int *first,
2313 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002314{
2315 int current_size = 0;
2316
2317 if (!*first) {
2318 **to = '|';
2319 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002320 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002321 *first = 0;
2322
2323 while (current_size < len) {
2324 if (*from != '"') {
2325 **to = *from;
2326 *to += 1;
2327 }
2328 from += 1;
2329 current_size += 1;
2330 }
2331}
2332
Eric Parise0007522008-03-05 10:31:54 -05002333static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
2335 int fnosec, fsec, rc = 0;
2336 char *in_save, *in_curr, *in_end;
2337 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002338 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
2340 in_curr = orig;
2341 sec_curr = copy;
2342
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2344 if (!nosec) {
2345 rc = -ENOMEM;
2346 goto out;
2347 }
2348
2349 nosec_save = nosec;
2350 fnosec = fsec = 1;
2351 in_save = in_end = orig;
2352
2353 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002354 if (*in_end == '"')
2355 open_quote = !open_quote;
2356 if ((*in_end == ',' && open_quote == 0) ||
2357 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 int len = in_end - in_curr;
2359
2360 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002361 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 else
2363 take_option(&nosec, in_curr, &fnosec, len);
2364
2365 in_curr = in_end + 1;
2366 }
2367 } while (*in_end++);
2368
Eric Paris6931dfc2005-06-30 02:58:51 -07002369 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002370 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371out:
2372 return rc;
2373}
2374
Eric Paris026eb162011-03-03 16:09:14 -05002375static int selinux_sb_remount(struct super_block *sb, void *data)
2376{
2377 int rc, i, *flags;
2378 struct security_mnt_opts opts;
2379 char *secdata, **mount_options;
2380 struct superblock_security_struct *sbsec = sb->s_security;
2381
2382 if (!(sbsec->flags & SE_SBINITIALIZED))
2383 return 0;
2384
2385 if (!data)
2386 return 0;
2387
2388 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2389 return 0;
2390
2391 security_init_mnt_opts(&opts);
2392 secdata = alloc_secdata();
2393 if (!secdata)
2394 return -ENOMEM;
2395 rc = selinux_sb_copy_data(data, secdata);
2396 if (rc)
2397 goto out_free_secdata;
2398
2399 rc = selinux_parse_opts_str(secdata, &opts);
2400 if (rc)
2401 goto out_free_secdata;
2402
2403 mount_options = opts.mnt_opts;
2404 flags = opts.mnt_opts_flags;
2405
2406 for (i = 0; i < opts.num_mnt_opts; i++) {
2407 u32 sid;
2408 size_t len;
2409
Eric Paris12f348b2012-10-09 10:56:25 -04002410 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002411 continue;
2412 len = strlen(mount_options[i]);
2413 rc = security_context_to_sid(mount_options[i], len, &sid);
2414 if (rc) {
2415 printk(KERN_WARNING "SELinux: security_context_to_sid"
2416 "(%s) failed for (dev %s, type %s) errno=%d\n",
2417 mount_options[i], sb->s_id, sb->s_type->name, rc);
2418 goto out_free_opts;
2419 }
2420 rc = -EINVAL;
2421 switch (flags[i]) {
2422 case FSCONTEXT_MNT:
2423 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2424 goto out_bad_option;
2425 break;
2426 case CONTEXT_MNT:
2427 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2428 goto out_bad_option;
2429 break;
2430 case ROOTCONTEXT_MNT: {
2431 struct inode_security_struct *root_isec;
2432 root_isec = sb->s_root->d_inode->i_security;
2433
2434 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2435 goto out_bad_option;
2436 break;
2437 }
2438 case DEFCONTEXT_MNT:
2439 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2440 goto out_bad_option;
2441 break;
2442 default:
2443 goto out_free_opts;
2444 }
2445 }
2446
2447 rc = 0;
2448out_free_opts:
2449 security_free_mnt_opts(&opts);
2450out_free_secdata:
2451 free_secdata(secdata);
2452 return rc;
2453out_bad_option:
2454 printk(KERN_WARNING "SELinux: unable to change security options "
2455 "during remount (dev %s, type=%s)\n", sb->s_id,
2456 sb->s_type->name);
2457 goto out_free_opts;
2458}
2459
James Morris12204e22008-12-19 10:44:42 +11002460static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461{
David Howells88e67f32008-11-14 10:39:21 +11002462 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002463 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 int rc;
2465
2466 rc = superblock_doinit(sb, data);
2467 if (rc)
2468 return rc;
2469
James Morris74192242008-12-19 11:41:10 +11002470 /* Allow all mounts performed by the kernel */
2471 if (flags & MS_KERNMOUNT)
2472 return 0;
2473
Eric Paris50c205f2012-04-04 15:01:43 -04002474 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002475 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002476 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477}
2478
David Howells726c3342006-06-23 02:02:58 -07002479static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480{
David Howells88e67f32008-11-14 10:39:21 +11002481 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002482 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Eric Paris50c205f2012-04-04 15:01:43 -04002484 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002485 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002486 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487}
2488
Al Viro808d4e32012-10-11 11:42:01 -04002489static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002490 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002491 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002492 unsigned long flags,
2493 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494{
David Howells88e67f32008-11-14 10:39:21 +11002495 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
2497 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002498 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002499 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 else
Eric Paris2875fa02011-04-28 16:04:24 -04002501 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502}
2503
2504static int selinux_umount(struct vfsmount *mnt, int flags)
2505{
David Howells88e67f32008-11-14 10:39:21 +11002506 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507
David Howells88e67f32008-11-14 10:39:21 +11002508 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002509 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510}
2511
2512/* inode security operations */
2513
2514static int selinux_inode_alloc_security(struct inode *inode)
2515{
2516 return inode_alloc_security(inode);
2517}
2518
2519static void selinux_inode_free_security(struct inode *inode)
2520{
2521 inode_free_security(inode);
2522}
2523
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002524static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002525 const struct qstr *qstr, char **name,
2526 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002527{
Paul Moore5fb49872010-04-22 14:46:19 -04002528 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002529 struct inode_security_struct *dsec;
2530 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002531 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002532 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002533 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002534
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002535 dsec = dir->i_security;
2536 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002537
David Howells275bb412008-11-14 10:39:19 +11002538 sid = tsec->sid;
2539 newsid = tsec->create_sid;
2540
Eric Paris415103f2010-12-02 16:13:40 -05002541 if ((sbsec->flags & SE_SBINITIALIZED) &&
2542 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2543 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002544 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002545 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002546 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002547 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002548 if (rc) {
2549 printk(KERN_WARNING "%s: "
2550 "security_transition_sid failed, rc=%d (dev=%s "
2551 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002552 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002553 -rc, inode->i_sb->s_id, inode->i_ino);
2554 return rc;
2555 }
2556 }
2557
Eric Paris296fddf2006-09-25 23:32:00 -07002558 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002559 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002560 struct inode_security_struct *isec = inode->i_security;
2561 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2562 isec->sid = newsid;
2563 isec->initialized = 1;
2564 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002565
Eric Paris12f348b2012-10-09 10:56:25 -04002566 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002567 return -EOPNOTSUPP;
2568
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002569 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002570 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002571 if (!namep)
2572 return -ENOMEM;
2573 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002574 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002575
2576 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002577 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002578 if (rc) {
2579 kfree(namep);
2580 return rc;
2581 }
2582 *value = context;
2583 *len = clen;
2584 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002585
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002586 return 0;
2587}
2588
Al Viro4acdaf22011-07-26 01:42:34 -04002589static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
2591 return may_create(dir, dentry, SECCLASS_FILE);
2592}
2593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2595{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 return may_link(dir, old_dentry, MAY_LINK);
2597}
2598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2600{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 return may_link(dir, dentry, MAY_UNLINK);
2602}
2603
2604static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2605{
2606 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2607}
2608
Al Viro18bb1db2011-07-26 01:41:39 -04002609static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610{
2611 return may_create(dir, dentry, SECCLASS_DIR);
2612}
2613
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2615{
2616 return may_link(dir, dentry, MAY_RMDIR);
2617}
2618
Al Viro1a67aaf2011-07-26 01:52:52 -04002619static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2622}
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002625 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
2627 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2628}
2629
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630static int selinux_inode_readlink(struct dentry *dentry)
2631{
David Howells88e67f32008-11-14 10:39:21 +11002632 const struct cred *cred = current_cred();
2633
Eric Paris2875fa02011-04-28 16:04:24 -04002634 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635}
2636
2637static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2638{
David Howells88e67f32008-11-14 10:39:21 +11002639 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Eric Paris2875fa02011-04-28 16:04:24 -04002641 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643
Eric Parisd4cf970d2012-04-04 15:01:42 -04002644static noinline int audit_inode_permission(struct inode *inode,
2645 u32 perms, u32 audited, u32 denied,
2646 unsigned flags)
2647{
2648 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002649 struct inode_security_struct *isec = inode->i_security;
2650 int rc;
2651
Eric Paris50c205f2012-04-04 15:01:43 -04002652 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002653 ad.u.inode = inode;
2654
2655 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
2656 audited, denied, &ad, flags);
2657 if (rc)
2658 return rc;
2659 return 0;
2660}
2661
Al Viroe74f71e2011-06-20 19:38:15 -04002662static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663{
David Howells88e67f32008-11-14 10:39:21 +11002664 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002665 u32 perms;
2666 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002667 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002668 struct inode_security_struct *isec;
2669 u32 sid;
2670 struct av_decision avd;
2671 int rc, rc2;
2672 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Eric Parisb782e0a2010-07-23 11:44:03 -04002674 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002675 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2676
Eric Parisb782e0a2010-07-23 11:44:03 -04002677 /* No permission to check. Existence test. */
2678 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680
Eric Paris2e334052012-04-04 15:01:42 -04002681 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002682
Eric Paris2e334052012-04-04 15:01:42 -04002683 if (unlikely(IS_PRIVATE(inode)))
2684 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002685
2686 perms = file_mask_to_av(inode->i_mode, mask);
2687
Eric Paris2e334052012-04-04 15:01:42 -04002688 sid = cred_sid(cred);
2689 isec = inode->i_security;
2690
2691 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2692 audited = avc_audit_required(perms, &avd, rc,
2693 from_access ? FILE__AUDIT_ACCESS : 0,
2694 &denied);
2695 if (likely(!audited))
2696 return rc;
2697
Eric Parisd4cf970d2012-04-04 15:01:42 -04002698 rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002699 if (rc2)
2700 return rc2;
2701 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702}
2703
2704static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2705{
David Howells88e67f32008-11-14 10:39:21 +11002706 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002707 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002708 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002710 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2711 if (ia_valid & ATTR_FORCE) {
2712 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2713 ATTR_FORCE);
2714 if (!ia_valid)
2715 return 0;
2716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002718 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2719 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002720 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721
Eric Paris3d2195c2012-07-06 14:13:30 -04002722 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002723 av |= FILE__OPEN;
2724
2725 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726}
2727
2728static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2729{
David Howells88e67f32008-11-14 10:39:21 +11002730 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002731 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002732
Eric Paris2875fa02011-04-28 16:04:24 -04002733 path.dentry = dentry;
2734 path.mnt = mnt;
2735
2736 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737}
2738
David Howells8f0cfa52008-04-29 00:59:41 -07002739static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002740{
David Howells88e67f32008-11-14 10:39:21 +11002741 const struct cred *cred = current_cred();
2742
Serge E. Hallynb5376772007-10-16 23:31:36 -07002743 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2744 sizeof XATTR_SECURITY_PREFIX - 1)) {
2745 if (!strcmp(name, XATTR_NAME_CAPS)) {
2746 if (!capable(CAP_SETFCAP))
2747 return -EPERM;
2748 } else if (!capable(CAP_SYS_ADMIN)) {
2749 /* A different attribute in the security namespace.
2750 Restrict to administrator. */
2751 return -EPERM;
2752 }
2753 }
2754
2755 /* Not an attribute we recognize, so just check the
2756 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002757 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002758}
2759
David Howells8f0cfa52008-04-29 00:59:41 -07002760static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2761 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 struct inode *inode = dentry->d_inode;
2764 struct inode_security_struct *isec = inode->i_security;
2765 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002766 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002767 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 int rc = 0;
2769
Serge E. Hallynb5376772007-10-16 23:31:36 -07002770 if (strcmp(name, XATTR_NAME_SELINUX))
2771 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
2773 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002774 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 return -EOPNOTSUPP;
2776
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002777 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 return -EPERM;
2779
Eric Paris50c205f2012-04-04 15:01:43 -04002780 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002781 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
David Howells275bb412008-11-14 10:39:19 +11002783 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 FILE__RELABELFROM, &ad);
2785 if (rc)
2786 return rc;
2787
2788 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002789 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002790 if (!capable(CAP_MAC_ADMIN)) {
2791 struct audit_buffer *ab;
2792 size_t audit_size;
2793 const char *str;
2794
2795 /* We strip a nul only if it is at the end, otherwise the
2796 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002797 if (value) {
2798 str = value;
2799 if (str[size - 1] == '\0')
2800 audit_size = size - 1;
2801 else
2802 audit_size = size;
2803 } else {
2804 str = "";
2805 audit_size = 0;
2806 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002807 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2808 audit_log_format(ab, "op=setxattr invalid_context=");
2809 audit_log_n_untrustedstring(ab, value, audit_size);
2810 audit_log_end(ab);
2811
Stephen Smalley12b29f32008-05-07 13:03:20 -04002812 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002813 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002814 rc = security_context_to_sid_force(value, size, &newsid);
2815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 if (rc)
2817 return rc;
2818
David Howells275bb412008-11-14 10:39:19 +11002819 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 FILE__RELABELTO, &ad);
2821 if (rc)
2822 return rc;
2823
David Howells275bb412008-11-14 10:39:19 +11002824 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002825 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 if (rc)
2827 return rc;
2828
2829 return avc_has_perm(newsid,
2830 sbsec->sid,
2831 SECCLASS_FILESYSTEM,
2832 FILESYSTEM__ASSOCIATE,
2833 &ad);
2834}
2835
David Howells8f0cfa52008-04-29 00:59:41 -07002836static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002837 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002838 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839{
2840 struct inode *inode = dentry->d_inode;
2841 struct inode_security_struct *isec = inode->i_security;
2842 u32 newsid;
2843 int rc;
2844
2845 if (strcmp(name, XATTR_NAME_SELINUX)) {
2846 /* Not an attribute we recognize, so nothing to do. */
2847 return;
2848 }
2849
Stephen Smalley12b29f32008-05-07 13:03:20 -04002850 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002852 printk(KERN_ERR "SELinux: unable to map context to SID"
2853 "for (%s, %lu), rc=%d\n",
2854 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 return;
2856 }
2857
2858 isec->sid = newsid;
2859 return;
2860}
2861
David Howells8f0cfa52008-04-29 00:59:41 -07002862static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863{
David Howells88e67f32008-11-14 10:39:21 +11002864 const struct cred *cred = current_cred();
2865
Eric Paris2875fa02011-04-28 16:04:24 -04002866 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867}
2868
Eric Paris828dfe12008-04-17 13:17:49 -04002869static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870{
David Howells88e67f32008-11-14 10:39:21 +11002871 const struct cred *cred = current_cred();
2872
Eric Paris2875fa02011-04-28 16:04:24 -04002873 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874}
2875
David Howells8f0cfa52008-04-29 00:59:41 -07002876static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002878 if (strcmp(name, XATTR_NAME_SELINUX))
2879 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880
2881 /* No one is allowed to remove a SELinux security label.
2882 You can change the label, but all data must be labeled. */
2883 return -EACCES;
2884}
2885
James Morrisd381d8a2005-10-30 14:59:22 -08002886/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002887 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002888 *
2889 * Permission check is handled by selinux_inode_getxattr hook.
2890 */
David P. Quigley42492592008-02-04 22:29:39 -08002891static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892{
David P. Quigley42492592008-02-04 22:29:39 -08002893 u32 size;
2894 int error;
2895 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002898 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2899 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002901 /*
2902 * If the caller has CAP_MAC_ADMIN, then get the raw context
2903 * value even if it is not defined by current policy; otherwise,
2904 * use the in-core value under current policy.
2905 * Use the non-auditing forms of the permission checks since
2906 * getxattr may be called by unprivileged processes commonly
2907 * and lack of permission just means that we fall back to the
2908 * in-core context value, not a denial.
2909 */
Eric Paris6a9de492012-01-03 12:25:14 -05002910 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002911 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002912 if (!error)
2913 error = security_sid_to_context_force(isec->sid, &context,
2914 &size);
2915 else
2916 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002917 if (error)
2918 return error;
2919 error = size;
2920 if (alloc) {
2921 *buffer = context;
2922 goto out_nofree;
2923 }
2924 kfree(context);
2925out_nofree:
2926 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927}
2928
2929static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002930 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931{
2932 struct inode_security_struct *isec = inode->i_security;
2933 u32 newsid;
2934 int rc;
2935
2936 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2937 return -EOPNOTSUPP;
2938
2939 if (!value || !size)
2940 return -EACCES;
2941
Eric Paris828dfe12008-04-17 13:17:49 -04002942 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 if (rc)
2944 return rc;
2945
2946 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04002947 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 return 0;
2949}
2950
2951static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2952{
2953 const int len = sizeof(XATTR_NAME_SELINUX);
2954 if (buffer && len <= buffer_size)
2955 memcpy(buffer, XATTR_NAME_SELINUX, len);
2956 return len;
2957}
2958
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02002959static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2960{
2961 struct inode_security_struct *isec = inode->i_security;
2962 *secid = isec->sid;
2963}
2964
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965/* file security operations */
2966
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002967static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968{
David Howells88e67f32008-11-14 10:39:21 +11002969 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05002970 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2973 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2974 mask |= MAY_APPEND;
2975
Paul Moore389fb8002009-03-27 17:10:34 -04002976 return file_has_perm(cred, file,
2977 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978}
2979
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002980static int selinux_file_permission(struct file *file, int mask)
2981{
Al Viro496ad9a2013-01-23 17:07:38 -05002982 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04002983 struct file_security_struct *fsec = file->f_security;
2984 struct inode_security_struct *isec = inode->i_security;
2985 u32 sid = current_sid();
2986
Paul Moore389fb8002009-03-27 17:10:34 -04002987 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002988 /* No permission to check. Existence test. */
2989 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002990
Stephen Smalley20dda182009-06-22 14:54:53 -04002991 if (sid == fsec->sid && fsec->isid == isec->sid &&
2992 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04002993 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04002994 return 0;
2995
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002996 return selinux_revalidate_file_permission(file, mask);
2997}
2998
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999static int selinux_file_alloc_security(struct file *file)
3000{
3001 return file_alloc_security(file);
3002}
3003
3004static void selinux_file_free_security(struct file *file)
3005{
3006 file_free_security(file);
3007}
3008
3009static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3010 unsigned long arg)
3011{
David Howells88e67f32008-11-14 10:39:21 +11003012 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003013 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
Eric Paris0b24dcb2011-02-25 15:39:20 -05003015 switch (cmd) {
3016 case FIONREAD:
3017 /* fall through */
3018 case FIBMAP:
3019 /* fall through */
3020 case FIGETBSZ:
3021 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003022 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003023 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003024 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003025 error = file_has_perm(cred, file, FILE__GETATTR);
3026 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
Al Viro2f99c362012-03-23 16:04:05 -04003028 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003029 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003030 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003031 error = file_has_perm(cred, file, FILE__SETATTR);
3032 break;
3033
3034 /* sys_ioctl() checks */
3035 case FIONBIO:
3036 /* fall through */
3037 case FIOASYNC:
3038 error = file_has_perm(cred, file, 0);
3039 break;
3040
3041 case KDSKBENT:
3042 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003043 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3044 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003045 break;
3046
3047 /* default case assumes that the command will go
3048 * to the file's ioctl() function.
3049 */
3050 default:
3051 error = file_has_perm(cred, file, FILE__IOCTL);
3052 }
3053 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054}
3055
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003056static int default_noexec;
3057
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3059{
David Howells88e67f32008-11-14 10:39:21 +11003060 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003061 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003062
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003063 if (default_noexec &&
3064 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 /*
3066 * We are making executable an anonymous mapping or a
3067 * private file mapping that will also be writable.
3068 * This has an additional check.
3069 */
David Howellsd84f4f92008-11-14 10:39:23 +11003070 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003072 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074
3075 if (file) {
3076 /* read access is always possible with a mapping */
3077 u32 av = FILE__READ;
3078
3079 /* write access only matters if the mapping is shared */
3080 if (shared && (prot & PROT_WRITE))
3081 av |= FILE__WRITE;
3082
3083 if (prot & PROT_EXEC)
3084 av |= FILE__EXECUTE;
3085
David Howells88e67f32008-11-14 10:39:21 +11003086 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 }
David Howellsd84f4f92008-11-14 10:39:23 +11003088
3089error:
3090 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091}
3092
Al Viroe5467852012-05-30 13:30:51 -04003093static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094{
Eric Parised032182007-06-28 15:55:21 -04003095 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003096 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
Eric Paris84336d1a2009-07-31 12:54:05 -04003098 /*
3099 * notice that we are intentionally putting the SELinux check before
3100 * the secondary cap_file_mmap check. This is such a likely attempt
3101 * at bad behaviour/exploit that we always want to get the AVC, even
3102 * if DAC would have also denied the operation.
3103 */
Eric Parisa2551df2009-07-31 12:54:11 -04003104 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003105 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3106 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003107 if (rc)
3108 return rc;
3109 }
3110
3111 /* do DAC check on address space usage */
Al Viroe5467852012-05-30 13:30:51 -04003112 return cap_mmap_addr(addr);
3113}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114
Al Viroe5467852012-05-30 13:30:51 -04003115static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3116 unsigned long prot, unsigned long flags)
3117{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 if (selinux_checkreqprot)
3119 prot = reqprot;
3120
3121 return file_map_prot_check(file, prot,
3122 (flags & MAP_TYPE) == MAP_SHARED);
3123}
3124
3125static int selinux_file_mprotect(struct vm_area_struct *vma,
3126 unsigned long reqprot,
3127 unsigned long prot)
3128{
David Howells88e67f32008-11-14 10:39:21 +11003129 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131 if (selinux_checkreqprot)
3132 prot = reqprot;
3133
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003134 if (default_noexec &&
3135 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003136 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003137 if (vma->vm_start >= vma->vm_mm->start_brk &&
3138 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003139 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003140 } else if (!vma->vm_file &&
3141 vma->vm_start <= vma->vm_mm->start_stack &&
3142 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003143 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003144 } else if (vma->vm_file && vma->anon_vma) {
3145 /*
3146 * We are making executable a file mapping that has
3147 * had some COW done. Since pages might have been
3148 * written, check ability to execute the possibly
3149 * modified content. This typically should only
3150 * occur for text relocations.
3151 */
David Howellsd84f4f92008-11-14 10:39:23 +11003152 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003153 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003154 if (rc)
3155 return rc;
3156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
3158 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3159}
3160
3161static int selinux_file_lock(struct file *file, unsigned int cmd)
3162{
David Howells88e67f32008-11-14 10:39:21 +11003163 const struct cred *cred = current_cred();
3164
3165 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166}
3167
3168static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3169 unsigned long arg)
3170{
David Howells88e67f32008-11-14 10:39:21 +11003171 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 int err = 0;
3173
3174 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003175 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003176 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003177 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003179 }
3180 /* fall through */
3181 case F_SETOWN:
3182 case F_SETSIG:
3183 case F_GETFL:
3184 case F_GETOWN:
3185 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003186 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003187 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003188 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003189 break;
3190 case F_GETLK:
3191 case F_SETLK:
3192 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003194 case F_GETLK64:
3195 case F_SETLK64:
3196 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197#endif
David Howells88e67f32008-11-14 10:39:21 +11003198 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003199 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 }
3201
3202 return err;
3203}
3204
3205static int selinux_file_set_fowner(struct file *file)
3206{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 struct file_security_struct *fsec;
3208
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003210 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212 return 0;
3213}
3214
3215static int selinux_file_send_sigiotask(struct task_struct *tsk,
3216 struct fown_struct *fown, int signum)
3217{
Eric Paris828dfe12008-04-17 13:17:49 -04003218 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003219 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 struct file_security_struct *fsec;
3222
3223 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003224 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 fsec = file->f_security;
3227
3228 if (!signum)
3229 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3230 else
3231 perm = signal_to_av(signum);
3232
David Howells275bb412008-11-14 10:39:19 +11003233 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 SECCLASS_PROCESS, perm, NULL);
3235}
3236
3237static int selinux_file_receive(struct file *file)
3238{
David Howells88e67f32008-11-14 10:39:21 +11003239 const struct cred *cred = current_cred();
3240
3241 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242}
3243
Eric Paris83d49852012-04-04 13:45:40 -04003244static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003245{
3246 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003247 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003248
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003249 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003250 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003251 /*
3252 * Save inode label and policy sequence number
3253 * at open-time so that selinux_file_permission
3254 * can determine whether revalidation is necessary.
3255 * Task label is already saved in the file security
3256 * struct as its SID.
3257 */
3258 fsec->isid = isec->sid;
3259 fsec->pseqno = avc_policy_seqno();
3260 /*
3261 * Since the inode label or policy seqno may have changed
3262 * between the selinux_inode_permission check and the saving
3263 * of state above, recheck that access is still permitted.
3264 * Otherwise, access might never be revalidated against the
3265 * new inode label or new policy.
3266 * This check is not redundant - do not remove.
3267 */
Eric Paris602a8dd2012-04-04 15:01:42 -04003268 return path_has_perm(cred, &file->f_path, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003269}
3270
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271/* task security operations */
3272
3273static int selinux_task_create(unsigned long clone_flags)
3274{
David Howells3b11a1d2008-11-14 10:39:26 +11003275 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276}
3277
David Howellsf1752ee2008-11-14 10:39:17 +11003278/*
David Howellsee18d642009-09-02 09:14:21 +01003279 * allocate the SELinux part of blank credentials
3280 */
3281static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3282{
3283 struct task_security_struct *tsec;
3284
3285 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3286 if (!tsec)
3287 return -ENOMEM;
3288
3289 cred->security = tsec;
3290 return 0;
3291}
3292
3293/*
David Howellsf1752ee2008-11-14 10:39:17 +11003294 * detach and free the LSM part of a set of credentials
3295 */
3296static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297{
David Howellsf1752ee2008-11-14 10:39:17 +11003298 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003299
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003300 /*
3301 * cred->security == NULL if security_cred_alloc_blank() or
3302 * security_prepare_creds() returned an error.
3303 */
3304 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003305 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003306 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307}
3308
David Howellsd84f4f92008-11-14 10:39:23 +11003309/*
3310 * prepare a new set of credentials for modification
3311 */
3312static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3313 gfp_t gfp)
3314{
3315 const struct task_security_struct *old_tsec;
3316 struct task_security_struct *tsec;
3317
3318 old_tsec = old->security;
3319
3320 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3321 if (!tsec)
3322 return -ENOMEM;
3323
3324 new->security = tsec;
3325 return 0;
3326}
3327
3328/*
David Howellsee18d642009-09-02 09:14:21 +01003329 * transfer the SELinux data to a blank set of creds
3330 */
3331static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3332{
3333 const struct task_security_struct *old_tsec = old->security;
3334 struct task_security_struct *tsec = new->security;
3335
3336 *tsec = *old_tsec;
3337}
3338
3339/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003340 * set the security data for a kernel service
3341 * - all the creation contexts are set to unlabelled
3342 */
3343static int selinux_kernel_act_as(struct cred *new, u32 secid)
3344{
3345 struct task_security_struct *tsec = new->security;
3346 u32 sid = current_sid();
3347 int ret;
3348
3349 ret = avc_has_perm(sid, secid,
3350 SECCLASS_KERNEL_SERVICE,
3351 KERNEL_SERVICE__USE_AS_OVERRIDE,
3352 NULL);
3353 if (ret == 0) {
3354 tsec->sid = secid;
3355 tsec->create_sid = 0;
3356 tsec->keycreate_sid = 0;
3357 tsec->sockcreate_sid = 0;
3358 }
3359 return ret;
3360}
3361
3362/*
3363 * set the file creation context in a security record to the same as the
3364 * objective context of the specified inode
3365 */
3366static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3367{
3368 struct inode_security_struct *isec = inode->i_security;
3369 struct task_security_struct *tsec = new->security;
3370 u32 sid = current_sid();
3371 int ret;
3372
3373 ret = avc_has_perm(sid, isec->sid,
3374 SECCLASS_KERNEL_SERVICE,
3375 KERNEL_SERVICE__CREATE_FILES_AS,
3376 NULL);
3377
3378 if (ret == 0)
3379 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003380 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003381}
3382
Eric Parisdd8dbf22009-11-03 16:35:32 +11003383static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003384{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003385 u32 sid;
3386 struct common_audit_data ad;
3387
3388 sid = task_sid(current);
3389
Eric Paris50c205f2012-04-04 15:01:43 -04003390 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003391 ad.u.kmod_name = kmod_name;
3392
3393 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3394 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003395}
3396
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3398{
David Howells3b11a1d2008-11-14 10:39:26 +11003399 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400}
3401
3402static int selinux_task_getpgid(struct task_struct *p)
3403{
David Howells3b11a1d2008-11-14 10:39:26 +11003404 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405}
3406
3407static int selinux_task_getsid(struct task_struct *p)
3408{
David Howells3b11a1d2008-11-14 10:39:26 +11003409 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410}
3411
David Quigleyf9008e42006-06-30 01:55:46 -07003412static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3413{
David Howells275bb412008-11-14 10:39:19 +11003414 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003415}
3416
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417static int selinux_task_setnice(struct task_struct *p, int nice)
3418{
3419 int rc;
3420
Eric Paris200ac532009-02-12 15:01:04 -05003421 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 if (rc)
3423 return rc;
3424
David Howells3b11a1d2008-11-14 10:39:26 +11003425 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426}
3427
James Morris03e68062006-06-23 02:03:58 -07003428static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3429{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003430 int rc;
3431
Eric Paris200ac532009-02-12 15:01:04 -05003432 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003433 if (rc)
3434 return rc;
3435
David Howells3b11a1d2008-11-14 10:39:26 +11003436 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003437}
3438
David Quigleya1836a42006-06-30 01:55:49 -07003439static int selinux_task_getioprio(struct task_struct *p)
3440{
David Howells3b11a1d2008-11-14 10:39:26 +11003441 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003442}
3443
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003444static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3445 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003447 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448
3449 /* Control the ability to change the hard limit (whether
3450 lowering or raising it), so that the hard limit can
3451 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003452 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003454 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
3456 return 0;
3457}
3458
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003459static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003461 int rc;
3462
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003463 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003464 if (rc)
3465 return rc;
3466
David Howells3b11a1d2008-11-14 10:39:26 +11003467 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468}
3469
3470static int selinux_task_getscheduler(struct task_struct *p)
3471{
David Howells3b11a1d2008-11-14 10:39:26 +11003472 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473}
3474
David Quigley35601542006-06-23 02:04:01 -07003475static int selinux_task_movememory(struct task_struct *p)
3476{
David Howells3b11a1d2008-11-14 10:39:26 +11003477 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003478}
3479
David Quigleyf9008e42006-06-30 01:55:46 -07003480static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3481 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482{
3483 u32 perm;
3484 int rc;
3485
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 if (!sig)
3487 perm = PROCESS__SIGNULL; /* null signal; existence test */
3488 else
3489 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003490 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003491 rc = avc_has_perm(secid, task_sid(p),
3492 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003493 else
David Howells3b11a1d2008-11-14 10:39:26 +11003494 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003495 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496}
3497
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498static int selinux_task_wait(struct task_struct *p)
3499{
Eric Paris8a535142007-10-22 16:10:31 -04003500 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501}
3502
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503static void selinux_task_to_inode(struct task_struct *p,
3504 struct inode *inode)
3505{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003507 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508
David Howells275bb412008-11-14 10:39:19 +11003509 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511}
3512
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003514static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003515 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516{
3517 int offset, ihlen, ret = -EINVAL;
3518 struct iphdr _iph, *ih;
3519
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003520 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3522 if (ih == NULL)
3523 goto out;
3524
3525 ihlen = ih->ihl * 4;
3526 if (ihlen < sizeof(_iph))
3527 goto out;
3528
Eric Paris48c62af2012-04-02 13:15:44 -04003529 ad->u.net->v4info.saddr = ih->saddr;
3530 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531 ret = 0;
3532
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003533 if (proto)
3534 *proto = ih->protocol;
3535
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003537 case IPPROTO_TCP: {
3538 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
Eric Paris828dfe12008-04-17 13:17:49 -04003540 if (ntohs(ih->frag_off) & IP_OFFSET)
3541 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
3543 offset += ihlen;
3544 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3545 if (th == NULL)
3546 break;
3547
Eric Paris48c62af2012-04-02 13:15:44 -04003548 ad->u.net->sport = th->source;
3549 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552
Eric Paris828dfe12008-04-17 13:17:49 -04003553 case IPPROTO_UDP: {
3554 struct udphdr _udph, *uh;
3555
3556 if (ntohs(ih->frag_off) & IP_OFFSET)
3557 break;
3558
3559 offset += ihlen;
3560 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3561 if (uh == NULL)
3562 break;
3563
Eric Paris48c62af2012-04-02 13:15:44 -04003564 ad->u.net->sport = uh->source;
3565 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003566 break;
3567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568
James Morris2ee92d42006-11-13 16:09:01 -08003569 case IPPROTO_DCCP: {
3570 struct dccp_hdr _dccph, *dh;
3571
3572 if (ntohs(ih->frag_off) & IP_OFFSET)
3573 break;
3574
3575 offset += ihlen;
3576 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3577 if (dh == NULL)
3578 break;
3579
Eric Paris48c62af2012-04-02 13:15:44 -04003580 ad->u.net->sport = dh->dccph_sport;
3581 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003582 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003583 }
James Morris2ee92d42006-11-13 16:09:01 -08003584
Eric Paris828dfe12008-04-17 13:17:49 -04003585 default:
3586 break;
3587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588out:
3589 return ret;
3590}
3591
3592#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3593
3594/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003595static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003596 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597{
3598 u8 nexthdr;
3599 int ret = -EINVAL, offset;
3600 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003601 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003603 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3605 if (ip6 == NULL)
3606 goto out;
3607
Eric Paris48c62af2012-04-02 13:15:44 -04003608 ad->u.net->v6info.saddr = ip6->saddr;
3609 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610 ret = 0;
3611
3612 nexthdr = ip6->nexthdr;
3613 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003614 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 if (offset < 0)
3616 goto out;
3617
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003618 if (proto)
3619 *proto = nexthdr;
3620
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 switch (nexthdr) {
3622 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003623 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
3625 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3626 if (th == NULL)
3627 break;
3628
Eric Paris48c62af2012-04-02 13:15:44 -04003629 ad->u.net->sport = th->source;
3630 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 break;
3632 }
3633
3634 case IPPROTO_UDP: {
3635 struct udphdr _udph, *uh;
3636
3637 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3638 if (uh == NULL)
3639 break;
3640
Eric Paris48c62af2012-04-02 13:15:44 -04003641 ad->u.net->sport = uh->source;
3642 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 break;
3644 }
3645
James Morris2ee92d42006-11-13 16:09:01 -08003646 case IPPROTO_DCCP: {
3647 struct dccp_hdr _dccph, *dh;
3648
3649 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3650 if (dh == NULL)
3651 break;
3652
Eric Paris48c62af2012-04-02 13:15:44 -04003653 ad->u.net->sport = dh->dccph_sport;
3654 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003655 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003656 }
James Morris2ee92d42006-11-13 16:09:01 -08003657
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 /* includes fragments */
3659 default:
3660 break;
3661 }
3662out:
3663 return ret;
3664}
3665
3666#endif /* IPV6 */
3667
Thomas Liu2bf49692009-07-14 12:14:09 -04003668static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003669 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670{
David Howellscf9481e2008-07-27 21:31:07 +10003671 char *addrp;
3672 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673
Eric Paris48c62af2012-04-02 13:15:44 -04003674 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003676 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003677 if (ret)
3678 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003679 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3680 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003681 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
3683#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3684 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003685 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003686 if (ret)
3687 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003688 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3689 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003690 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691#endif /* IPV6 */
3692 default:
David Howellscf9481e2008-07-27 21:31:07 +10003693 addrp = NULL;
3694 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 }
3696
David Howellscf9481e2008-07-27 21:31:07 +10003697parse_error:
3698 printk(KERN_WARNING
3699 "SELinux: failure in selinux_parse_skb(),"
3700 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003702
3703okay:
3704 if (_addrp)
3705 *_addrp = addrp;
3706 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707}
3708
Paul Moore4f6a9932007-03-01 14:35:22 -05003709/**
Paul Moore220deb92008-01-29 08:38:23 -05003710 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003711 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003712 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003713 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003714 *
3715 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003716 * Check the various different forms of network peer labeling and determine
3717 * the peer label/SID for the packet; most of the magic actually occurs in
3718 * the security server function security_net_peersid_cmp(). The function
3719 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3720 * or -EACCES if @sid is invalid due to inconsistencies with the different
3721 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003722 *
3723 */
Paul Moore220deb92008-01-29 08:38:23 -05003724static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003725{
Paul Moore71f1cb02008-01-29 08:51:16 -05003726 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003727 u32 xfrm_sid;
3728 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003729 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003730
Paul Moorebed4d7e2013-07-23 17:38:40 -04003731 err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
3732 if (unlikely(err))
3733 return -EACCES;
3734 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3735 if (unlikely(err))
3736 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003737
Paul Moore71f1cb02008-01-29 08:51:16 -05003738 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3739 if (unlikely(err)) {
3740 printk(KERN_WARNING
3741 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3742 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003743 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003744 }
Paul Moore220deb92008-01-29 08:38:23 -05003745
3746 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003747}
3748
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003750
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003751static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3752 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003753{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003754 if (tsec->sockcreate_sid > SECSID_NULL) {
3755 *socksid = tsec->sockcreate_sid;
3756 return 0;
3757 }
3758
3759 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3760 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003761}
3762
Paul Moore253bfae2010-04-22 14:46:19 -04003763static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764{
Paul Moore253bfae2010-04-22 14:46:19 -04003765 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003766 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003767 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003768 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Paul Moore253bfae2010-04-22 14:46:19 -04003770 if (sksec->sid == SECINITSID_KERNEL)
3771 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Eric Paris50c205f2012-04-04 15:01:43 -04003773 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003774 ad.u.net = &net;
3775 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776
Paul Moore253bfae2010-04-22 14:46:19 -04003777 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778}
3779
3780static int selinux_socket_create(int family, int type,
3781 int protocol, int kern)
3782{
Paul Moore5fb49872010-04-22 14:46:19 -04003783 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003784 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003785 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003786 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
3788 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003789 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790
David Howells275bb412008-11-14 10:39:19 +11003791 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003792 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3793 if (rc)
3794 return rc;
3795
Paul Moored4f2d972010-04-22 14:46:18 -04003796 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797}
3798
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003799static int selinux_socket_post_create(struct socket *sock, int family,
3800 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801{
Paul Moore5fb49872010-04-22 14:46:19 -04003802 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003803 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003804 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003805 int err = 0;
3806
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003807 isec->sclass = socket_type_to_security_class(family, type, protocol);
3808
David Howells275bb412008-11-14 10:39:19 +11003809 if (kern)
3810 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003811 else {
3812 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3813 if (err)
3814 return err;
3815 }
David Howells275bb412008-11-14 10:39:19 +11003816
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 isec->initialized = 1;
3818
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003819 if (sock->sk) {
3820 sksec = sock->sk->sk_security;
3821 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003822 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04003823 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003824 }
3825
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003826 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827}
3828
3829/* Range of port numbers used to automatically bind.
3830 Need to determine whether we should perform a name_bind
3831 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832
3833static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3834{
Paul Moore253bfae2010-04-22 14:46:19 -04003835 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 u16 family;
3837 int err;
3838
Paul Moore253bfae2010-04-22 14:46:19 -04003839 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 if (err)
3841 goto out;
3842
3843 /*
3844 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003845 * Multiple address binding for SCTP is not supported yet: we just
3846 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 */
Paul Moore253bfae2010-04-22 14:46:19 -04003848 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 if (family == PF_INET || family == PF_INET6) {
3850 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04003851 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003852 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003853 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 struct sockaddr_in *addr4 = NULL;
3855 struct sockaddr_in6 *addr6 = NULL;
3856 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10003857 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 if (family == PF_INET) {
3860 addr4 = (struct sockaddr_in *)address;
3861 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 addrp = (char *)&addr4->sin_addr.s_addr;
3863 } else {
3864 addr6 = (struct sockaddr_in6 *)address;
3865 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 addrp = (char *)&addr6->sin6_addr.s6_addr;
3867 }
3868
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003869 if (snum) {
3870 int low, high;
3871
3872 inet_get_local_port_range(&low, &high);
3873
3874 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003875 err = sel_netport_sid(sk->sk_protocol,
3876 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003877 if (err)
3878 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04003879 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003880 ad.u.net = &net;
3881 ad.u.net->sport = htons(snum);
3882 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04003883 err = avc_has_perm(sksec->sid, sid,
3884 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003885 SOCKET__NAME_BIND, &ad);
3886 if (err)
3887 goto out;
3888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 }
Eric Paris828dfe12008-04-17 13:17:49 -04003890
Paul Moore253bfae2010-04-22 14:46:19 -04003891 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003892 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 node_perm = TCP_SOCKET__NODE_BIND;
3894 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003895
James Morris13402582005-09-30 14:24:34 -04003896 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 node_perm = UDP_SOCKET__NODE_BIND;
3898 break;
James Morris2ee92d42006-11-13 16:09:01 -08003899
3900 case SECCLASS_DCCP_SOCKET:
3901 node_perm = DCCP_SOCKET__NODE_BIND;
3902 break;
3903
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 default:
3905 node_perm = RAWIP_SOCKET__NODE_BIND;
3906 break;
3907 }
Eric Paris828dfe12008-04-17 13:17:49 -04003908
Paul Moore224dfbd2008-01-29 08:38:13 -05003909 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 if (err)
3911 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003912
Eric Paris50c205f2012-04-04 15:01:43 -04003913 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003914 ad.u.net = &net;
3915 ad.u.net->sport = htons(snum);
3916 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917
3918 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04003919 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 else
Eric Paris48c62af2012-04-02 13:15:44 -04003921 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
Paul Moore253bfae2010-04-22 14:46:19 -04003923 err = avc_has_perm(sksec->sid, sid,
3924 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 if (err)
3926 goto out;
3927 }
3928out:
3929 return err;
3930}
3931
3932static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3933{
Paul Moore014ab192008-10-10 10:16:33 -04003934 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04003935 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 int err;
3937
Paul Moore253bfae2010-04-22 14:46:19 -04003938 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 if (err)
3940 return err;
3941
3942 /*
James Morris2ee92d42006-11-13 16:09:01 -08003943 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 */
Paul Moore253bfae2010-04-22 14:46:19 -04003945 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3946 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04003947 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003948 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 struct sockaddr_in *addr4 = NULL;
3950 struct sockaddr_in6 *addr6 = NULL;
3951 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003952 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
3954 if (sk->sk_family == PF_INET) {
3955 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003956 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 return -EINVAL;
3958 snum = ntohs(addr4->sin_port);
3959 } else {
3960 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003961 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 return -EINVAL;
3963 snum = ntohs(addr6->sin6_port);
3964 }
3965
Paul Moore3e112172008-04-10 10:48:14 -04003966 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 if (err)
3968 goto out;
3969
Paul Moore253bfae2010-04-22 14:46:19 -04003970 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08003971 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3972
Eric Paris50c205f2012-04-04 15:01:43 -04003973 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003974 ad.u.net = &net;
3975 ad.u.net->dport = htons(snum);
3976 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04003977 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 if (err)
3979 goto out;
3980 }
3981
Paul Moore014ab192008-10-10 10:16:33 -04003982 err = selinux_netlbl_socket_connect(sk, address);
3983
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984out:
3985 return err;
3986}
3987
3988static int selinux_socket_listen(struct socket *sock, int backlog)
3989{
Paul Moore253bfae2010-04-22 14:46:19 -04003990 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991}
3992
3993static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3994{
3995 int err;
3996 struct inode_security_struct *isec;
3997 struct inode_security_struct *newisec;
3998
Paul Moore253bfae2010-04-22 14:46:19 -04003999 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 if (err)
4001 return err;
4002
4003 newisec = SOCK_INODE(newsock)->i_security;
4004
4005 isec = SOCK_INODE(sock)->i_security;
4006 newisec->sclass = isec->sclass;
4007 newisec->sid = isec->sid;
4008 newisec->initialized = 1;
4009
4010 return 0;
4011}
4012
4013static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004014 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015{
Paul Moore253bfae2010-04-22 14:46:19 -04004016 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017}
4018
4019static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4020 int size, int flags)
4021{
Paul Moore253bfae2010-04-22 14:46:19 -04004022 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023}
4024
4025static int selinux_socket_getsockname(struct socket *sock)
4026{
Paul Moore253bfae2010-04-22 14:46:19 -04004027 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028}
4029
4030static int selinux_socket_getpeername(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
Eric Paris828dfe12008-04-17 13:17:49 -04004035static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036{
Paul Mooref8687af2006-10-30 15:22:15 -08004037 int err;
4038
Paul Moore253bfae2010-04-22 14:46:19 -04004039 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004040 if (err)
4041 return err;
4042
4043 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044}
4045
4046static int selinux_socket_getsockopt(struct socket *sock, int level,
4047 int optname)
4048{
Paul Moore253bfae2010-04-22 14:46:19 -04004049 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050}
4051
4052static int selinux_socket_shutdown(struct socket *sock, int how)
4053{
Paul Moore253bfae2010-04-22 14:46:19 -04004054 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
David S. Miller3610cda2011-01-05 15:38:53 -08004057static int selinux_socket_unix_stream_connect(struct sock *sock,
4058 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 struct sock *newsk)
4060{
David S. Miller3610cda2011-01-05 15:38:53 -08004061 struct sk_security_struct *sksec_sock = sock->sk_security;
4062 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004063 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004064 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004065 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 int err;
4067
Eric Paris50c205f2012-04-04 15:01:43 -04004068 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004069 ad.u.net = &net;
4070 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Paul Moore4d1e2452010-04-22 14:46:18 -04004072 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4073 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4075 if (err)
4076 return err;
4077
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004079 sksec_new->peer_sid = sksec_sock->sid;
4080 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4081 &sksec_new->sid);
4082 if (err)
4083 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004084
Paul Moore4d1e2452010-04-22 14:46:18 -04004085 /* connecting socket */
4086 sksec_sock->peer_sid = sksec_new->sid;
4087
4088 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089}
4090
4091static int selinux_socket_unix_may_send(struct socket *sock,
4092 struct socket *other)
4093{
Paul Moore253bfae2010-04-22 14:46:19 -04004094 struct sk_security_struct *ssec = sock->sk->sk_security;
4095 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004096 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004097 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
Eric Paris50c205f2012-04-04 15:01:43 -04004099 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004100 ad.u.net = &net;
4101 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
Paul Moore253bfae2010-04-22 14:46:19 -04004103 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4104 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105}
4106
Paul Mooreeffad8d2008-01-29 08:49:27 -05004107static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4108 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004109 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004110{
4111 int err;
4112 u32 if_sid;
4113 u32 node_sid;
4114
4115 err = sel_netif_sid(ifindex, &if_sid);
4116 if (err)
4117 return err;
4118 err = avc_has_perm(peer_sid, if_sid,
4119 SECCLASS_NETIF, NETIF__INGRESS, ad);
4120 if (err)
4121 return err;
4122
4123 err = sel_netnode_sid(addrp, family, &node_sid);
4124 if (err)
4125 return err;
4126 return avc_has_perm(peer_sid, node_sid,
4127 SECCLASS_NODE, NODE__RECVFROM, ad);
4128}
4129
Paul Moore220deb92008-01-29 08:38:23 -05004130static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004131 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004132{
Paul Moore277d3422008-12-31 12:54:11 -05004133 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004134 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004135 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004136 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004137 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004138 char *addrp;
4139
Eric Paris50c205f2012-04-04 15:01:43 -04004140 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004141 ad.u.net = &net;
4142 ad.u.net->netif = skb->skb_iif;
4143 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004144 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4145 if (err)
4146 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004147
Paul Moore58bfbb52009-03-27 17:10:41 -04004148 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004149 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004150 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004151 if (err)
4152 return err;
4153 }
Paul Moore220deb92008-01-29 08:38:23 -05004154
Steffen Klassertb9679a72011-02-23 12:55:21 +01004155 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4156 if (err)
4157 return err;
4158 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004159
James Morris4e5ab4c2006-06-09 00:33:33 -07004160 return err;
4161}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004162
James Morris4e5ab4c2006-06-09 00:33:33 -07004163static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4164{
Paul Moore220deb92008-01-29 08:38:23 -05004165 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004166 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004167 u16 family = sk->sk_family;
4168 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004169 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004170 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004171 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004172 u8 secmark_active;
4173 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004174
James Morris4e5ab4c2006-06-09 00:33:33 -07004175 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004176 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004177
4178 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004179 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004180 family = PF_INET;
4181
Paul Moored8395c82008-10-10 10:16:30 -04004182 /* If any sort of compatibility mode is enabled then handoff processing
4183 * to the selinux_sock_rcv_skb_compat() function to deal with the
4184 * special handling. We do this in an attempt to keep this function
4185 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004186 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004187 return selinux_sock_rcv_skb_compat(sk, skb, family);
4188
4189 secmark_active = selinux_secmark_enabled();
4190 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4191 if (!secmark_active && !peerlbl_active)
4192 return 0;
4193
Eric Paris50c205f2012-04-04 15:01:43 -04004194 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004195 ad.u.net = &net;
4196 ad.u.net->netif = skb->skb_iif;
4197 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004198 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004199 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004200 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004201
Paul Moored8395c82008-10-10 10:16:30 -04004202 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004203 u32 peer_sid;
4204
4205 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4206 if (err)
4207 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004208 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004209 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004210 if (err) {
4211 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004212 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004213 }
Paul Moored621d352008-01-29 08:43:36 -05004214 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4215 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004216 if (err)
4217 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004218 }
4219
Paul Moored8395c82008-10-10 10:16:30 -04004220 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004221 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4222 PACKET__RECV, &ad);
4223 if (err)
4224 return err;
4225 }
4226
Paul Moored621d352008-01-29 08:43:36 -05004227 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228}
4229
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004230static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4231 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232{
4233 int err = 0;
4234 char *scontext;
4235 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004236 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004237 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Paul Moore253bfae2010-04-22 14:46:19 -04004239 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4240 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004241 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004242 if (peer_sid == SECSID_NULL)
4243 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004245 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004247 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248
4249 if (scontext_len > len) {
4250 err = -ERANGE;
4251 goto out_len;
4252 }
4253
4254 if (copy_to_user(optval, scontext, scontext_len))
4255 err = -EFAULT;
4256
4257out_len:
4258 if (put_user(scontext_len, optlen))
4259 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 return err;
4262}
4263
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004264static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004265{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004266 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004267 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004268
Paul Mooreaa862902008-10-10 10:16:29 -04004269 if (skb && skb->protocol == htons(ETH_P_IP))
4270 family = PF_INET;
4271 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4272 family = PF_INET6;
4273 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004274 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004275 else
4276 goto out;
4277
4278 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004279 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004280 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004281 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004282
Paul Moore75e22912008-01-29 08:38:04 -05004283out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004284 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004285 if (peer_secid == SECSID_NULL)
4286 return -EINVAL;
4287 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004288}
4289
Al Viro7d877f32005-10-21 03:20:43 -04004290static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
Paul Moore84914b72010-04-22 14:46:18 -04004292 struct sk_security_struct *sksec;
4293
4294 sksec = kzalloc(sizeof(*sksec), priority);
4295 if (!sksec)
4296 return -ENOMEM;
4297
4298 sksec->peer_sid = SECINITSID_UNLABELED;
4299 sksec->sid = SECINITSID_UNLABELED;
4300 selinux_netlbl_sk_security_reset(sksec);
4301 sk->sk_security = sksec;
4302
4303 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304}
4305
4306static void selinux_sk_free_security(struct sock *sk)
4307{
Paul Moore84914b72010-04-22 14:46:18 -04004308 struct sk_security_struct *sksec = sk->sk_security;
4309
4310 sk->sk_security = NULL;
4311 selinux_netlbl_sk_security_free(sksec);
4312 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313}
4314
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004315static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4316{
Eric Parisdd3e7832010-04-07 15:08:46 -04004317 struct sk_security_struct *sksec = sk->sk_security;
4318 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004319
Eric Parisdd3e7832010-04-07 15:08:46 -04004320 newsksec->sid = sksec->sid;
4321 newsksec->peer_sid = sksec->peer_sid;
4322 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004323
Eric Parisdd3e7832010-04-07 15:08:46 -04004324 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004325}
4326
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004327static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004328{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004329 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004330 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004331 else {
4332 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004333
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004334 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004335 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004336}
4337
Eric Paris828dfe12008-04-17 13:17:49 -04004338static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004339{
4340 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4341 struct sk_security_struct *sksec = sk->sk_security;
4342
David Woodhouse2148ccc2006-09-29 15:50:25 -07004343 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4344 sk->sk_family == PF_UNIX)
4345 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004346 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004347}
4348
Adrian Bunk9a673e52006-08-15 00:03:53 -07004349static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4350 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004351{
4352 struct sk_security_struct *sksec = sk->sk_security;
4353 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004354 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004355 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004356 u32 peersid;
4357
Paul Mooreaa862902008-10-10 10:16:29 -04004358 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4359 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4360 family = PF_INET;
4361
4362 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004363 if (err)
4364 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004365 if (peersid == SECSID_NULL) {
4366 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004367 req->peer_secid = SECSID_NULL;
Paul Moore389fb8002009-03-27 17:10:34 -04004368 } else {
4369 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4370 if (err)
4371 return err;
4372 req->secid = newsid;
4373 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004374 }
4375
Paul Moore389fb8002009-03-27 17:10:34 -04004376 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004377}
4378
Adrian Bunk9a673e52006-08-15 00:03:53 -07004379static void selinux_inet_csk_clone(struct sock *newsk,
4380 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004381{
4382 struct sk_security_struct *newsksec = newsk->sk_security;
4383
4384 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004385 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004386 /* NOTE: Ideally, we should also get the isec->sid for the
4387 new socket in sync, but we don't have the isec available yet.
4388 So we will wait until sock_graft to do it, by which
4389 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004390
Paul Moore9f2ad662006-11-17 17:38:53 -05004391 /* We don't need to take any sort of lock here as we are the only
4392 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004393 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004394}
4395
Paul Moore014ab192008-10-10 10:16:33 -04004396static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004397{
Paul Mooreaa862902008-10-10 10:16:29 -04004398 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004399 struct sk_security_struct *sksec = sk->sk_security;
4400
Paul Mooreaa862902008-10-10 10:16:29 -04004401 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4402 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4403 family = PF_INET;
4404
4405 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004406}
4407
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004408static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4409{
4410 skb_set_owner_w(skb, sk);
4411}
4412
Eric Paris2606fd12010-10-13 16:24:41 -04004413static int selinux_secmark_relabel_packet(u32 sid)
4414{
4415 const struct task_security_struct *__tsec;
4416 u32 tsid;
4417
4418 __tsec = current_security();
4419 tsid = __tsec->sid;
4420
4421 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4422}
4423
4424static void selinux_secmark_refcount_inc(void)
4425{
4426 atomic_inc(&selinux_secmark_refcount);
4427}
4428
4429static void selinux_secmark_refcount_dec(void)
4430{
4431 atomic_dec(&selinux_secmark_refcount);
4432}
4433
Adrian Bunk9a673e52006-08-15 00:03:53 -07004434static void selinux_req_classify_flow(const struct request_sock *req,
4435 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004436{
David S. Miller1d28f422011-03-12 00:29:39 -05004437 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004438}
4439
Paul Moore5dbbaf22013-01-14 07:12:19 +00004440static int selinux_tun_dev_alloc_security(void **security)
4441{
4442 struct tun_security_struct *tunsec;
4443
4444 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4445 if (!tunsec)
4446 return -ENOMEM;
4447 tunsec->sid = current_sid();
4448
4449 *security = tunsec;
4450 return 0;
4451}
4452
4453static void selinux_tun_dev_free_security(void *security)
4454{
4455 kfree(security);
4456}
4457
Paul Mooreed6d76e2009-08-28 18:12:49 -04004458static int selinux_tun_dev_create(void)
4459{
4460 u32 sid = current_sid();
4461
4462 /* we aren't taking into account the "sockcreate" SID since the socket
4463 * that is being created here is not a socket in the traditional sense,
4464 * instead it is a private sock, accessible only to the kernel, and
4465 * representing a wide range of network traffic spanning multiple
4466 * connections unlike traditional sockets - check the TUN driver to
4467 * get a better understanding of why this socket is special */
4468
4469 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4470 NULL);
4471}
4472
Paul Moore5dbbaf22013-01-14 07:12:19 +00004473static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004474{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004475 struct tun_security_struct *tunsec = security;
4476
4477 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4478 TUN_SOCKET__ATTACH_QUEUE, NULL);
4479}
4480
4481static int selinux_tun_dev_attach(struct sock *sk, void *security)
4482{
4483 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004484 struct sk_security_struct *sksec = sk->sk_security;
4485
4486 /* we don't currently perform any NetLabel based labeling here and it
4487 * isn't clear that we would want to do so anyway; while we could apply
4488 * labeling without the support of the TUN user the resulting labeled
4489 * traffic from the other end of the connection would almost certainly
4490 * cause confusion to the TUN user that had no idea network labeling
4491 * protocols were being used */
4492
Paul Moore5dbbaf22013-01-14 07:12:19 +00004493 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004494 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004495
4496 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004497}
4498
Paul Moore5dbbaf22013-01-14 07:12:19 +00004499static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004500{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004501 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004502 u32 sid = current_sid();
4503 int err;
4504
Paul Moore5dbbaf22013-01-14 07:12:19 +00004505 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004506 TUN_SOCKET__RELABELFROM, NULL);
4507 if (err)
4508 return err;
4509 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4510 TUN_SOCKET__RELABELTO, NULL);
4511 if (err)
4512 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004513 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004514
4515 return 0;
4516}
4517
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4519{
4520 int err = 0;
4521 u32 perm;
4522 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004523 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004524
Hong zhi guo77954982013-03-27 06:49:35 +00004525 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526 err = -EINVAL;
4527 goto out;
4528 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004529 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004530
Paul Moore253bfae2010-04-22 14:46:19 -04004531 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 if (err) {
4533 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004534 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535 "SELinux: unrecognized netlink message"
4536 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004537 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004538 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539 err = 0;
4540 }
4541
4542 /* Ignore */
4543 if (err == -ENOENT)
4544 err = 0;
4545 goto out;
4546 }
4547
Paul Moore253bfae2010-04-22 14:46:19 -04004548 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549out:
4550 return err;
4551}
4552
4553#ifdef CONFIG_NETFILTER
4554
Paul Mooreeffad8d2008-01-29 08:49:27 -05004555static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4556 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557{
Paul Mooredfaebe92008-10-10 10:16:31 -04004558 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004559 char *addrp;
4560 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004561 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004562 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004563 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004564 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004565 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004566
Paul Mooreeffad8d2008-01-29 08:49:27 -05004567 if (!selinux_policycap_netpeer)
4568 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004569
Paul Mooreeffad8d2008-01-29 08:49:27 -05004570 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004571 netlbl_active = netlbl_enabled();
4572 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004573 if (!secmark_active && !peerlbl_active)
4574 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004575
Paul Moored8395c82008-10-10 10:16:30 -04004576 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4577 return NF_DROP;
4578
Eric Paris50c205f2012-04-04 15:01:43 -04004579 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004580 ad.u.net = &net;
4581 ad.u.net->netif = ifindex;
4582 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004583 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4584 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585
Paul Mooredfaebe92008-10-10 10:16:31 -04004586 if (peerlbl_active) {
4587 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4588 peer_sid, &ad);
4589 if (err) {
4590 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004591 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004592 }
4593 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004594
4595 if (secmark_active)
4596 if (avc_has_perm(peer_sid, skb->secmark,
4597 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4598 return NF_DROP;
4599
Paul Moore948bf852008-10-10 10:16:32 -04004600 if (netlbl_active)
4601 /* we do this in the FORWARD path and not the POST_ROUTING
4602 * path because we want to make sure we apply the necessary
4603 * labeling before IPsec is applied so we can leverage AH
4604 * protection */
4605 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4606 return NF_DROP;
4607
Paul Mooreeffad8d2008-01-29 08:49:27 -05004608 return NF_ACCEPT;
4609}
4610
4611static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4612 struct sk_buff *skb,
4613 const struct net_device *in,
4614 const struct net_device *out,
4615 int (*okfn)(struct sk_buff *))
4616{
4617 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4618}
4619
4620#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4621static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4622 struct sk_buff *skb,
4623 const struct net_device *in,
4624 const struct net_device *out,
4625 int (*okfn)(struct sk_buff *))
4626{
4627 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4628}
4629#endif /* IPV6 */
4630
Paul Moore948bf852008-10-10 10:16:32 -04004631static unsigned int selinux_ip_output(struct sk_buff *skb,
4632 u16 family)
4633{
4634 u32 sid;
4635
4636 if (!netlbl_enabled())
4637 return NF_ACCEPT;
4638
4639 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4640 * because we want to make sure we apply the necessary labeling
4641 * before IPsec is applied so we can leverage AH protection */
4642 if (skb->sk) {
4643 struct sk_security_struct *sksec = skb->sk->sk_security;
4644 sid = sksec->sid;
4645 } else
4646 sid = SECINITSID_KERNEL;
4647 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4648 return NF_DROP;
4649
4650 return NF_ACCEPT;
4651}
4652
4653static unsigned int selinux_ipv4_output(unsigned int hooknum,
4654 struct sk_buff *skb,
4655 const struct net_device *in,
4656 const struct net_device *out,
4657 int (*okfn)(struct sk_buff *))
4658{
4659 return selinux_ip_output(skb, PF_INET);
4660}
4661
Paul Mooreeffad8d2008-01-29 08:49:27 -05004662static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4663 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004664 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004665{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004666 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004667 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004668 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004669 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004670 char *addrp;
4671 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004672
Paul Mooreeffad8d2008-01-29 08:49:27 -05004673 if (sk == NULL)
4674 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004675 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004676
Eric Paris50c205f2012-04-04 15:01:43 -04004677 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004678 ad.u.net = &net;
4679 ad.u.net->netif = ifindex;
4680 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004681 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4682 return NF_DROP;
4683
Paul Moore58bfbb52009-03-27 17:10:41 -04004684 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004685 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004686 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004687 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004688
Steffen Klassertb9679a72011-02-23 12:55:21 +01004689 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4690 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004691
Paul Mooreeffad8d2008-01-29 08:49:27 -05004692 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693}
4694
Paul Mooreeffad8d2008-01-29 08:49:27 -05004695static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4696 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004698 u32 secmark_perm;
4699 u32 peer_sid;
4700 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004701 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004702 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004703 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004704 u8 secmark_active;
4705 u8 peerlbl_active;
4706
Paul Mooreeffad8d2008-01-29 08:49:27 -05004707 /* If any sort of compatibility mode is enabled then handoff processing
4708 * to the selinux_ip_postroute_compat() function to deal with the
4709 * special handling. We do this in an attempt to keep this function
4710 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004711 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004712 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004713#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004714 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4715 * packet transformation so allow the packet to pass without any checks
4716 * since we'll have another chance to perform access control checks
4717 * when the packet is on it's final way out.
4718 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4719 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004720 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004721 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004722#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004723 secmark_active = selinux_secmark_enabled();
4724 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4725 if (!secmark_active && !peerlbl_active)
4726 return NF_ACCEPT;
4727
Paul Moored8395c82008-10-10 10:16:30 -04004728 /* if the packet is being forwarded then get the peer label from the
4729 * packet itself; otherwise check to see if it is from a local
4730 * application or the kernel, if from an application get the peer label
4731 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004732 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004733 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004734 if (skb->skb_iif) {
4735 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004736 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004737 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004738 } else {
4739 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004740 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004741 }
Paul Moored8395c82008-10-10 10:16:30 -04004742 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004743 struct sk_security_struct *sksec = sk->sk_security;
4744 peer_sid = sksec->sid;
4745 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004746 }
4747
Eric Paris50c205f2012-04-04 15:01:43 -04004748 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004749 ad.u.net = &net;
4750 ad.u.net->netif = ifindex;
4751 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004752 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004753 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004754
Paul Mooreeffad8d2008-01-29 08:49:27 -05004755 if (secmark_active)
4756 if (avc_has_perm(peer_sid, skb->secmark,
4757 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004758 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004759
4760 if (peerlbl_active) {
4761 u32 if_sid;
4762 u32 node_sid;
4763
4764 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004765 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004766 if (avc_has_perm(peer_sid, if_sid,
4767 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004768 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004769
4770 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004771 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004772 if (avc_has_perm(peer_sid, node_sid,
4773 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004774 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004775 }
4776
4777 return NF_ACCEPT;
4778}
4779
4780static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4781 struct sk_buff *skb,
4782 const struct net_device *in,
4783 const struct net_device *out,
4784 int (*okfn)(struct sk_buff *))
4785{
4786 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787}
4788
4789#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004790static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4791 struct sk_buff *skb,
4792 const struct net_device *in,
4793 const struct net_device *out,
4794 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004796 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798#endif /* IPV6 */
4799
4800#endif /* CONFIG_NETFILTER */
4801
Linus Torvalds1da177e2005-04-16 15:20:36 -07004802static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4803{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 int err;
4805
Eric Paris200ac532009-02-12 15:01:04 -05004806 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807 if (err)
4808 return err;
4809
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004810 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004811}
4812
Linus Torvalds1da177e2005-04-16 15:20:36 -07004813static int ipc_alloc_security(struct task_struct *task,
4814 struct kern_ipc_perm *perm,
4815 u16 sclass)
4816{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004818 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004819
James Morris89d155e2005-10-30 14:59:21 -08004820 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821 if (!isec)
4822 return -ENOMEM;
4823
David Howells275bb412008-11-14 10:39:19 +11004824 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11004826 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 perm->security = isec;
4828
4829 return 0;
4830}
4831
4832static void ipc_free_security(struct kern_ipc_perm *perm)
4833{
4834 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835 perm->security = NULL;
4836 kfree(isec);
4837}
4838
4839static int msg_msg_alloc_security(struct msg_msg *msg)
4840{
4841 struct msg_security_struct *msec;
4842
James Morris89d155e2005-10-30 14:59:21 -08004843 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844 if (!msec)
4845 return -ENOMEM;
4846
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 msec->sid = SECINITSID_UNLABELED;
4848 msg->security = msec;
4849
4850 return 0;
4851}
4852
4853static void msg_msg_free_security(struct msg_msg *msg)
4854{
4855 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856
4857 msg->security = NULL;
4858 kfree(msec);
4859}
4860
4861static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004862 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004865 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004866 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868 isec = ipc_perms->security;
4869
Eric Paris50c205f2012-04-04 15:01:43 -04004870 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871 ad.u.ipc_id = ipc_perms->key;
4872
David Howells275bb412008-11-14 10:39:19 +11004873 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004874}
4875
4876static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4877{
4878 return msg_msg_alloc_security(msg);
4879}
4880
4881static void selinux_msg_msg_free_security(struct msg_msg *msg)
4882{
4883 msg_msg_free_security(msg);
4884}
4885
4886/* message queue security operations */
4887static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4888{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004890 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004891 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 int rc;
4893
4894 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4895 if (rc)
4896 return rc;
4897
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898 isec = msq->q_perm.security;
4899
Eric Paris50c205f2012-04-04 15:01:43 -04004900 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04004901 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902
David Howells275bb412008-11-14 10:39:19 +11004903 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904 MSGQ__CREATE, &ad);
4905 if (rc) {
4906 ipc_free_security(&msq->q_perm);
4907 return rc;
4908 }
4909 return 0;
4910}
4911
4912static void selinux_msg_queue_free_security(struct msg_queue *msq)
4913{
4914 ipc_free_security(&msq->q_perm);
4915}
4916
4917static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4918{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004920 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004921 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923 isec = msq->q_perm.security;
4924
Eric Paris50c205f2012-04-04 15:01:43 -04004925 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926 ad.u.ipc_id = msq->q_perm.key;
4927
David Howells275bb412008-11-14 10:39:19 +11004928 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929 MSGQ__ASSOCIATE, &ad);
4930}
4931
4932static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4933{
4934 int err;
4935 int perms;
4936
Eric Paris828dfe12008-04-17 13:17:49 -04004937 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938 case IPC_INFO:
4939 case MSG_INFO:
4940 /* No specific object, just general system-wide information. */
4941 return task_has_system(current, SYSTEM__IPC_INFO);
4942 case IPC_STAT:
4943 case MSG_STAT:
4944 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4945 break;
4946 case IPC_SET:
4947 perms = MSGQ__SETATTR;
4948 break;
4949 case IPC_RMID:
4950 perms = MSGQ__DESTROY;
4951 break;
4952 default:
4953 return 0;
4954 }
4955
Stephen Smalley6af963f2005-05-01 08:58:39 -07004956 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004957 return err;
4958}
4959
4960static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4961{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 struct ipc_security_struct *isec;
4963 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004964 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004965 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966 int rc;
4967
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968 isec = msq->q_perm.security;
4969 msec = msg->security;
4970
4971 /*
4972 * First time through, need to assign label to the message
4973 */
4974 if (msec->sid == SECINITSID_UNLABELED) {
4975 /*
4976 * Compute new sid based on current process and
4977 * message queue this message will be stored in
4978 */
David Howells275bb412008-11-14 10:39:19 +11004979 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05004980 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981 if (rc)
4982 return rc;
4983 }
4984
Eric Paris50c205f2012-04-04 15:01:43 -04004985 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986 ad.u.ipc_id = msq->q_perm.key;
4987
4988 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11004989 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990 MSGQ__WRITE, &ad);
4991 if (!rc)
4992 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11004993 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
4994 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995 if (!rc)
4996 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11004997 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
4998 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999
5000 return rc;
5001}
5002
5003static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5004 struct task_struct *target,
5005 long type, int mode)
5006{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007 struct ipc_security_struct *isec;
5008 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005009 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005010 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 int rc;
5012
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013 isec = msq->q_perm.security;
5014 msec = msg->security;
5015
Eric Paris50c205f2012-04-04 15:01:43 -04005016 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005017 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018
David Howells275bb412008-11-14 10:39:19 +11005019 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 SECCLASS_MSGQ, MSGQ__READ, &ad);
5021 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005022 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023 SECCLASS_MSG, MSG__RECEIVE, &ad);
5024 return rc;
5025}
5026
5027/* Shared Memory security operations */
5028static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5029{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005031 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005032 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033 int rc;
5034
5035 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5036 if (rc)
5037 return rc;
5038
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039 isec = shp->shm_perm.security;
5040
Eric Paris50c205f2012-04-04 15:01:43 -04005041 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005042 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043
David Howells275bb412008-11-14 10:39:19 +11005044 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 SHM__CREATE, &ad);
5046 if (rc) {
5047 ipc_free_security(&shp->shm_perm);
5048 return rc;
5049 }
5050 return 0;
5051}
5052
5053static void selinux_shm_free_security(struct shmid_kernel *shp)
5054{
5055 ipc_free_security(&shp->shm_perm);
5056}
5057
5058static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5059{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005061 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005062 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064 isec = shp->shm_perm.security;
5065
Eric Paris50c205f2012-04-04 15:01:43 -04005066 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067 ad.u.ipc_id = shp->shm_perm.key;
5068
David Howells275bb412008-11-14 10:39:19 +11005069 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070 SHM__ASSOCIATE, &ad);
5071}
5072
5073/* Note, at this point, shp is locked down */
5074static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5075{
5076 int perms;
5077 int err;
5078
Eric Paris828dfe12008-04-17 13:17:49 -04005079 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080 case IPC_INFO:
5081 case SHM_INFO:
5082 /* No specific object, just general system-wide information. */
5083 return task_has_system(current, SYSTEM__IPC_INFO);
5084 case IPC_STAT:
5085 case SHM_STAT:
5086 perms = SHM__GETATTR | SHM__ASSOCIATE;
5087 break;
5088 case IPC_SET:
5089 perms = SHM__SETATTR;
5090 break;
5091 case SHM_LOCK:
5092 case SHM_UNLOCK:
5093 perms = SHM__LOCK;
5094 break;
5095 case IPC_RMID:
5096 perms = SHM__DESTROY;
5097 break;
5098 default:
5099 return 0;
5100 }
5101
Stephen Smalley6af963f2005-05-01 08:58:39 -07005102 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103 return err;
5104}
5105
5106static int selinux_shm_shmat(struct shmid_kernel *shp,
5107 char __user *shmaddr, int shmflg)
5108{
5109 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110
5111 if (shmflg & SHM_RDONLY)
5112 perms = SHM__READ;
5113 else
5114 perms = SHM__READ | SHM__WRITE;
5115
Stephen Smalley6af963f2005-05-01 08:58:39 -07005116 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117}
5118
5119/* Semaphore security operations */
5120static int selinux_sem_alloc_security(struct sem_array *sma)
5121{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005123 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005124 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 int rc;
5126
5127 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5128 if (rc)
5129 return rc;
5130
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131 isec = sma->sem_perm.security;
5132
Eric Paris50c205f2012-04-04 15:01:43 -04005133 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005134 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135
David Howells275bb412008-11-14 10:39:19 +11005136 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137 SEM__CREATE, &ad);
5138 if (rc) {
5139 ipc_free_security(&sma->sem_perm);
5140 return rc;
5141 }
5142 return 0;
5143}
5144
5145static void selinux_sem_free_security(struct sem_array *sma)
5146{
5147 ipc_free_security(&sma->sem_perm);
5148}
5149
5150static int selinux_sem_associate(struct sem_array *sma, int semflg)
5151{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005153 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005154 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156 isec = sma->sem_perm.security;
5157
Eric Paris50c205f2012-04-04 15:01:43 -04005158 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 ad.u.ipc_id = sma->sem_perm.key;
5160
David Howells275bb412008-11-14 10:39:19 +11005161 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162 SEM__ASSOCIATE, &ad);
5163}
5164
5165/* Note, at this point, sma is locked down */
5166static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5167{
5168 int err;
5169 u32 perms;
5170
Eric Paris828dfe12008-04-17 13:17:49 -04005171 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 case IPC_INFO:
5173 case SEM_INFO:
5174 /* No specific object, just general system-wide information. */
5175 return task_has_system(current, SYSTEM__IPC_INFO);
5176 case GETPID:
5177 case GETNCNT:
5178 case GETZCNT:
5179 perms = SEM__GETATTR;
5180 break;
5181 case GETVAL:
5182 case GETALL:
5183 perms = SEM__READ;
5184 break;
5185 case SETVAL:
5186 case SETALL:
5187 perms = SEM__WRITE;
5188 break;
5189 case IPC_RMID:
5190 perms = SEM__DESTROY;
5191 break;
5192 case IPC_SET:
5193 perms = SEM__SETATTR;
5194 break;
5195 case IPC_STAT:
5196 case SEM_STAT:
5197 perms = SEM__GETATTR | SEM__ASSOCIATE;
5198 break;
5199 default:
5200 return 0;
5201 }
5202
Stephen Smalley6af963f2005-05-01 08:58:39 -07005203 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 return err;
5205}
5206
5207static int selinux_sem_semop(struct sem_array *sma,
5208 struct sembuf *sops, unsigned nsops, int alter)
5209{
5210 u32 perms;
5211
5212 if (alter)
5213 perms = SEM__READ | SEM__WRITE;
5214 else
5215 perms = SEM__READ;
5216
Stephen Smalley6af963f2005-05-01 08:58:39 -07005217 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218}
5219
5220static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5221{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222 u32 av = 0;
5223
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 av = 0;
5225 if (flag & S_IRUGO)
5226 av |= IPC__UNIX_READ;
5227 if (flag & S_IWUGO)
5228 av |= IPC__UNIX_WRITE;
5229
5230 if (av == 0)
5231 return 0;
5232
Stephen Smalley6af963f2005-05-01 08:58:39 -07005233 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234}
5235
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005236static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5237{
5238 struct ipc_security_struct *isec = ipcp->security;
5239 *secid = isec->sid;
5240}
5241
Eric Paris828dfe12008-04-17 13:17:49 -04005242static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005243{
5244 if (inode)
5245 inode_doinit_with_dentry(inode, dentry);
5246}
5247
5248static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005249 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250{
David Howells275bb412008-11-14 10:39:19 +11005251 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005252 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005254 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255
5256 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005257 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 if (error)
5259 return error;
5260 }
5261
David Howells275bb412008-11-14 10:39:19 +11005262 rcu_read_lock();
5263 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264
5265 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005266 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005268 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005270 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005272 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005273 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005274 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005275 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005276 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 else
David Howells275bb412008-11-14 10:39:19 +11005278 goto invalid;
5279 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280
5281 if (!sid)
5282 return 0;
5283
Al Viro04ff9702007-03-12 16:17:58 +00005284 error = security_sid_to_context(sid, value, &len);
5285 if (error)
5286 return error;
5287 return len;
David Howells275bb412008-11-14 10:39:19 +11005288
5289invalid:
5290 rcu_read_unlock();
5291 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292}
5293
5294static int selinux_setprocattr(struct task_struct *p,
5295 char *name, void *value, size_t size)
5296{
5297 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005298 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005299 struct cred *new;
5300 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301 int error;
5302 char *str = value;
5303
5304 if (current != p) {
5305 /* SELinux only allows a process to change its own
5306 security attributes. */
5307 return -EACCES;
5308 }
5309
5310 /*
5311 * Basic control over ability to set these attributes at all.
5312 * current == p, but we'll pass them separately in case the
5313 * above restriction is ever removed.
5314 */
5315 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005316 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005318 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005319 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005320 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005321 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005322 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005324 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325 else
5326 error = -EINVAL;
5327 if (error)
5328 return error;
5329
5330 /* Obtain a SID for the context, if one was specified. */
5331 if (size && str[1] && str[1] != '\n') {
5332 if (str[size-1] == '\n') {
5333 str[size-1] = 0;
5334 size--;
5335 }
5336 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005337 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005338 if (!capable(CAP_MAC_ADMIN)) {
5339 struct audit_buffer *ab;
5340 size_t audit_size;
5341
5342 /* We strip a nul only if it is at the end, otherwise the
5343 * context contains a nul and we should audit that */
5344 if (str[size - 1] == '\0')
5345 audit_size = size - 1;
5346 else
5347 audit_size = size;
5348 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5349 audit_log_format(ab, "op=fscreate invalid_context=");
5350 audit_log_n_untrustedstring(ab, value, audit_size);
5351 audit_log_end(ab);
5352
Stephen Smalley12b29f32008-05-07 13:03:20 -04005353 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005354 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005355 error = security_context_to_sid_force(value, size,
5356 &sid);
5357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358 if (error)
5359 return error;
5360 }
5361
David Howellsd84f4f92008-11-14 10:39:23 +11005362 new = prepare_creds();
5363 if (!new)
5364 return -ENOMEM;
5365
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366 /* Permission checking based on the specified context is
5367 performed during the actual operation (execve,
5368 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005369 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370 checks and may_create for the file creation checks. The
5371 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005372 tsec = new->security;
5373 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005375 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005377 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005378 error = may_create_key(sid, p);
5379 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005380 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005381 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005382 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005383 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005384 } else if (!strcmp(name, "current")) {
5385 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005387 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005388
David Howellsd84f4f92008-11-14 10:39:23 +11005389 /* Only allow single threaded processes to change context */
5390 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005391 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005392 error = security_bounded_transition(tsec->sid, sid);
5393 if (error)
5394 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
5397 /* Check permissions for the transition. */
5398 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005399 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005401 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
5403 /* Check for ptracing, and update the task SID if ok.
5404 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005405 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005407 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005408 if (tracer)
5409 ptsid = task_sid(tracer);
5410 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411
David Howellsd84f4f92008-11-14 10:39:23 +11005412 if (tracer) {
5413 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5414 PROCESS__PTRACE, NULL);
5415 if (error)
5416 goto abort_change;
5417 }
5418
5419 tsec->sid = sid;
5420 } else {
5421 error = -EINVAL;
5422 goto abort_change;
5423 }
5424
5425 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005427
5428abort_change:
5429 abort_creds(new);
5430 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431}
5432
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005433static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5434{
5435 return security_sid_to_context(secid, secdata, seclen);
5436}
5437
David Howells7bf570d2008-04-29 20:52:51 +01005438static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005439{
5440 return security_context_to_sid(secdata, seclen, secid);
5441}
5442
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005443static void selinux_release_secctx(char *secdata, u32 seclen)
5444{
Paul Moore088999e2007-08-01 11:12:58 -04005445 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005446}
5447
David P. Quigley1ee65e32009-09-03 14:25:57 -04005448/*
5449 * called with inode->i_mutex locked
5450 */
5451static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5452{
5453 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5454}
5455
5456/*
5457 * called with inode->i_mutex locked
5458 */
5459static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5460{
5461 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5462}
5463
5464static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5465{
5466 int len = 0;
5467 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5468 ctx, true);
5469 if (len < 0)
5470 return len;
5471 *ctxlen = len;
5472 return 0;
5473}
Michael LeMayd7200242006-06-22 14:47:17 -07005474#ifdef CONFIG_KEYS
5475
David Howellsd84f4f92008-11-14 10:39:23 +11005476static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005477 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005478{
David Howellsd84f4f92008-11-14 10:39:23 +11005479 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005480 struct key_security_struct *ksec;
5481
5482 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5483 if (!ksec)
5484 return -ENOMEM;
5485
David Howellsd84f4f92008-11-14 10:39:23 +11005486 tsec = cred->security;
5487 if (tsec->keycreate_sid)
5488 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005489 else
David Howellsd84f4f92008-11-14 10:39:23 +11005490 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005491
David Howells275bb412008-11-14 10:39:19 +11005492 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005493 return 0;
5494}
5495
5496static void selinux_key_free(struct key *k)
5497{
5498 struct key_security_struct *ksec = k->security;
5499
5500 k->security = NULL;
5501 kfree(ksec);
5502}
5503
5504static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005505 const struct cred *cred,
5506 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005507{
5508 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005509 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005510 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005511
5512 /* if no specific permissions are requested, we skip the
5513 permission check. No serious, additional covert channels
5514 appear to be created. */
5515 if (perm == 0)
5516 return 0;
5517
David Howellsd84f4f92008-11-14 10:39:23 +11005518 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005519
5520 key = key_ref_to_ptr(key_ref);
5521 ksec = key->security;
5522
5523 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005524}
5525
David Howells70a5bb72008-04-29 01:01:26 -07005526static int selinux_key_getsecurity(struct key *key, char **_buffer)
5527{
5528 struct key_security_struct *ksec = key->security;
5529 char *context = NULL;
5530 unsigned len;
5531 int rc;
5532
5533 rc = security_sid_to_context(ksec->sid, &context, &len);
5534 if (!rc)
5535 rc = len;
5536 *_buffer = context;
5537 return rc;
5538}
5539
Michael LeMayd7200242006-06-22 14:47:17 -07005540#endif
5541
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005543 .name = "selinux",
5544
Ingo Molnar9e488582009-05-07 19:26:19 +10005545 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005546 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005548 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549 .capable = selinux_capable,
5550 .quotactl = selinux_quotactl,
5551 .quota_on = selinux_quota_on,
5552 .syslog = selinux_syslog,
5553 .vm_enough_memory = selinux_vm_enough_memory,
5554
5555 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556
David Howellsa6f76f22008-11-14 10:39:24 +11005557 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005558 .bprm_committing_creds = selinux_bprm_committing_creds,
5559 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 .bprm_secureexec = selinux_bprm_secureexec,
5561
5562 .sb_alloc_security = selinux_sb_alloc_security,
5563 .sb_free_security = selinux_sb_free_security,
5564 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005565 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005566 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005567 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 .sb_statfs = selinux_sb_statfs,
5569 .sb_mount = selinux_mount,
5570 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005571 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005572 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005573 .sb_parse_opts_str = selinux_parse_opts_str,
5574
Linus Torvalds1da177e2005-04-16 15:20:36 -07005575
5576 .inode_alloc_security = selinux_inode_alloc_security,
5577 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005578 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581 .inode_unlink = selinux_inode_unlink,
5582 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 .inode_rmdir = selinux_inode_rmdir,
5585 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587 .inode_readlink = selinux_inode_readlink,
5588 .inode_follow_link = selinux_inode_follow_link,
5589 .inode_permission = selinux_inode_permission,
5590 .inode_setattr = selinux_inode_setattr,
5591 .inode_getattr = selinux_inode_getattr,
5592 .inode_setxattr = selinux_inode_setxattr,
5593 .inode_post_setxattr = selinux_inode_post_setxattr,
5594 .inode_getxattr = selinux_inode_getxattr,
5595 .inode_listxattr = selinux_inode_listxattr,
5596 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005597 .inode_getsecurity = selinux_inode_getsecurity,
5598 .inode_setsecurity = selinux_inode_setsecurity,
5599 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005600 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005601
5602 .file_permission = selinux_file_permission,
5603 .file_alloc_security = selinux_file_alloc_security,
5604 .file_free_security = selinux_file_free_security,
5605 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005606 .mmap_file = selinux_mmap_file,
5607 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005608 .file_mprotect = selinux_file_mprotect,
5609 .file_lock = selinux_file_lock,
5610 .file_fcntl = selinux_file_fcntl,
5611 .file_set_fowner = selinux_file_set_fowner,
5612 .file_send_sigiotask = selinux_file_send_sigiotask,
5613 .file_receive = selinux_file_receive,
5614
Eric Paris83d49852012-04-04 13:45:40 -04005615 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005616
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005618 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005619 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005620 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005621 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005622 .kernel_act_as = selinux_kernel_act_as,
5623 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005624 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 .task_setpgid = selinux_task_setpgid,
5626 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005627 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005628 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005630 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005631 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005632 .task_setrlimit = selinux_task_setrlimit,
5633 .task_setscheduler = selinux_task_setscheduler,
5634 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005635 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636 .task_kill = selinux_task_kill,
5637 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005638 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639
5640 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005641 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642
5643 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5644 .msg_msg_free_security = selinux_msg_msg_free_security,
5645
5646 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5647 .msg_queue_free_security = selinux_msg_queue_free_security,
5648 .msg_queue_associate = selinux_msg_queue_associate,
5649 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5650 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5651 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5652
5653 .shm_alloc_security = selinux_shm_alloc_security,
5654 .shm_free_security = selinux_shm_free_security,
5655 .shm_associate = selinux_shm_associate,
5656 .shm_shmctl = selinux_shm_shmctl,
5657 .shm_shmat = selinux_shm_shmat,
5658
Eric Paris828dfe12008-04-17 13:17:49 -04005659 .sem_alloc_security = selinux_sem_alloc_security,
5660 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 .sem_associate = selinux_sem_associate,
5662 .sem_semctl = selinux_sem_semctl,
5663 .sem_semop = selinux_sem_semop,
5664
Eric Paris828dfe12008-04-17 13:17:49 -04005665 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666
Eric Paris828dfe12008-04-17 13:17:49 -04005667 .getprocattr = selinux_getprocattr,
5668 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005670 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005671 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005672 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005673 .inode_notifysecctx = selinux_inode_notifysecctx,
5674 .inode_setsecctx = selinux_inode_setsecctx,
5675 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005676
Eric Paris828dfe12008-04-17 13:17:49 -04005677 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678 .unix_may_send = selinux_socket_unix_may_send,
5679
5680 .socket_create = selinux_socket_create,
5681 .socket_post_create = selinux_socket_post_create,
5682 .socket_bind = selinux_socket_bind,
5683 .socket_connect = selinux_socket_connect,
5684 .socket_listen = selinux_socket_listen,
5685 .socket_accept = selinux_socket_accept,
5686 .socket_sendmsg = selinux_socket_sendmsg,
5687 .socket_recvmsg = selinux_socket_recvmsg,
5688 .socket_getsockname = selinux_socket_getsockname,
5689 .socket_getpeername = selinux_socket_getpeername,
5690 .socket_getsockopt = selinux_socket_getsockopt,
5691 .socket_setsockopt = selinux_socket_setsockopt,
5692 .socket_shutdown = selinux_socket_shutdown,
5693 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005694 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5695 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696 .sk_alloc_security = selinux_sk_alloc_security,
5697 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005698 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005699 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005700 .sock_graft = selinux_sock_graft,
5701 .inet_conn_request = selinux_inet_conn_request,
5702 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005703 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005704 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5705 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5706 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005707 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005708 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5709 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005710 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005711 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005712 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005713 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005714 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005715
5716#ifdef CONFIG_SECURITY_NETWORK_XFRM
5717 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5718 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5719 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005720 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Paul Moore2e5aa862013-07-23 17:38:38 -04005721 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5722 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005723 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005724 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005725 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005726 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005727 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005728#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005729
5730#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005731 .key_alloc = selinux_key_alloc,
5732 .key_free = selinux_key_free,
5733 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005734 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005735#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005736
5737#ifdef CONFIG_AUDIT
5738 .audit_rule_init = selinux_audit_rule_init,
5739 .audit_rule_known = selinux_audit_rule_known,
5740 .audit_rule_match = selinux_audit_rule_match,
5741 .audit_rule_free = selinux_audit_rule_free,
5742#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743};
5744
5745static __init int selinux_init(void)
5746{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005747 if (!security_module_enable(&selinux_ops)) {
5748 selinux_enabled = 0;
5749 return 0;
5750 }
5751
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752 if (!selinux_enabled) {
5753 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5754 return 0;
5755 }
5756
5757 printk(KERN_INFO "SELinux: Initializing.\n");
5758
5759 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005760 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005761
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005762 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5763
James Morris7cae7e22006-03-22 00:09:22 -08005764 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5765 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005766 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767 avc_init();
5768
Eric Paris828dfe12008-04-17 13:17:49 -04005769 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770 panic("SELinux: Unable to register with kernel.\n");
5771
Eric Paris828dfe12008-04-17 13:17:49 -04005772 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005773 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005774 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005775 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005776
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777 return 0;
5778}
5779
Al Viroe8c26252010-03-23 06:36:54 -04005780static void delayed_superblock_init(struct super_block *sb, void *unused)
5781{
5782 superblock_doinit(sb, NULL);
5783}
5784
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785void selinux_complete_init(void)
5786{
Eric Parisfadcdb42007-02-22 18:11:31 -05005787 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788
5789 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005790 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005791 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792}
5793
5794/* SELinux requires early initialization in order to label
5795 all processes and objects when they are created. */
5796security_initcall(selinux_init);
5797
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005798#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799
Paul Mooreeffad8d2008-01-29 08:49:27 -05005800static struct nf_hook_ops selinux_ipv4_ops[] = {
5801 {
5802 .hook = selinux_ipv4_postroute,
5803 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005804 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005805 .hooknum = NF_INET_POST_ROUTING,
5806 .priority = NF_IP_PRI_SELINUX_LAST,
5807 },
5808 {
5809 .hook = selinux_ipv4_forward,
5810 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005811 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005812 .hooknum = NF_INET_FORWARD,
5813 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005814 },
5815 {
5816 .hook = selinux_ipv4_output,
5817 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005818 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04005819 .hooknum = NF_INET_LOCAL_OUT,
5820 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822};
5823
5824#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5825
Paul Mooreeffad8d2008-01-29 08:49:27 -05005826static struct nf_hook_ops selinux_ipv6_ops[] = {
5827 {
5828 .hook = selinux_ipv6_postroute,
5829 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005830 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005831 .hooknum = NF_INET_POST_ROUTING,
5832 .priority = NF_IP6_PRI_SELINUX_LAST,
5833 },
5834 {
5835 .hook = selinux_ipv6_forward,
5836 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005837 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005838 .hooknum = NF_INET_FORWARD,
5839 .priority = NF_IP6_PRI_SELINUX_FIRST,
5840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841};
5842
5843#endif /* IPV6 */
5844
5845static int __init selinux_nf_ip_init(void)
5846{
5847 int err = 0;
5848
5849 if (!selinux_enabled)
5850 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005851
5852 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5853
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005854 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5855 if (err)
5856 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857
5858#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005859 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5860 if (err)
5861 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005863
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864out:
5865 return err;
5866}
5867
5868__initcall(selinux_nf_ip_init);
5869
5870#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5871static void selinux_nf_ip_exit(void)
5872{
Eric Parisfadcdb42007-02-22 18:11:31 -05005873 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005875 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005877 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878#endif /* IPV6 */
5879}
5880#endif
5881
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005882#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883
5884#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5885#define selinux_nf_ip_exit()
5886#endif
5887
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005888#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889
5890#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005891static int selinux_disabled;
5892
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893int selinux_disable(void)
5894{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895 if (ss_initialized) {
5896 /* Not permitted after initial policy load. */
5897 return -EINVAL;
5898 }
5899
5900 if (selinux_disabled) {
5901 /* Only do this once. */
5902 return -EINVAL;
5903 }
5904
5905 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5906
5907 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005908 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08005910 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911
Eric Parisaf8ff042009-09-20 21:23:01 -04005912 /* Try to destroy the avc node cache */
5913 avc_disable();
5914
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 /* Unregister netfilter hooks. */
5916 selinux_nf_ip_exit();
5917
5918 /* Unregister selinuxfs. */
5919 exit_sel_fs();
5920
5921 return 0;
5922}
5923#endif