blob: daf59b4bc02baead7876f61528b84a09fadaf32f [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>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#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[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
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
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800129
Paul Moored621d352008-01-29 08:43:36 -0500130/**
131 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
132 *
133 * Description:
134 * This function checks the SECMARK reference counter to see if any SECMARK
135 * targets are currently configured, if the reference counter is greater than
136 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400137 * enabled, false (0) if SECMARK is disabled. If the always_check_network
138 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500139 *
140 */
141static int selinux_secmark_enabled(void)
142{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400143 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
144}
145
146/**
147 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
148 *
149 * Description:
150 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
151 * (1) if any are enabled or false (0) if neither are enabled. If the
152 * always_check_network policy capability is enabled, peer labeling
153 * is always considered enabled.
154 *
155 */
156static int selinux_peerlbl_enabled(void)
157{
158 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500159}
160
Paul Moore615e51f2014-06-26 14:33:56 -0400161static int selinux_netcache_avc_callback(u32 event)
162{
163 if (event == AVC_CALLBACK_RESET) {
164 sel_netif_flush();
165 sel_netnode_flush();
166 sel_netport_flush();
167 synchronize_net();
168 }
169 return 0;
170}
171
David Howellsd84f4f92008-11-14 10:39:23 +1100172/*
173 * initialise the security for the init task
174 */
175static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
David Howells3b11a1d2008-11-14 10:39:26 +1100177 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 struct task_security_struct *tsec;
179
James Morris89d155e2005-10-30 14:59:21 -0800180 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100182 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
David Howellsd84f4f92008-11-14 10:39:23 +1100184 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100185 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
David Howells275bb412008-11-14 10:39:19 +1100188/*
David Howells88e67f32008-11-14 10:39:21 +1100189 * get the security ID of a set of credentials
190 */
191static inline u32 cred_sid(const struct cred *cred)
192{
193 const struct task_security_struct *tsec;
194
195 tsec = cred->security;
196 return tsec->sid;
197}
198
199/*
David Howells3b11a1d2008-11-14 10:39:26 +1100200 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100201 */
202static inline u32 task_sid(const struct task_struct *task)
203{
David Howells275bb412008-11-14 10:39:19 +1100204 u32 sid;
205
206 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100207 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100208 rcu_read_unlock();
209 return sid;
210}
211
212/*
David Howells3b11a1d2008-11-14 10:39:26 +1100213 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100214 */
215static inline u32 current_sid(void)
216{
Paul Moore5fb49872010-04-22 14:46:19 -0400217 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100218
219 return tsec->sid;
220}
221
David Howells88e67f32008-11-14 10:39:21 +1100222/* Allocate and free functions for each kind of security blob. */
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static int inode_alloc_security(struct inode *inode)
225{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100227 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Josef Bacika02fe132008-04-04 09:35:05 +1100229 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 if (!isec)
231 return -ENOMEM;
232
Eric Paris23970742006-09-25 23:32:01 -0700233 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 isec->inode = inode;
236 isec->sid = SECINITSID_UNLABELED;
237 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100238 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 inode->i_security = isec;
240
241 return 0;
242}
243
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500244static void inode_free_rcu(struct rcu_head *head)
245{
246 struct inode_security_struct *isec;
247
248 isec = container_of(head, struct inode_security_struct, rcu);
249 kmem_cache_free(sel_inode_cache, isec);
250}
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252static void inode_free_security(struct inode *inode)
253{
254 struct inode_security_struct *isec = inode->i_security;
255 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 spin_lock(&sbsec->isec_lock);
258 if (!list_empty(&isec->list))
259 list_del_init(&isec->list);
260 spin_unlock(&sbsec->isec_lock);
261
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500262 /*
263 * The inode may still be referenced in a path walk and
264 * a call to selinux_inode_permission() can be made
265 * after inode_free_security() is called. Ideally, the VFS
266 * wouldn't do this, but fixing that is a much harder
267 * job. For now, simply free the i_security via RCU, and
268 * leave the current inode->i_security pointer intact.
269 * The inode will be freed after the RCU grace period too.
270 */
271 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272}
273
274static int file_alloc_security(struct file *file)
275{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100277 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800279 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!fsec)
281 return -ENOMEM;
282
David Howells275bb412008-11-14 10:39:19 +1100283 fsec->sid = sid;
284 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 file->f_security = fsec;
286
287 return 0;
288}
289
290static void file_free_security(struct file *file)
291{
292 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 file->f_security = NULL;
294 kfree(fsec);
295}
296
297static int superblock_alloc_security(struct super_block *sb)
298{
299 struct superblock_security_struct *sbsec;
300
James Morris89d155e2005-10-30 14:59:21 -0800301 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 if (!sbsec)
303 return -ENOMEM;
304
Eric Parisbc7e9822006-09-25 23:32:02 -0700305 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 INIT_LIST_HEAD(&sbsec->isec_head);
307 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sbsec->sb = sb;
309 sbsec->sid = SECINITSID_UNLABELED;
310 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700311 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 sb->s_security = sbsec;
313
314 return 0;
315}
316
317static void superblock_free_security(struct super_block *sb)
318{
319 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 sb->s_security = NULL;
321 kfree(sbsec);
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324/* The file system's label must be initialized prior to use. */
325
David Quigleyeb9ae682013-05-22 12:50:37 -0400326static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 "uses xattr",
328 "uses transition SIDs",
329 "uses task SIDs",
330 "uses genfs_contexts",
331 "not configured for labeling",
332 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400333 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334};
335
336static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
337
338static inline int inode_doinit(struct inode *inode)
339{
340 return inode_doinit_with_dentry(inode, NULL);
341}
342
343enum {
Eric Paris31e87932007-09-19 17:19:12 -0400344 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 Opt_context = 1,
346 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500347 Opt_defcontext = 3,
348 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500349 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400350 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351};
352
Eric Parisd355987f2012-08-24 15:58:53 -0400353#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
354
Steven Whitehousea447c092008-10-13 10:46:57 +0100355static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400356 {Opt_context, CONTEXT_STR "%s"},
357 {Opt_fscontext, FSCONTEXT_STR "%s"},
358 {Opt_defcontext, DEFCONTEXT_STR "%s"},
359 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500360 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400361 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362};
363
364#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
365
Eric Parisc312feb2006-07-10 04:43:53 -0700366static int may_context_mount_sb_relabel(u32 sid,
367 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100368 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700369{
David Howells275bb412008-11-14 10:39:19 +1100370 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700371 int rc;
372
373 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
374 FILESYSTEM__RELABELFROM, NULL);
375 if (rc)
376 return rc;
377
378 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
379 FILESYSTEM__RELABELTO, NULL);
380 return rc;
381}
382
Eric Paris08089252006-07-10 04:43:55 -0700383static int may_context_mount_inode_relabel(u32 sid,
384 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100385 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700386{
David Howells275bb412008-11-14 10:39:19 +1100387 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700388 int rc;
389 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
390 FILESYSTEM__RELABELFROM, NULL);
391 if (rc)
392 return rc;
393
394 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
395 FILESYSTEM__ASSOCIATE, NULL);
396 return rc;
397}
398
Eric Parisb43e7252012-10-10 14:27:35 -0400399static int selinux_is_sblabel_mnt(struct super_block *sb)
400{
401 struct superblock_security_struct *sbsec = sb->s_security;
402
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500403 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
404 sbsec->behavior == SECURITY_FS_USE_TRANS ||
405 sbsec->behavior == SECURITY_FS_USE_TASK ||
406 /* Special handling. Genfs but also in-core setxattr handler */
407 !strcmp(sb->s_type->name, "sysfs") ||
408 !strcmp(sb->s_type->name, "pstore") ||
409 !strcmp(sb->s_type->name, "debugfs") ||
410 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400411}
412
Eric Parisc9180a52007-11-30 13:00:35 -0500413static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
415 struct superblock_security_struct *sbsec = sb->s_security;
416 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000417 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 int rc = 0;
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
421 /* Make sure that the xattr handler exists and that no
422 error other than -ENODATA is returned by getxattr on
423 the root directory. -ENODATA is ok, as this may be
424 the first boot of the SELinux kernel before we have
425 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500426 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800427 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
428 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 rc = -EOPNOTSUPP;
430 goto out;
431 }
Eric Parisc9180a52007-11-30 13:00:35 -0500432 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 if (rc < 0 && rc != -ENODATA) {
434 if (rc == -EOPNOTSUPP)
435 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800436 "%s) has no security xattr handler\n",
437 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 else
439 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800440 "%s) getxattr errno %d\n", sb->s_id,
441 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 goto out;
443 }
444 }
445
Eric Parisc9180a52007-11-30 13:00:35 -0500446 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800447 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
448 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Eric Pariseadcabc2012-08-24 15:59:14 -0400450 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400451 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400452 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500455 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457 /* Initialize any other inodes associated with the superblock, e.g.
458 inodes created prior to initial policy load or inodes created
459 during get_sb by a pseudo filesystem that directly
460 populates itself. */
461 spin_lock(&sbsec->isec_lock);
462next_inode:
463 if (!list_empty(&sbsec->isec_head)) {
464 struct inode_security_struct *isec =
465 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500466 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400468 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 spin_unlock(&sbsec->isec_lock);
470 inode = igrab(inode);
471 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500472 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 inode_doinit(inode);
474 iput(inode);
475 }
476 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 goto next_inode;
478 }
479 spin_unlock(&sbsec->isec_lock);
480out:
Eric Parisc9180a52007-11-30 13:00:35 -0500481 return rc;
482}
483
484/*
485 * This function should allow an FS to ask what it's mount security
486 * options were so it can use those later for submounts, displaying
487 * mount options, or whatever.
488 */
489static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500490 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500491{
492 int rc = 0, i;
493 struct superblock_security_struct *sbsec = sb->s_security;
494 char *context = NULL;
495 u32 len;
496 char tmp;
497
Eric Parise0007522008-03-05 10:31:54 -0500498 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500499
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500500 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500501 return -EINVAL;
502
503 if (!ss_initialized)
504 return -EINVAL;
505
Eric Parisaf8e50c2012-08-24 15:59:00 -0400506 /* make sure we always check enough bits to cover the mask */
507 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
508
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500509 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500510 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400511 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500512 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500513 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500514 tmp >>= 1;
515 }
David P. Quigley11689d42009-01-16 09:22:03 -0500516 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400517 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500518 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500519
Eric Parise0007522008-03-05 10:31:54 -0500520 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
521 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500522 rc = -ENOMEM;
523 goto out_free;
524 }
525
Eric Parise0007522008-03-05 10:31:54 -0500526 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
527 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500528 rc = -ENOMEM;
529 goto out_free;
530 }
531
532 i = 0;
533 if (sbsec->flags & FSCONTEXT_MNT) {
534 rc = security_sid_to_context(sbsec->sid, &context, &len);
535 if (rc)
536 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500537 opts->mnt_opts[i] = context;
538 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500539 }
540 if (sbsec->flags & CONTEXT_MNT) {
541 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
542 if (rc)
543 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500544 opts->mnt_opts[i] = context;
545 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500546 }
547 if (sbsec->flags & DEFCONTEXT_MNT) {
548 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
549 if (rc)
550 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500551 opts->mnt_opts[i] = context;
552 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500553 }
554 if (sbsec->flags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000555 struct inode *root = d_backing_inode(sbsec->sb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500556 struct inode_security_struct *isec = root->i_security;
557
558 rc = security_sid_to_context(isec->sid, &context, &len);
559 if (rc)
560 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500561 opts->mnt_opts[i] = context;
562 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500563 }
Eric Paris12f348b2012-10-09 10:56:25 -0400564 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500565 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400566 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500567 }
Eric Parisc9180a52007-11-30 13:00:35 -0500568
Eric Parise0007522008-03-05 10:31:54 -0500569 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500570
571 return 0;
572
573out_free:
Eric Parise0007522008-03-05 10:31:54 -0500574 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500575 return rc;
576}
577
578static int bad_option(struct superblock_security_struct *sbsec, char flag,
579 u32 old_sid, u32 new_sid)
580{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500581 char mnt_flags = sbsec->flags & SE_MNTMASK;
582
Eric Parisc9180a52007-11-30 13:00:35 -0500583 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500584 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500585 if (!(sbsec->flags & flag) ||
586 (old_sid != new_sid))
587 return 1;
588
589 /* check if we were passed the same options twice,
590 * aka someone passed context=a,context=b
591 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500592 if (!(sbsec->flags & SE_SBINITIALIZED))
593 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500594 return 1;
595 return 0;
596}
Eric Parise0007522008-03-05 10:31:54 -0500597
Eric Parisc9180a52007-11-30 13:00:35 -0500598/*
599 * Allow filesystems with binary mount data to explicitly set mount point
600 * labeling information.
601 */
Eric Parise0007522008-03-05 10:31:54 -0500602static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400603 struct security_mnt_opts *opts,
604 unsigned long kern_flags,
605 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500606{
David Howells275bb412008-11-14 10:39:19 +1100607 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500608 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500609 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800610 const char *name = sb->s_type->name;
David Howellsc6f493d2015-03-17 22:26:22 +0000611 struct inode *inode = d_backing_inode(sbsec->sb->s_root);
James Morris089be432008-07-15 18:32:49 +1000612 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500613 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
614 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500615 char **mount_options = opts->mnt_opts;
616 int *flags = opts->mnt_opts_flags;
617 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500618
619 mutex_lock(&sbsec->lock);
620
621 if (!ss_initialized) {
622 if (!num_opts) {
623 /* Defer initialization until selinux_complete_init,
624 after the initial policy is loaded and the security
625 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500626 goto out;
627 }
628 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400629 printk(KERN_WARNING "SELinux: Unable to set superblock options "
630 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500631 goto out;
632 }
David Quigley649f6e72013-05-22 12:50:36 -0400633 if (kern_flags && !set_kern_flags) {
634 /* Specifying internal flags without providing a place to
635 * place the results is not allowed */
636 rc = -EINVAL;
637 goto out;
638 }
Eric Parisc9180a52007-11-30 13:00:35 -0500639
640 /*
Eric Parise0007522008-03-05 10:31:54 -0500641 * Binary mount data FS will come through this function twice. Once
642 * from an explicit call and once from the generic calls from the vfs.
643 * Since the generic VFS calls will not contain any security mount data
644 * we need to skip the double mount verification.
645 *
646 * This does open a hole in which we will not notice if the first
647 * mount using this sb set explict options and a second mount using
648 * this sb does not set any security options. (The first options
649 * will be used for both mounts)
650 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500651 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500652 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400653 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500654
655 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500656 * parse the mount options, check if they are valid sids.
657 * also check if someone is trying to mount the same sb more
658 * than once with different security options.
659 */
660 for (i = 0; i < num_opts; i++) {
661 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500662
Eric Paris12f348b2012-10-09 10:56:25 -0400663 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500664 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500665 rc = security_context_to_sid(mount_options[i],
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +0100666 strlen(mount_options[i]), &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500667 if (rc) {
668 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800669 "(%s) failed for (dev %s, type %s) errno=%d\n",
670 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500671 goto out;
672 }
673 switch (flags[i]) {
674 case FSCONTEXT_MNT:
675 fscontext_sid = sid;
676
677 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
678 fscontext_sid))
679 goto out_double_mount;
680
681 sbsec->flags |= FSCONTEXT_MNT;
682 break;
683 case CONTEXT_MNT:
684 context_sid = sid;
685
686 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
687 context_sid))
688 goto out_double_mount;
689
690 sbsec->flags |= CONTEXT_MNT;
691 break;
692 case ROOTCONTEXT_MNT:
693 rootcontext_sid = sid;
694
695 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
696 rootcontext_sid))
697 goto out_double_mount;
698
699 sbsec->flags |= ROOTCONTEXT_MNT;
700
701 break;
702 case DEFCONTEXT_MNT:
703 defcontext_sid = sid;
704
705 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
706 defcontext_sid))
707 goto out_double_mount;
708
709 sbsec->flags |= DEFCONTEXT_MNT;
710
711 break;
712 default:
713 rc = -EINVAL;
714 goto out;
715 }
716 }
717
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500718 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500719 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500720 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500721 goto out_double_mount;
722 rc = 0;
723 goto out;
724 }
725
James Morris089be432008-07-15 18:32:49 +1000726 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400727 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
728
Stephen Smalley8e014722015-06-04 16:22:17 -0400729 if (!strcmp(sb->s_type->name, "debugfs") ||
730 !strcmp(sb->s_type->name, "sysfs") ||
731 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400732 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500733
David Quigleyeb9ae682013-05-22 12:50:37 -0400734 if (!sbsec->behavior) {
735 /*
736 * Determine the labeling behavior to use for this
737 * filesystem type.
738 */
Paul Moore98f700f2013-09-18 13:52:20 -0400739 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400740 if (rc) {
741 printk(KERN_WARNING
742 "%s: security_fs_use(%s) returned %d\n",
743 __func__, sb->s_type->name, rc);
744 goto out;
745 }
Eric Parisc9180a52007-11-30 13:00:35 -0500746 }
Eric Parisc9180a52007-11-30 13:00:35 -0500747 /* sets the context of the superblock for the fs being mounted. */
748 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100749 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500750 if (rc)
751 goto out;
752
753 sbsec->sid = fscontext_sid;
754 }
755
756 /*
757 * Switch to using mount point labeling behavior.
758 * sets the label used on all file below the mountpoint, and will set
759 * the superblock context if not already set.
760 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400761 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
762 sbsec->behavior = SECURITY_FS_USE_NATIVE;
763 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
764 }
765
Eric Parisc9180a52007-11-30 13:00:35 -0500766 if (context_sid) {
767 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100768 rc = may_context_mount_sb_relabel(context_sid, sbsec,
769 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500770 if (rc)
771 goto out;
772 sbsec->sid = context_sid;
773 } else {
David Howells275bb412008-11-14 10:39:19 +1100774 rc = may_context_mount_inode_relabel(context_sid, sbsec,
775 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500776 if (rc)
777 goto out;
778 }
779 if (!rootcontext_sid)
780 rootcontext_sid = context_sid;
781
782 sbsec->mntpoint_sid = context_sid;
783 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
784 }
785
786 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100787 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
788 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500789 if (rc)
790 goto out;
791
792 root_isec->sid = rootcontext_sid;
793 root_isec->initialized = 1;
794 }
795
796 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400797 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
798 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500799 rc = -EINVAL;
800 printk(KERN_WARNING "SELinux: defcontext option is "
801 "invalid for this filesystem type\n");
802 goto out;
803 }
804
805 if (defcontext_sid != sbsec->def_sid) {
806 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100807 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500808 if (rc)
809 goto out;
810 }
811
812 sbsec->def_sid = defcontext_sid;
813 }
814
815 rc = sb_finish_set_opts(sb);
816out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700817 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500819out_double_mount:
820 rc = -EINVAL;
821 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800822 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500823 goto out;
824}
825
Jeff Layton094f7b62013-04-01 08:14:24 -0400826static int selinux_cmp_sb_context(const struct super_block *oldsb,
827 const struct super_block *newsb)
828{
829 struct superblock_security_struct *old = oldsb->s_security;
830 struct superblock_security_struct *new = newsb->s_security;
831 char oldflags = old->flags & SE_MNTMASK;
832 char newflags = new->flags & SE_MNTMASK;
833
834 if (oldflags != newflags)
835 goto mismatch;
836 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
837 goto mismatch;
838 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
839 goto mismatch;
840 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
841 goto mismatch;
842 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000843 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
844 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400845 if (oldroot->sid != newroot->sid)
846 goto mismatch;
847 }
848 return 0;
849mismatch:
850 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
851 "different security settings for (dev %s, "
852 "type %s)\n", newsb->s_id, newsb->s_type->name);
853 return -EBUSY;
854}
855
856static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500857 struct super_block *newsb)
858{
859 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
860 struct superblock_security_struct *newsbsec = newsb->s_security;
861
862 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
863 int set_context = (oldsbsec->flags & CONTEXT_MNT);
864 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
865
Eric Paris0f5e6422008-04-21 16:24:11 -0400866 /*
867 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400868 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400869 */
Al Viroe8c26252010-03-23 06:36:54 -0400870 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400871 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500872
Eric Parisc9180a52007-11-30 13:00:35 -0500873 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500874 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500875
Jeff Layton094f7b62013-04-01 08:14:24 -0400876 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500877 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400878 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400879
Eric Parisc9180a52007-11-30 13:00:35 -0500880 mutex_lock(&newsbsec->lock);
881
882 newsbsec->flags = oldsbsec->flags;
883
884 newsbsec->sid = oldsbsec->sid;
885 newsbsec->def_sid = oldsbsec->def_sid;
886 newsbsec->behavior = oldsbsec->behavior;
887
888 if (set_context) {
889 u32 sid = oldsbsec->mntpoint_sid;
890
891 if (!set_fscontext)
892 newsbsec->sid = sid;
893 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000894 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500895 struct inode_security_struct *newisec = newinode->i_security;
896 newisec->sid = sid;
897 }
898 newsbsec->mntpoint_sid = sid;
899 }
900 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000901 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500902 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000903 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500904 struct inode_security_struct *newisec = newinode->i_security;
905
906 newisec->sid = oldisec->sid;
907 }
908
909 sb_finish_set_opts(newsb);
910 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400911 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500912}
913
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200914static int selinux_parse_opts_str(char *options,
915 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500916{
Eric Parise0007522008-03-05 10:31:54 -0500917 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500918 char *context = NULL, *defcontext = NULL;
919 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500920 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500921
Eric Parise0007522008-03-05 10:31:54 -0500922 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500923
924 /* Standard string-based options. */
925 while ((p = strsep(&options, "|")) != NULL) {
926 int token;
927 substring_t args[MAX_OPT_ARGS];
928
929 if (!*p)
930 continue;
931
932 token = match_token(p, tokens, args);
933
934 switch (token) {
935 case Opt_context:
936 if (context || defcontext) {
937 rc = -EINVAL;
938 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
939 goto out_err;
940 }
941 context = match_strdup(&args[0]);
942 if (!context) {
943 rc = -ENOMEM;
944 goto out_err;
945 }
946 break;
947
948 case Opt_fscontext:
949 if (fscontext) {
950 rc = -EINVAL;
951 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
952 goto out_err;
953 }
954 fscontext = match_strdup(&args[0]);
955 if (!fscontext) {
956 rc = -ENOMEM;
957 goto out_err;
958 }
959 break;
960
961 case Opt_rootcontext:
962 if (rootcontext) {
963 rc = -EINVAL;
964 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
965 goto out_err;
966 }
967 rootcontext = match_strdup(&args[0]);
968 if (!rootcontext) {
969 rc = -ENOMEM;
970 goto out_err;
971 }
972 break;
973
974 case Opt_defcontext:
975 if (context || defcontext) {
976 rc = -EINVAL;
977 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
978 goto out_err;
979 }
980 defcontext = match_strdup(&args[0]);
981 if (!defcontext) {
982 rc = -ENOMEM;
983 goto out_err;
984 }
985 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500986 case Opt_labelsupport:
987 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500988 default:
989 rc = -EINVAL;
990 printk(KERN_WARNING "SELinux: unknown mount option\n");
991 goto out_err;
992
993 }
994 }
995
Eric Parise0007522008-03-05 10:31:54 -0500996 rc = -ENOMEM;
997 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
998 if (!opts->mnt_opts)
999 goto out_err;
1000
1001 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1002 if (!opts->mnt_opts_flags) {
1003 kfree(opts->mnt_opts);
1004 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001005 }
1006
Eric Parise0007522008-03-05 10:31:54 -05001007 if (fscontext) {
1008 opts->mnt_opts[num_mnt_opts] = fscontext;
1009 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1010 }
1011 if (context) {
1012 opts->mnt_opts[num_mnt_opts] = context;
1013 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1014 }
1015 if (rootcontext) {
1016 opts->mnt_opts[num_mnt_opts] = rootcontext;
1017 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1018 }
1019 if (defcontext) {
1020 opts->mnt_opts[num_mnt_opts] = defcontext;
1021 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1022 }
1023
1024 opts->num_mnt_opts = num_mnt_opts;
1025 return 0;
1026
Eric Parisc9180a52007-11-30 13:00:35 -05001027out_err:
1028 kfree(context);
1029 kfree(defcontext);
1030 kfree(fscontext);
1031 kfree(rootcontext);
1032 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033}
Eric Parise0007522008-03-05 10:31:54 -05001034/*
1035 * string mount options parsing and call set the sbsec
1036 */
1037static int superblock_doinit(struct super_block *sb, void *data)
1038{
1039 int rc = 0;
1040 char *options = data;
1041 struct security_mnt_opts opts;
1042
1043 security_init_mnt_opts(&opts);
1044
1045 if (!data)
1046 goto out;
1047
1048 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1049
1050 rc = selinux_parse_opts_str(options, &opts);
1051 if (rc)
1052 goto out_err;
1053
1054out:
David Quigley649f6e72013-05-22 12:50:36 -04001055 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001056
1057out_err:
1058 security_free_mnt_opts(&opts);
1059 return rc;
1060}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Adrian Bunk3583a712008-07-22 20:21:23 +03001062static void selinux_write_opts(struct seq_file *m,
1063 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001064{
1065 int i;
1066 char *prefix;
1067
1068 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001069 char *has_comma;
1070
1071 if (opts->mnt_opts[i])
1072 has_comma = strchr(opts->mnt_opts[i], ',');
1073 else
1074 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001075
1076 switch (opts->mnt_opts_flags[i]) {
1077 case CONTEXT_MNT:
1078 prefix = CONTEXT_STR;
1079 break;
1080 case FSCONTEXT_MNT:
1081 prefix = FSCONTEXT_STR;
1082 break;
1083 case ROOTCONTEXT_MNT:
1084 prefix = ROOTCONTEXT_STR;
1085 break;
1086 case DEFCONTEXT_MNT:
1087 prefix = DEFCONTEXT_STR;
1088 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001089 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001090 seq_putc(m, ',');
1091 seq_puts(m, LABELSUPP_STR);
1092 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001093 default:
1094 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001095 return;
Eric Paris2069f452008-07-04 09:47:13 +10001096 };
1097 /* we need a comma before each option */
1098 seq_putc(m, ',');
1099 seq_puts(m, prefix);
1100 if (has_comma)
1101 seq_putc(m, '\"');
1102 seq_puts(m, opts->mnt_opts[i]);
1103 if (has_comma)
1104 seq_putc(m, '\"');
1105 }
1106}
1107
1108static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1109{
1110 struct security_mnt_opts opts;
1111 int rc;
1112
1113 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001114 if (rc) {
1115 /* before policy load we may get EINVAL, don't show anything */
1116 if (rc == -EINVAL)
1117 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001118 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001119 }
Eric Paris2069f452008-07-04 09:47:13 +10001120
1121 selinux_write_opts(m, &opts);
1122
1123 security_free_mnt_opts(&opts);
1124
1125 return rc;
1126}
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128static inline u16 inode_mode_to_security_class(umode_t mode)
1129{
1130 switch (mode & S_IFMT) {
1131 case S_IFSOCK:
1132 return SECCLASS_SOCK_FILE;
1133 case S_IFLNK:
1134 return SECCLASS_LNK_FILE;
1135 case S_IFREG:
1136 return SECCLASS_FILE;
1137 case S_IFBLK:
1138 return SECCLASS_BLK_FILE;
1139 case S_IFDIR:
1140 return SECCLASS_DIR;
1141 case S_IFCHR:
1142 return SECCLASS_CHR_FILE;
1143 case S_IFIFO:
1144 return SECCLASS_FIFO_FILE;
1145
1146 }
1147
1148 return SECCLASS_FILE;
1149}
1150
James Morris13402582005-09-30 14:24:34 -04001151static inline int default_protocol_stream(int protocol)
1152{
1153 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1154}
1155
1156static inline int default_protocol_dgram(int protocol)
1157{
1158 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1159}
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1162{
1163 switch (family) {
1164 case PF_UNIX:
1165 switch (type) {
1166 case SOCK_STREAM:
1167 case SOCK_SEQPACKET:
1168 return SECCLASS_UNIX_STREAM_SOCKET;
1169 case SOCK_DGRAM:
1170 return SECCLASS_UNIX_DGRAM_SOCKET;
1171 }
1172 break;
1173 case PF_INET:
1174 case PF_INET6:
1175 switch (type) {
1176 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001177 if (default_protocol_stream(protocol))
1178 return SECCLASS_TCP_SOCKET;
1179 else
1180 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001182 if (default_protocol_dgram(protocol))
1183 return SECCLASS_UDP_SOCKET;
1184 else
1185 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001186 case SOCK_DCCP:
1187 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001188 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 return SECCLASS_RAWIP_SOCKET;
1190 }
1191 break;
1192 case PF_NETLINK:
1193 switch (protocol) {
1194 case NETLINK_ROUTE:
1195 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001196 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1198 case NETLINK_NFLOG:
1199 return SECCLASS_NETLINK_NFLOG_SOCKET;
1200 case NETLINK_XFRM:
1201 return SECCLASS_NETLINK_XFRM_SOCKET;
1202 case NETLINK_SELINUX:
1203 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001204 case NETLINK_ISCSI:
1205 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case NETLINK_AUDIT:
1207 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001208 case NETLINK_FIB_LOOKUP:
1209 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1210 case NETLINK_CONNECTOR:
1211 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1212 case NETLINK_NETFILTER:
1213 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 case NETLINK_DNRTMSG:
1215 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001216 case NETLINK_KOBJECT_UEVENT:
1217 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001218 case NETLINK_GENERIC:
1219 return SECCLASS_NETLINK_GENERIC_SOCKET;
1220 case NETLINK_SCSITRANSPORT:
1221 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1222 case NETLINK_RDMA:
1223 return SECCLASS_NETLINK_RDMA_SOCKET;
1224 case NETLINK_CRYPTO:
1225 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 default:
1227 return SECCLASS_NETLINK_SOCKET;
1228 }
1229 case PF_PACKET:
1230 return SECCLASS_PACKET_SOCKET;
1231 case PF_KEY:
1232 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001233 case PF_APPLETALK:
1234 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 }
1236
1237 return SECCLASS_SOCKET;
1238}
1239
Stephen Smalley134509d2015-06-04 16:22:17 -04001240static int selinux_genfs_get_sid(struct dentry *dentry,
1241 u16 tclass,
1242 u16 flags,
1243 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001245 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001246 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001247 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Eric Paris828dfe12008-04-17 13:17:49 -04001249 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 if (!buffer)
1251 return -ENOMEM;
1252
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001253 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1254 if (IS_ERR(path))
1255 rc = PTR_ERR(path);
1256 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001257 if (flags & SE_SBPROC) {
1258 /* each process gets a /proc/PID/ entry. Strip off the
1259 * PID part to get a valid selinux labeling.
1260 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1261 while (path[1] >= '0' && path[1] <= '9') {
1262 path[1] = '/';
1263 path++;
1264 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001265 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001266 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 free_page((unsigned long)buffer);
1269 return rc;
1270}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272/* The inode's security attributes must be initialized before first use. */
1273static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1274{
1275 struct superblock_security_struct *sbsec = NULL;
1276 struct inode_security_struct *isec = inode->i_security;
1277 u32 sid;
1278 struct dentry *dentry;
1279#define INITCONTEXTLEN 255
1280 char *context = NULL;
1281 unsigned len = 0;
1282 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
1284 if (isec->initialized)
1285 goto out;
1286
Eric Paris23970742006-09-25 23:32:01 -07001287 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001289 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001292 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 /* Defer initialization until selinux_complete_init,
1294 after the initial policy is loaded and the security
1295 server is ready to handle calls. */
1296 spin_lock(&sbsec->isec_lock);
1297 if (list_empty(&isec->list))
1298 list_add(&isec->list, &sbsec->isec_head);
1299 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001300 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 }
1302
1303 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001304 case SECURITY_FS_USE_NATIVE:
1305 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 case SECURITY_FS_USE_XATTR:
1307 if (!inode->i_op->getxattr) {
1308 isec->sid = sbsec->def_sid;
1309 break;
1310 }
1311
1312 /* Need a dentry, since the xattr API requires one.
1313 Life would be simpler if we could just pass the inode. */
1314 if (opt_dentry) {
1315 /* Called from d_instantiate or d_splice_alias. */
1316 dentry = dget(opt_dentry);
1317 } else {
1318 /* Called from selinux_complete_init, try to find a dentry. */
1319 dentry = d_find_alias(inode);
1320 }
1321 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001322 /*
1323 * this is can be hit on boot when a file is accessed
1324 * before the policy is loaded. When we load policy we
1325 * may find inodes that have no dentry on the
1326 * sbsec->isec_head list. No reason to complain as these
1327 * will get fixed up the next time we go through
1328 * inode_doinit with a dentry, before these inodes could
1329 * be used again by userspace.
1330 */
Eric Paris23970742006-09-25 23:32:01 -07001331 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 }
1333
1334 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001335 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (!context) {
1337 rc = -ENOMEM;
1338 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001339 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001341 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1343 context, len);
1344 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001345 kfree(context);
1346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 /* Need a larger buffer. Query for the right size. */
1348 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1349 NULL, 0);
1350 if (rc < 0) {
1351 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001352 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001355 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 if (!context) {
1357 rc = -ENOMEM;
1358 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001359 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001361 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 rc = inode->i_op->getxattr(dentry,
1363 XATTR_NAME_SELINUX,
1364 context, len);
1365 }
1366 dput(dentry);
1367 if (rc < 0) {
1368 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001369 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001370 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 -rc, inode->i_sb->s_id, inode->i_ino);
1372 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001373 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
1375 /* Map ENODATA to the default file SID */
1376 sid = sbsec->def_sid;
1377 rc = 0;
1378 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001379 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001380 sbsec->def_sid,
1381 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001383 char *dev = inode->i_sb->s_id;
1384 unsigned long ino = inode->i_ino;
1385
1386 if (rc == -EINVAL) {
1387 if (printk_ratelimit())
1388 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1389 "context=%s. This indicates you may need to relabel the inode or the "
1390 "filesystem in question.\n", ino, dev, context);
1391 } else {
1392 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1393 "returned %d for dev=%s ino=%ld\n",
1394 __func__, context, -rc, dev, ino);
1395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 kfree(context);
1397 /* Leave with the unlabeled SID */
1398 rc = 0;
1399 break;
1400 }
1401 }
1402 kfree(context);
1403 isec->sid = sid;
1404 break;
1405 case SECURITY_FS_USE_TASK:
1406 isec->sid = isec->task_sid;
1407 break;
1408 case SECURITY_FS_USE_TRANS:
1409 /* Default to the fs SID. */
1410 isec->sid = sbsec->sid;
1411
1412 /* Try to obtain a transition SID. */
1413 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001414 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1415 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001417 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 isec->sid = sid;
1419 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001420 case SECURITY_FS_USE_MNTPOINT:
1421 isec->sid = sbsec->mntpoint_sid;
1422 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001424 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 isec->sid = sbsec->sid;
1426
Stephen Smalley134509d2015-06-04 16:22:17 -04001427 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001428 /* We must have a dentry to determine the label on
1429 * procfs inodes */
1430 if (opt_dentry)
1431 /* Called from d_instantiate or
1432 * d_splice_alias. */
1433 dentry = dget(opt_dentry);
1434 else
1435 /* Called from selinux_complete_init, try to
1436 * find a dentry. */
1437 dentry = d_find_alias(inode);
1438 /*
1439 * This can be hit on boot when a file is accessed
1440 * before the policy is loaded. When we load policy we
1441 * may find inodes that have no dentry on the
1442 * sbsec->isec_head list. No reason to complain as
1443 * these will get fixed up the next time we go through
1444 * inode_doinit() with a dentry, before these inodes
1445 * could be used again by userspace.
1446 */
1447 if (!dentry)
1448 goto out_unlock;
1449 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001450 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1451 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001452 dput(dentry);
1453 if (rc)
1454 goto out_unlock;
1455 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457 break;
1458 }
1459
1460 isec->initialized = 1;
1461
Eric Paris23970742006-09-25 23:32:01 -07001462out_unlock:
1463 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464out:
1465 if (isec->sclass == SECCLASS_FILE)
1466 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 return rc;
1468}
1469
1470/* Convert a Linux signal to an access vector. */
1471static inline u32 signal_to_av(int sig)
1472{
1473 u32 perm = 0;
1474
1475 switch (sig) {
1476 case SIGCHLD:
1477 /* Commonly granted from child to parent. */
1478 perm = PROCESS__SIGCHLD;
1479 break;
1480 case SIGKILL:
1481 /* Cannot be caught or ignored */
1482 perm = PROCESS__SIGKILL;
1483 break;
1484 case SIGSTOP:
1485 /* Cannot be caught or ignored */
1486 perm = PROCESS__SIGSTOP;
1487 break;
1488 default:
1489 /* All other signals. */
1490 perm = PROCESS__SIGNAL;
1491 break;
1492 }
1493
1494 return perm;
1495}
1496
David Howells275bb412008-11-14 10:39:19 +11001497/*
David Howellsd84f4f92008-11-14 10:39:23 +11001498 * Check permission between a pair of credentials
1499 * fork check, ptrace check, etc.
1500 */
1501static int cred_has_perm(const struct cred *actor,
1502 const struct cred *target,
1503 u32 perms)
1504{
1505 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1506
1507 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1508}
1509
1510/*
David Howells88e67f32008-11-14 10:39:21 +11001511 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001512 * fork check, ptrace check, etc.
1513 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001514 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001515 */
1516static int task_has_perm(const struct task_struct *tsk1,
1517 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 u32 perms)
1519{
David Howells275bb412008-11-14 10:39:19 +11001520 const struct task_security_struct *__tsec1, *__tsec2;
1521 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
David Howells275bb412008-11-14 10:39:19 +11001523 rcu_read_lock();
1524 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1525 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1526 rcu_read_unlock();
1527 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528}
1529
David Howells3b11a1d2008-11-14 10:39:26 +11001530/*
1531 * Check permission between current and another task, e.g. signal checks,
1532 * fork check, ptrace check, etc.
1533 * current is the actor and tsk2 is the target
1534 * - this uses current's subjective creds
1535 */
1536static int current_has_perm(const struct task_struct *tsk,
1537 u32 perms)
1538{
1539 u32 sid, tsid;
1540
1541 sid = current_sid();
1542 tsid = task_sid(tsk);
1543 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1544}
1545
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001546#if CAP_LAST_CAP > 63
1547#error Fix SELinux to handle capabilities > 63.
1548#endif
1549
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001551static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001552 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553{
Thomas Liu2bf49692009-07-14 12:14:09 -04001554 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001555 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001556 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001557 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001558 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001559 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Eric Paris50c205f2012-04-04 15:01:43 -04001561 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 ad.u.cap = cap;
1563
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001564 switch (CAP_TO_INDEX(cap)) {
1565 case 0:
1566 sclass = SECCLASS_CAPABILITY;
1567 break;
1568 case 1:
1569 sclass = SECCLASS_CAPABILITY2;
1570 break;
1571 default:
1572 printk(KERN_ERR
1573 "SELinux: out of range capability %d\n", cap);
1574 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001575 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001576 }
Eric Paris06112162008-11-11 22:02:50 +11001577
David Howells275bb412008-11-14 10:39:19 +11001578 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001579 if (audit == SECURITY_CAP_AUDIT) {
Linus Torvaldsab354062013-10-04 14:05:38 -07001580 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001581 if (rc2)
1582 return rc2;
1583 }
Eric Paris06112162008-11-11 22:02:50 +11001584 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585}
1586
1587/* Check whether a task is allowed to use a system operation. */
1588static int task_has_system(struct task_struct *tsk,
1589 u32 perms)
1590{
David Howells275bb412008-11-14 10:39:19 +11001591 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
David Howells275bb412008-11-14 10:39:19 +11001593 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 SECCLASS_SYSTEM, perms, NULL);
1595}
1596
1597/* Check whether a task has a particular permission to an inode.
1598 The 'adp' parameter is optional and allows other audit
1599 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001600static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 struct inode *inode,
1602 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001603 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001606 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
David Howellse0e81732009-09-02 09:13:40 +01001608 validate_creds(cred);
1609
Eric Paris828dfe12008-04-17 13:17:49 -04001610 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001611 return 0;
1612
David Howells88e67f32008-11-14 10:39:21 +11001613 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 isec = inode->i_security;
1615
Linus Torvalds19e49832013-10-04 12:54:11 -07001616 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617}
1618
1619/* Same as inode_has_perm, but pass explicit audit data containing
1620 the dentry to help the auditing code to more easily generate the
1621 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001622static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 struct dentry *dentry,
1624 u32 av)
1625{
David Howellsc6f493d2015-03-17 22:26:22 +00001626 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001627 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001628
Eric Paris50c205f2012-04-04 15:01:43 -04001629 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001630 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001631 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001632}
1633
1634/* Same as inode_has_perm, but pass explicit audit data containing
1635 the path to help the auditing code to more easily generate the
1636 pathname if needed. */
1637static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001638 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001639 u32 av)
1640{
David Howellsc6f493d2015-03-17 22:26:22 +00001641 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001642 struct common_audit_data ad;
1643
Eric Paris50c205f2012-04-04 15:01:43 -04001644 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001645 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001646 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647}
1648
David Howells13f8e982013-06-13 23:37:55 +01001649/* Same as path_has_perm, but uses the inode from the file struct. */
1650static inline int file_path_has_perm(const struct cred *cred,
1651 struct file *file,
1652 u32 av)
1653{
1654 struct common_audit_data ad;
1655
1656 ad.type = LSM_AUDIT_DATA_PATH;
1657 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001658 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001659}
1660
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661/* Check whether a task can use an open file descriptor to
1662 access an inode in a given way. Check access to the
1663 descriptor itself, and then use dentry_has_perm to
1664 check a particular permission to the file.
1665 Access to the descriptor is implicitly granted if it
1666 has the same SID as the process. If av is zero, then
1667 access to the file is not checked, e.g. for cases
1668 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001669static int file_has_perm(const struct cred *cred,
1670 struct file *file,
1671 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001674 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001675 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001676 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 int rc;
1678
Eric Paris50c205f2012-04-04 15:01:43 -04001679 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001680 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
David Howells275bb412008-11-14 10:39:19 +11001682 if (sid != fsec->sid) {
1683 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 SECCLASS_FD,
1685 FD__USE,
1686 &ad);
1687 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001688 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 }
1690
1691 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001692 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001694 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
David Howells88e67f32008-11-14 10:39:21 +11001696out:
1697 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698}
1699
1700/* Check whether a task can create a file. */
1701static int may_create(struct inode *dir,
1702 struct dentry *dentry,
1703 u16 tclass)
1704{
Paul Moore5fb49872010-04-22 14:46:19 -04001705 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 struct inode_security_struct *dsec;
1707 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001708 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001709 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 int rc;
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 dsec = dir->i_security;
1713 sbsec = dir->i_sb->s_security;
1714
David Howells275bb412008-11-14 10:39:19 +11001715 sid = tsec->sid;
1716 newsid = tsec->create_sid;
1717
Eric Paris50c205f2012-04-04 15:01:43 -04001718 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001719 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
David Howells275bb412008-11-14 10:39:19 +11001721 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 DIR__ADD_NAME | DIR__SEARCH,
1723 &ad);
1724 if (rc)
1725 return rc;
1726
Eric Paris12f348b2012-10-09 10:56:25 -04001727 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001728 rc = security_transition_sid(sid, dsec->sid, tclass,
1729 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 if (rc)
1731 return rc;
1732 }
1733
David Howells275bb412008-11-14 10:39:19 +11001734 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if (rc)
1736 return rc;
1737
1738 return avc_has_perm(newsid, sbsec->sid,
1739 SECCLASS_FILESYSTEM,
1740 FILESYSTEM__ASSOCIATE, &ad);
1741}
1742
Michael LeMay4eb582c2006-06-26 00:24:57 -07001743/* Check whether a task can create a key. */
1744static int may_create_key(u32 ksid,
1745 struct task_struct *ctx)
1746{
David Howells275bb412008-11-14 10:39:19 +11001747 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001748
David Howells275bb412008-11-14 10:39:19 +11001749 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001750}
1751
Eric Paris828dfe12008-04-17 13:17:49 -04001752#define MAY_LINK 0
1753#define MAY_UNLINK 1
1754#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
1756/* Check whether a task can link, unlink, or rmdir a file/directory. */
1757static int may_link(struct inode *dir,
1758 struct dentry *dentry,
1759 int kind)
1760
1761{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001763 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001764 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 u32 av;
1766 int rc;
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001769 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Eric Paris50c205f2012-04-04 15:01:43 -04001771 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001772 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 av = DIR__SEARCH;
1775 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001776 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 if (rc)
1778 return rc;
1779
1780 switch (kind) {
1781 case MAY_LINK:
1782 av = FILE__LINK;
1783 break;
1784 case MAY_UNLINK:
1785 av = FILE__UNLINK;
1786 break;
1787 case MAY_RMDIR:
1788 av = DIR__RMDIR;
1789 break;
1790 default:
Eric Paris744ba352008-04-17 11:52:44 -04001791 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1792 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 return 0;
1794 }
1795
David Howells275bb412008-11-14 10:39:19 +11001796 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return rc;
1798}
1799
1800static inline int may_rename(struct inode *old_dir,
1801 struct dentry *old_dentry,
1802 struct inode *new_dir,
1803 struct dentry *new_dentry)
1804{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001806 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001807 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 u32 av;
1809 int old_is_dir, new_is_dir;
1810 int rc;
1811
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001813 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001814 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 new_dsec = new_dir->i_security;
1816
Eric Paris50c205f2012-04-04 15:01:43 -04001817 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
Eric Parisa2694342011-04-25 13:10:27 -04001819 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001820 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1822 if (rc)
1823 return rc;
David Howells275bb412008-11-14 10:39:19 +11001824 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 old_isec->sclass, FILE__RENAME, &ad);
1826 if (rc)
1827 return rc;
1828 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001829 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 old_isec->sclass, DIR__REPARENT, &ad);
1831 if (rc)
1832 return rc;
1833 }
1834
Eric Parisa2694342011-04-25 13:10:27 -04001835 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001837 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001839 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 if (rc)
1841 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001842 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001843 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001844 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001845 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 new_isec->sclass,
1847 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1848 if (rc)
1849 return rc;
1850 }
1851
1852 return 0;
1853}
1854
1855/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001856static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 struct super_block *sb,
1858 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001859 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001862 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001865 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866}
1867
1868/* Convert a Linux mode and permission mask to an access vector. */
1869static inline u32 file_mask_to_av(int mode, int mask)
1870{
1871 u32 av = 0;
1872
Al Virodba19c62011-07-25 20:49:29 -04001873 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if (mask & MAY_EXEC)
1875 av |= FILE__EXECUTE;
1876 if (mask & MAY_READ)
1877 av |= FILE__READ;
1878
1879 if (mask & MAY_APPEND)
1880 av |= FILE__APPEND;
1881 else if (mask & MAY_WRITE)
1882 av |= FILE__WRITE;
1883
1884 } else {
1885 if (mask & MAY_EXEC)
1886 av |= DIR__SEARCH;
1887 if (mask & MAY_WRITE)
1888 av |= DIR__WRITE;
1889 if (mask & MAY_READ)
1890 av |= DIR__READ;
1891 }
1892
1893 return av;
1894}
1895
1896/* Convert a Linux file to an access vector. */
1897static inline u32 file_to_av(struct file *file)
1898{
1899 u32 av = 0;
1900
1901 if (file->f_mode & FMODE_READ)
1902 av |= FILE__READ;
1903 if (file->f_mode & FMODE_WRITE) {
1904 if (file->f_flags & O_APPEND)
1905 av |= FILE__APPEND;
1906 else
1907 av |= FILE__WRITE;
1908 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001909 if (!av) {
1910 /*
1911 * Special file opened with flags 3 for ioctl-only use.
1912 */
1913 av = FILE__IOCTL;
1914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
1916 return av;
1917}
1918
Eric Paris8b6a5a32008-10-29 17:06:46 -04001919/*
1920 * Convert a file to an access vector and include the correct open
1921 * open permission.
1922 */
1923static inline u32 open_file_to_av(struct file *file)
1924{
1925 u32 av = file_to_av(file);
1926
Eric Paris49b7b8d2010-07-23 11:44:09 -04001927 if (selinux_policycap_openperm)
1928 av |= FILE__OPEN;
1929
Eric Paris8b6a5a32008-10-29 17:06:46 -04001930 return av;
1931}
1932
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933/* Hook functions begin here. */
1934
Stephen Smalley79af7302015-01-21 10:54:10 -05001935static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1936{
1937 u32 mysid = current_sid();
1938 u32 mgrsid = task_sid(mgr);
1939
1940 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1941 BINDER__SET_CONTEXT_MGR, NULL);
1942}
1943
1944static int selinux_binder_transaction(struct task_struct *from,
1945 struct task_struct *to)
1946{
1947 u32 mysid = current_sid();
1948 u32 fromsid = task_sid(from);
1949 u32 tosid = task_sid(to);
1950 int rc;
1951
1952 if (mysid != fromsid) {
1953 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1954 BINDER__IMPERSONATE, NULL);
1955 if (rc)
1956 return rc;
1957 }
1958
1959 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1960 NULL);
1961}
1962
1963static int selinux_binder_transfer_binder(struct task_struct *from,
1964 struct task_struct *to)
1965{
1966 u32 fromsid = task_sid(from);
1967 u32 tosid = task_sid(to);
1968
1969 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
1970 NULL);
1971}
1972
1973static int selinux_binder_transfer_file(struct task_struct *from,
1974 struct task_struct *to,
1975 struct file *file)
1976{
1977 u32 sid = task_sid(to);
1978 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001979 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05001980 struct inode_security_struct *isec = inode->i_security;
1981 struct common_audit_data ad;
1982 int rc;
1983
1984 ad.type = LSM_AUDIT_DATA_PATH;
1985 ad.u.path = file->f_path;
1986
1987 if (sid != fsec->sid) {
1988 rc = avc_has_perm(sid, fsec->sid,
1989 SECCLASS_FD,
1990 FD__USE,
1991 &ad);
1992 if (rc)
1993 return rc;
1994 }
1995
1996 if (unlikely(IS_PRIVATE(inode)))
1997 return 0;
1998
1999 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2000 &ad);
2001}
2002
Ingo Molnar9e488582009-05-07 19:26:19 +10002003static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002004 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005{
Eric Paris69f594a2012-01-03 12:25:15 -05002006 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002007 u32 sid = current_sid();
2008 u32 csid = task_sid(child);
2009 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002010 }
2011
David Howells3b11a1d2008-11-14 10:39:26 +11002012 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002013}
2014
2015static int selinux_ptrace_traceme(struct task_struct *parent)
2016{
David Howells5cd9c582008-08-14 11:37:28 +01002017 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018}
2019
2020static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002021 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002023 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024}
2025
David Howellsd84f4f92008-11-14 10:39:23 +11002026static int selinux_capset(struct cred *new, const struct cred *old,
2027 const kernel_cap_t *effective,
2028 const kernel_cap_t *inheritable,
2029 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030{
David Howellsd84f4f92008-11-14 10:39:23 +11002031 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032}
2033
James Morris5626d3e2009-01-30 10:05:06 +11002034/*
2035 * (This comment used to live with the selinux_task_setuid hook,
2036 * which was removed).
2037 *
2038 * Since setuid only affects the current process, and since the SELinux
2039 * controls are not based on the Linux identity attributes, SELinux does not
2040 * need to control this operation. However, SELinux does control the use of
2041 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2042 */
2043
Eric Paris6a9de492012-01-03 12:25:14 -05002044static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2045 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
Eric Paris6a9de492012-01-03 12:25:14 -05002047 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048}
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2051{
David Howells88e67f32008-11-14 10:39:21 +11002052 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 int rc = 0;
2054
2055 if (!sb)
2056 return 0;
2057
2058 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002059 case Q_SYNC:
2060 case Q_QUOTAON:
2061 case Q_QUOTAOFF:
2062 case Q_SETINFO:
2063 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002064 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002065 break;
2066 case Q_GETFMT:
2067 case Q_GETINFO:
2068 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002069 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002070 break;
2071 default:
2072 rc = 0; /* let the kernel handle invalid cmds */
2073 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 }
2075 return rc;
2076}
2077
2078static int selinux_quota_on(struct dentry *dentry)
2079{
David Howells88e67f32008-11-14 10:39:21 +11002080 const struct cred *cred = current_cred();
2081
Eric Paris2875fa02011-04-28 16:04:24 -04002082 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083}
2084
Eric Paris12b30522010-11-15 18:36:29 -05002085static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086{
2087 int rc;
2088
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002090 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2091 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002092 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2093 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002094 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2095 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2096 /* Set level of messages printed to console */
2097 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002098 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2099 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002100 case SYSLOG_ACTION_CLOSE: /* Close log */
2101 case SYSLOG_ACTION_OPEN: /* Open log */
2102 case SYSLOG_ACTION_READ: /* Read from log */
2103 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2104 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002105 default:
2106 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2107 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 }
2109 return rc;
2110}
2111
2112/*
2113 * Check that a process has enough memory to allocate a new virtual
2114 * mapping. 0 means there is enough memory for the allocation to
2115 * succeed and -ENOMEM implies there is not.
2116 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 * Do not audit the selinux permission check, as this is applied to all
2118 * processes that allocate mappings.
2119 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002120static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
2122 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002124 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2125 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 if (rc == 0)
2127 cap_sys_admin = 1;
2128
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002129 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130}
2131
2132/* binprm security operations */
2133
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002134static int check_nnp_nosuid(const struct linux_binprm *bprm,
2135 const struct task_security_struct *old_tsec,
2136 const struct task_security_struct *new_tsec)
2137{
2138 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2139 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2140 int rc;
2141
2142 if (!nnp && !nosuid)
2143 return 0; /* neither NNP nor nosuid */
2144
2145 if (new_tsec->sid == old_tsec->sid)
2146 return 0; /* No change in credentials */
2147
2148 /*
2149 * The only transitions we permit under NNP or nosuid
2150 * are transitions to bounded SIDs, i.e. SIDs that are
2151 * guaranteed to only be allowed a subset of the permissions
2152 * of the current SID.
2153 */
2154 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2155 if (rc) {
2156 /*
2157 * On failure, preserve the errno values for NNP vs nosuid.
2158 * NNP: Operation not permitted for caller.
2159 * nosuid: Permission denied to file.
2160 */
2161 if (nnp)
2162 return -EPERM;
2163 else
2164 return -EACCES;
2165 }
2166 return 0;
2167}
2168
David Howellsa6f76f22008-11-14 10:39:24 +11002169static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170{
David Howellsa6f76f22008-11-14 10:39:24 +11002171 const struct task_security_struct *old_tsec;
2172 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002174 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002175 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 int rc;
2177
David Howellsa6f76f22008-11-14 10:39:24 +11002178 /* SELinux context only depends on initial program or script and not
2179 * the script interpreter */
2180 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 return 0;
2182
David Howellsa6f76f22008-11-14 10:39:24 +11002183 old_tsec = current_security();
2184 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 isec = inode->i_security;
2186
2187 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002188 new_tsec->sid = old_tsec->sid;
2189 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Michael LeMay28eba5b2006-06-27 02:53:42 -07002191 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002192 new_tsec->create_sid = 0;
2193 new_tsec->keycreate_sid = 0;
2194 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
David Howellsa6f76f22008-11-14 10:39:24 +11002196 if (old_tsec->exec_sid) {
2197 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002199 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002200
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002201 /* Fail on NNP or nosuid if not an allowed transition. */
2202 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2203 if (rc)
2204 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 } else {
2206 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002207 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002208 SECCLASS_PROCESS, NULL,
2209 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 if (rc)
2211 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002212
2213 /*
2214 * Fallback to old SID on NNP or nosuid if not an allowed
2215 * transition.
2216 */
2217 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2218 if (rc)
2219 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 }
2221
Eric Paris50c205f2012-04-04 15:01:43 -04002222 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002223 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
David Howellsa6f76f22008-11-14 10:39:24 +11002225 if (new_tsec->sid == old_tsec->sid) {
2226 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2228 if (rc)
2229 return rc;
2230 } else {
2231 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002232 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2234 if (rc)
2235 return rc;
2236
David Howellsa6f76f22008-11-14 10:39:24 +11002237 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2239 if (rc)
2240 return rc;
2241
David Howellsa6f76f22008-11-14 10:39:24 +11002242 /* Check for shared state */
2243 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2244 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2245 SECCLASS_PROCESS, PROCESS__SHARE,
2246 NULL);
2247 if (rc)
2248 return -EPERM;
2249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
David Howellsa6f76f22008-11-14 10:39:24 +11002251 /* Make sure that anyone attempting to ptrace over a task that
2252 * changes its SID has the appropriate permit */
2253 if (bprm->unsafe &
2254 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2255 struct task_struct *tracer;
2256 struct task_security_struct *sec;
2257 u32 ptsid = 0;
2258
2259 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002260 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002261 if (likely(tracer != NULL)) {
2262 sec = __task_cred(tracer)->security;
2263 ptsid = sec->sid;
2264 }
2265 rcu_read_unlock();
2266
2267 if (ptsid != 0) {
2268 rc = avc_has_perm(ptsid, new_tsec->sid,
2269 SECCLASS_PROCESS,
2270 PROCESS__PTRACE, NULL);
2271 if (rc)
2272 return -EPERM;
2273 }
2274 }
2275
2276 /* Clear any possibly unsafe personality bits on exec: */
2277 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 }
2279
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return 0;
2281}
2282
Eric Paris828dfe12008-04-17 13:17:49 -04002283static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284{
Paul Moore5fb49872010-04-22 14:46:19 -04002285 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002286 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 int atsecure = 0;
2288
David Howells275bb412008-11-14 10:39:19 +11002289 sid = tsec->sid;
2290 osid = tsec->osid;
2291
2292 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 /* Enable secure mode for SIDs transitions unless
2294 the noatsecure permission is granted between
2295 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002296 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002297 SECCLASS_PROCESS,
2298 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 }
2300
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002301 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302}
2303
Al Viroc3c073f2012-08-21 22:32:06 -04002304static int match_file(const void *p, struct file *file, unsigned fd)
2305{
2306 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2307}
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002310static inline void flush_unauthorized_files(const struct cred *cred,
2311 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002314 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002315 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002316 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002318 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002320 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002321 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002322 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002323
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002325 Use file_path_has_perm on the tty path directly
2326 rather than using file_has_perm, as this particular
2327 open file may belong to another process and we are
2328 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002329 file_priv = list_first_entry(&tty->tty_files,
2330 struct tty_file_private, list);
2331 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002332 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002333 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002335 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002336 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002338 /* Reset controlling tty. */
2339 if (drop_tty)
2340 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
2342 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002343 n = iterate_fd(files, 0, match_file, cred);
2344 if (!n) /* none found? */
2345 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346
Al Viroc3c073f2012-08-21 22:32:06 -04002347 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002348 if (IS_ERR(devnull))
2349 devnull = NULL;
2350 /* replace all the matching ones with this */
2351 do {
2352 replace_fd(n - 1, devnull, 0);
2353 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2354 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002355 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356}
2357
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358/*
David Howellsa6f76f22008-11-14 10:39:24 +11002359 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 */
David Howellsa6f76f22008-11-14 10:39:24 +11002361static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362{
David Howellsa6f76f22008-11-14 10:39:24 +11002363 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 int rc, i;
2366
David Howellsa6f76f22008-11-14 10:39:24 +11002367 new_tsec = bprm->cred->security;
2368 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 return;
2370
2371 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002372 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
David Howellsa6f76f22008-11-14 10:39:24 +11002374 /* Always clear parent death signal on SID transitions. */
2375 current->pdeath_signal = 0;
2376
2377 /* Check whether the new SID can inherit resource limits from the old
2378 * SID. If not, reset all soft limits to the lower of the current
2379 * task's hard limit and the init task's soft limit.
2380 *
2381 * Note that the setting of hard limits (even to lower them) can be
2382 * controlled by the setrlimit check. The inclusion of the init task's
2383 * soft limit into the computation is to avoid resetting soft limits
2384 * higher than the default soft limit for cases where the default is
2385 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2386 */
2387 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2388 PROCESS__RLIMITINH, NULL);
2389 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002390 /* protect against do_prlimit() */
2391 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002392 for (i = 0; i < RLIM_NLIMITS; i++) {
2393 rlim = current->signal->rlim + i;
2394 initrlim = init_task.signal->rlim + i;
2395 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2396 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002397 task_unlock(current);
2398 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002399 }
2400}
2401
2402/*
2403 * Clean up the process immediately after the installation of new credentials
2404 * due to exec
2405 */
2406static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2407{
2408 const struct task_security_struct *tsec = current_security();
2409 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002410 u32 osid, sid;
2411 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002412
David Howellsa6f76f22008-11-14 10:39:24 +11002413 osid = tsec->osid;
2414 sid = tsec->sid;
2415
2416 if (sid == osid)
2417 return;
2418
2419 /* Check whether the new SID can inherit signal state from the old SID.
2420 * If not, clear itimers to avoid subsequent signal generation and
2421 * flush and unblock signals.
2422 *
2423 * This must occur _after_ the task SID has been updated so that any
2424 * kill done after the flush will be checked against the new SID.
2425 */
2426 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 if (rc) {
2428 memset(&itimer, 0, sizeof itimer);
2429 for (i = 0; i < 3; i++)
2430 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002432 if (!fatal_signal_pending(current)) {
2433 flush_sigqueue(&current->pending);
2434 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002435 flush_signal_handlers(current, 1);
2436 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002437 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 spin_unlock_irq(&current->sighand->siglock);
2440 }
2441
David Howellsa6f76f22008-11-14 10:39:24 +11002442 /* Wake up the parent if it is waiting so that it can recheck
2443 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002444 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002445 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002446 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447}
2448
2449/* superblock security operations */
2450
2451static int selinux_sb_alloc_security(struct super_block *sb)
2452{
2453 return superblock_alloc_security(sb);
2454}
2455
2456static void selinux_sb_free_security(struct super_block *sb)
2457{
2458 superblock_free_security(sb);
2459}
2460
2461static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2462{
2463 if (plen > olen)
2464 return 0;
2465
2466 return !memcmp(prefix, option, plen);
2467}
2468
2469static inline int selinux_option(char *option, int len)
2470{
Eric Paris832cbd92008-04-01 13:24:09 -04002471 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2472 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2473 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002474 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2475 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476}
2477
2478static inline void take_option(char **to, char *from, int *first, int len)
2479{
2480 if (!*first) {
2481 **to = ',';
2482 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002483 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 *first = 0;
2485 memcpy(*to, from, len);
2486 *to += len;
2487}
2488
Eric Paris828dfe12008-04-17 13:17:49 -04002489static inline void take_selinux_option(char **to, char *from, int *first,
2490 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002491{
2492 int current_size = 0;
2493
2494 if (!*first) {
2495 **to = '|';
2496 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002497 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002498 *first = 0;
2499
2500 while (current_size < len) {
2501 if (*from != '"') {
2502 **to = *from;
2503 *to += 1;
2504 }
2505 from += 1;
2506 current_size += 1;
2507 }
2508}
2509
Eric Parise0007522008-03-05 10:31:54 -05002510static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511{
2512 int fnosec, fsec, rc = 0;
2513 char *in_save, *in_curr, *in_end;
2514 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002515 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
2517 in_curr = orig;
2518 sec_curr = copy;
2519
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2521 if (!nosec) {
2522 rc = -ENOMEM;
2523 goto out;
2524 }
2525
2526 nosec_save = nosec;
2527 fnosec = fsec = 1;
2528 in_save = in_end = orig;
2529
2530 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002531 if (*in_end == '"')
2532 open_quote = !open_quote;
2533 if ((*in_end == ',' && open_quote == 0) ||
2534 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 int len = in_end - in_curr;
2536
2537 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002538 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 else
2540 take_option(&nosec, in_curr, &fnosec, len);
2541
2542 in_curr = in_end + 1;
2543 }
2544 } while (*in_end++);
2545
Eric Paris6931dfc2005-06-30 02:58:51 -07002546 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002547 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548out:
2549 return rc;
2550}
2551
Eric Paris026eb162011-03-03 16:09:14 -05002552static int selinux_sb_remount(struct super_block *sb, void *data)
2553{
2554 int rc, i, *flags;
2555 struct security_mnt_opts opts;
2556 char *secdata, **mount_options;
2557 struct superblock_security_struct *sbsec = sb->s_security;
2558
2559 if (!(sbsec->flags & SE_SBINITIALIZED))
2560 return 0;
2561
2562 if (!data)
2563 return 0;
2564
2565 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2566 return 0;
2567
2568 security_init_mnt_opts(&opts);
2569 secdata = alloc_secdata();
2570 if (!secdata)
2571 return -ENOMEM;
2572 rc = selinux_sb_copy_data(data, secdata);
2573 if (rc)
2574 goto out_free_secdata;
2575
2576 rc = selinux_parse_opts_str(secdata, &opts);
2577 if (rc)
2578 goto out_free_secdata;
2579
2580 mount_options = opts.mnt_opts;
2581 flags = opts.mnt_opts_flags;
2582
2583 for (i = 0; i < opts.num_mnt_opts; i++) {
2584 u32 sid;
2585 size_t len;
2586
Eric Paris12f348b2012-10-09 10:56:25 -04002587 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002588 continue;
2589 len = strlen(mount_options[i]);
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002590 rc = security_context_to_sid(mount_options[i], len, &sid,
2591 GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002592 if (rc) {
2593 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002594 "(%s) failed for (dev %s, type %s) errno=%d\n",
2595 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002596 goto out_free_opts;
2597 }
2598 rc = -EINVAL;
2599 switch (flags[i]) {
2600 case FSCONTEXT_MNT:
2601 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2602 goto out_bad_option;
2603 break;
2604 case CONTEXT_MNT:
2605 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2606 goto out_bad_option;
2607 break;
2608 case ROOTCONTEXT_MNT: {
2609 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002610 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002611
2612 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2613 goto out_bad_option;
2614 break;
2615 }
2616 case DEFCONTEXT_MNT:
2617 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2618 goto out_bad_option;
2619 break;
2620 default:
2621 goto out_free_opts;
2622 }
2623 }
2624
2625 rc = 0;
2626out_free_opts:
2627 security_free_mnt_opts(&opts);
2628out_free_secdata:
2629 free_secdata(secdata);
2630 return rc;
2631out_bad_option:
2632 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002633 "during remount (dev %s, type=%s)\n", sb->s_id,
2634 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002635 goto out_free_opts;
2636}
2637
James Morris12204e22008-12-19 10:44:42 +11002638static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
David Howells88e67f32008-11-14 10:39:21 +11002640 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002641 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 int rc;
2643
2644 rc = superblock_doinit(sb, data);
2645 if (rc)
2646 return rc;
2647
James Morris74192242008-12-19 11:41:10 +11002648 /* Allow all mounts performed by the kernel */
2649 if (flags & MS_KERNMOUNT)
2650 return 0;
2651
Eric Paris50c205f2012-04-04 15:01:43 -04002652 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002653 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002654 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655}
2656
David Howells726c3342006-06-23 02:02:58 -07002657static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658{
David Howells88e67f32008-11-14 10:39:21 +11002659 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002660 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Eric Paris50c205f2012-04-04 15:01:43 -04002662 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002663 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002664 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665}
2666
Al Viro808d4e32012-10-11 11:42:01 -04002667static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002668 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002669 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002670 unsigned long flags,
2671 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672{
David Howells88e67f32008-11-14 10:39:21 +11002673 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
2675 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002676 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002677 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 else
Eric Paris2875fa02011-04-28 16:04:24 -04002679 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680}
2681
2682static int selinux_umount(struct vfsmount *mnt, int flags)
2683{
David Howells88e67f32008-11-14 10:39:21 +11002684 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685
David Howells88e67f32008-11-14 10:39:21 +11002686 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002687 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688}
2689
2690/* inode security operations */
2691
2692static int selinux_inode_alloc_security(struct inode *inode)
2693{
2694 return inode_alloc_security(inode);
2695}
2696
2697static void selinux_inode_free_security(struct inode *inode)
2698{
2699 inode_free_security(inode);
2700}
2701
David Quigleyd47be3d2013-05-22 12:50:34 -04002702static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2703 struct qstr *name, void **ctx,
2704 u32 *ctxlen)
2705{
2706 const struct cred *cred = current_cred();
2707 struct task_security_struct *tsec;
2708 struct inode_security_struct *dsec;
2709 struct superblock_security_struct *sbsec;
David Howellsc6f493d2015-03-17 22:26:22 +00002710 struct inode *dir = d_backing_inode(dentry->d_parent);
David Quigleyd47be3d2013-05-22 12:50:34 -04002711 u32 newsid;
2712 int rc;
2713
2714 tsec = cred->security;
2715 dsec = dir->i_security;
2716 sbsec = dir->i_sb->s_security;
2717
2718 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2719 newsid = tsec->create_sid;
2720 } else {
2721 rc = security_transition_sid(tsec->sid, dsec->sid,
2722 inode_mode_to_security_class(mode),
2723 name,
2724 &newsid);
2725 if (rc) {
2726 printk(KERN_WARNING
2727 "%s: security_transition_sid failed, rc=%d\n",
2728 __func__, -rc);
2729 return rc;
2730 }
2731 }
2732
2733 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2734}
2735
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002736static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002737 const struct qstr *qstr,
2738 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002739 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002740{
Paul Moore5fb49872010-04-22 14:46:19 -04002741 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002742 struct inode_security_struct *dsec;
2743 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002744 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002745 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002746 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002747
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002748 dsec = dir->i_security;
2749 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002750
David Howells275bb412008-11-14 10:39:19 +11002751 sid = tsec->sid;
2752 newsid = tsec->create_sid;
2753
Eric Paris415103f2010-12-02 16:13:40 -05002754 if ((sbsec->flags & SE_SBINITIALIZED) &&
2755 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2756 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002757 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002758 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002759 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002760 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002761 if (rc) {
2762 printk(KERN_WARNING "%s: "
2763 "security_transition_sid failed, rc=%d (dev=%s "
2764 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002765 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002766 -rc, inode->i_sb->s_id, inode->i_ino);
2767 return rc;
2768 }
2769 }
2770
Eric Paris296fddf2006-09-25 23:32:00 -07002771 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002772 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002773 struct inode_security_struct *isec = inode->i_security;
2774 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2775 isec->sid = newsid;
2776 isec->initialized = 1;
2777 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002778
Eric Paris12f348b2012-10-09 10:56:25 -04002779 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002780 return -EOPNOTSUPP;
2781
Tetsuo Handa95489062013-07-25 05:44:02 +09002782 if (name)
2783 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002784
2785 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002786 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002787 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002788 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002789 *value = context;
2790 *len = clen;
2791 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002792
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002793 return 0;
2794}
2795
Al Viro4acdaf22011-07-26 01:42:34 -04002796static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797{
2798 return may_create(dir, dentry, SECCLASS_FILE);
2799}
2800
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2802{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 return may_link(dir, old_dentry, MAY_LINK);
2804}
2805
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2807{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 return may_link(dir, dentry, MAY_UNLINK);
2809}
2810
2811static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2812{
2813 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2814}
2815
Al Viro18bb1db2011-07-26 01:41:39 -04002816static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
2818 return may_create(dir, dentry, SECCLASS_DIR);
2819}
2820
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2822{
2823 return may_link(dir, dentry, MAY_RMDIR);
2824}
2825
Al Viro1a67aaf2011-07-26 01:52:52 -04002826static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2829}
2830
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002832 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833{
2834 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2835}
2836
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837static int selinux_inode_readlink(struct dentry *dentry)
2838{
David Howells88e67f32008-11-14 10:39:21 +11002839 const struct cred *cred = current_cred();
2840
Eric Paris2875fa02011-04-28 16:04:24 -04002841 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842}
2843
2844static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2845{
David Howells88e67f32008-11-14 10:39:21 +11002846 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
Eric Paris2875fa02011-04-28 16:04:24 -04002848 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849}
2850
Eric Parisd4cf970d2012-04-04 15:01:42 -04002851static noinline int audit_inode_permission(struct inode *inode,
2852 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002853 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002854 unsigned flags)
2855{
2856 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002857 struct inode_security_struct *isec = inode->i_security;
2858 int rc;
2859
Eric Paris50c205f2012-04-04 15:01:43 -04002860 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002861 ad.u.inode = inode;
2862
2863 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002864 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002865 if (rc)
2866 return rc;
2867 return 0;
2868}
2869
Al Viroe74f71e2011-06-20 19:38:15 -04002870static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871{
David Howells88e67f32008-11-14 10:39:21 +11002872 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002873 u32 perms;
2874 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002875 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002876 struct inode_security_struct *isec;
2877 u32 sid;
2878 struct av_decision avd;
2879 int rc, rc2;
2880 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Eric Parisb782e0a2010-07-23 11:44:03 -04002882 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002883 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2884
Eric Parisb782e0a2010-07-23 11:44:03 -04002885 /* No permission to check. Existence test. */
2886 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
Eric Paris2e334052012-04-04 15:01:42 -04002889 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002890
Eric Paris2e334052012-04-04 15:01:42 -04002891 if (unlikely(IS_PRIVATE(inode)))
2892 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002893
2894 perms = file_mask_to_av(inode->i_mode, mask);
2895
Eric Paris2e334052012-04-04 15:01:42 -04002896 sid = cred_sid(cred);
2897 isec = inode->i_security;
2898
2899 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2900 audited = avc_audit_required(perms, &avd, rc,
2901 from_access ? FILE__AUDIT_ACCESS : 0,
2902 &denied);
2903 if (likely(!audited))
2904 return rc;
2905
Stephen Smalley626b9742014-04-29 11:29:04 -07002906 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002907 if (rc2)
2908 return rc2;
2909 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910}
2911
2912static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2913{
David Howells88e67f32008-11-14 10:39:21 +11002914 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002915 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002916 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002918 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2919 if (ia_valid & ATTR_FORCE) {
2920 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2921 ATTR_FORCE);
2922 if (!ia_valid)
2923 return 0;
2924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002926 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2927 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002928 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
Eric Paris3d2195c2012-07-06 14:13:30 -04002930 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002931 av |= FILE__OPEN;
2932
2933 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934}
2935
Al Viro3f7036a2015-03-08 19:28:30 -04002936static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937{
Al Viro3f7036a2015-03-08 19:28:30 -04002938 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939}
2940
David Howells8f0cfa52008-04-29 00:59:41 -07002941static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002942{
David Howells88e67f32008-11-14 10:39:21 +11002943 const struct cred *cred = current_cred();
2944
Serge E. Hallynb5376772007-10-16 23:31:36 -07002945 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2946 sizeof XATTR_SECURITY_PREFIX - 1)) {
2947 if (!strcmp(name, XATTR_NAME_CAPS)) {
2948 if (!capable(CAP_SETFCAP))
2949 return -EPERM;
2950 } else if (!capable(CAP_SYS_ADMIN)) {
2951 /* A different attribute in the security namespace.
2952 Restrict to administrator. */
2953 return -EPERM;
2954 }
2955 }
2956
2957 /* Not an attribute we recognize, so just check the
2958 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002959 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002960}
2961
David Howells8f0cfa52008-04-29 00:59:41 -07002962static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2963 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964{
David Howellsc6f493d2015-03-17 22:26:22 +00002965 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 struct inode_security_struct *isec = inode->i_security;
2967 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002968 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002969 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 int rc = 0;
2971
Serge E. Hallynb5376772007-10-16 23:31:36 -07002972 if (strcmp(name, XATTR_NAME_SELINUX))
2973 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
2975 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002976 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return -EOPNOTSUPP;
2978
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002979 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 return -EPERM;
2981
Eric Paris50c205f2012-04-04 15:01:43 -04002982 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002983 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
David Howells275bb412008-11-14 10:39:19 +11002985 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 FILE__RELABELFROM, &ad);
2987 if (rc)
2988 return rc;
2989
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002990 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002991 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002992 if (!capable(CAP_MAC_ADMIN)) {
2993 struct audit_buffer *ab;
2994 size_t audit_size;
2995 const char *str;
2996
2997 /* We strip a nul only if it is at the end, otherwise the
2998 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002999 if (value) {
3000 str = value;
3001 if (str[size - 1] == '\0')
3002 audit_size = size - 1;
3003 else
3004 audit_size = size;
3005 } else {
3006 str = "";
3007 audit_size = 0;
3008 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003009 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3010 audit_log_format(ab, "op=setxattr invalid_context=");
3011 audit_log_n_untrustedstring(ab, value, audit_size);
3012 audit_log_end(ab);
3013
Stephen Smalley12b29f32008-05-07 13:03:20 -04003014 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003015 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003016 rc = security_context_to_sid_force(value, size, &newsid);
3017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 if (rc)
3019 return rc;
3020
David Howells275bb412008-11-14 10:39:19 +11003021 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 FILE__RELABELTO, &ad);
3023 if (rc)
3024 return rc;
3025
David Howells275bb412008-11-14 10:39:19 +11003026 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003027 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 if (rc)
3029 return rc;
3030
3031 return avc_has_perm(newsid,
3032 sbsec->sid,
3033 SECCLASS_FILESYSTEM,
3034 FILESYSTEM__ASSOCIATE,
3035 &ad);
3036}
3037
David Howells8f0cfa52008-04-29 00:59:41 -07003038static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003039 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003040 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
David Howellsc6f493d2015-03-17 22:26:22 +00003042 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 struct inode_security_struct *isec = inode->i_security;
3044 u32 newsid;
3045 int rc;
3046
3047 if (strcmp(name, XATTR_NAME_SELINUX)) {
3048 /* Not an attribute we recognize, so nothing to do. */
3049 return;
3050 }
3051
Stephen Smalley12b29f32008-05-07 13:03:20 -04003052 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003054 printk(KERN_ERR "SELinux: unable to map context to SID"
3055 "for (%s, %lu), rc=%d\n",
3056 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 return;
3058 }
3059
David Quigleyaa9c2662013-05-22 12:50:44 -04003060 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003062 isec->initialized = 1;
3063
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064 return;
3065}
3066
David Howells8f0cfa52008-04-29 00:59:41 -07003067static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068{
David Howells88e67f32008-11-14 10:39:21 +11003069 const struct cred *cred = current_cred();
3070
Eric Paris2875fa02011-04-28 16:04:24 -04003071 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072}
3073
Eric Paris828dfe12008-04-17 13:17:49 -04003074static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075{
David Howells88e67f32008-11-14 10:39:21 +11003076 const struct cred *cred = current_cred();
3077
Eric Paris2875fa02011-04-28 16:04:24 -04003078 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079}
3080
David Howells8f0cfa52008-04-29 00:59:41 -07003081static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003083 if (strcmp(name, XATTR_NAME_SELINUX))
3084 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
3086 /* No one is allowed to remove a SELinux security label.
3087 You can change the label, but all data must be labeled. */
3088 return -EACCES;
3089}
3090
James Morrisd381d8a2005-10-30 14:59:22 -08003091/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003092 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003093 *
3094 * Permission check is handled by selinux_inode_getxattr hook.
3095 */
David P. Quigley42492592008-02-04 22:29:39 -08003096static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097{
David P. Quigley42492592008-02-04 22:29:39 -08003098 u32 size;
3099 int error;
3100 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003103 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3104 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003106 /*
3107 * If the caller has CAP_MAC_ADMIN, then get the raw context
3108 * value even if it is not defined by current policy; otherwise,
3109 * use the in-core value under current policy.
3110 * Use the non-auditing forms of the permission checks since
3111 * getxattr may be called by unprivileged processes commonly
3112 * and lack of permission just means that we fall back to the
3113 * in-core context value, not a denial.
3114 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003115 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3116 SECURITY_CAP_NOAUDIT);
3117 if (!error)
3118 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3119 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003120 if (!error)
3121 error = security_sid_to_context_force(isec->sid, &context,
3122 &size);
3123 else
3124 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003125 if (error)
3126 return error;
3127 error = size;
3128 if (alloc) {
3129 *buffer = context;
3130 goto out_nofree;
3131 }
3132 kfree(context);
3133out_nofree:
3134 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135}
3136
3137static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003138 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139{
3140 struct inode_security_struct *isec = inode->i_security;
3141 u32 newsid;
3142 int rc;
3143
3144 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3145 return -EOPNOTSUPP;
3146
3147 if (!value || !size)
3148 return -EACCES;
3149
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003150 rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 if (rc)
3152 return rc;
3153
David Quigleyaa9c2662013-05-22 12:50:44 -04003154 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003156 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 return 0;
3158}
3159
3160static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3161{
3162 const int len = sizeof(XATTR_NAME_SELINUX);
3163 if (buffer && len <= buffer_size)
3164 memcpy(buffer, XATTR_NAME_SELINUX, len);
3165 return len;
3166}
3167
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003168static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3169{
3170 struct inode_security_struct *isec = inode->i_security;
3171 *secid = isec->sid;
3172}
3173
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174/* file security operations */
3175
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003176static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177{
David Howells88e67f32008-11-14 10:39:21 +11003178 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003179 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3182 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3183 mask |= MAY_APPEND;
3184
Paul Moore389fb8002009-03-27 17:10:34 -04003185 return file_has_perm(cred, file,
3186 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187}
3188
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003189static int selinux_file_permission(struct file *file, int mask)
3190{
Al Viro496ad9a2013-01-23 17:07:38 -05003191 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003192 struct file_security_struct *fsec = file->f_security;
3193 struct inode_security_struct *isec = inode->i_security;
3194 u32 sid = current_sid();
3195
Paul Moore389fb8002009-03-27 17:10:34 -04003196 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003197 /* No permission to check. Existence test. */
3198 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003199
Stephen Smalley20dda182009-06-22 14:54:53 -04003200 if (sid == fsec->sid && fsec->isid == isec->sid &&
3201 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003202 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003203 return 0;
3204
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003205 return selinux_revalidate_file_permission(file, mask);
3206}
3207
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208static int selinux_file_alloc_security(struct file *file)
3209{
3210 return file_alloc_security(file);
3211}
3212
3213static void selinux_file_free_security(struct file *file)
3214{
3215 file_free_security(file);
3216}
3217
3218static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3219 unsigned long arg)
3220{
David Howells88e67f32008-11-14 10:39:21 +11003221 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003222 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Eric Paris0b24dcb2011-02-25 15:39:20 -05003224 switch (cmd) {
3225 case FIONREAD:
3226 /* fall through */
3227 case FIBMAP:
3228 /* fall through */
3229 case FIGETBSZ:
3230 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003231 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003232 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003233 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003234 error = file_has_perm(cred, file, FILE__GETATTR);
3235 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236
Al Viro2f99c362012-03-23 16:04:05 -04003237 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003238 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003239 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003240 error = file_has_perm(cred, file, FILE__SETATTR);
3241 break;
3242
3243 /* sys_ioctl() checks */
3244 case FIONBIO:
3245 /* fall through */
3246 case FIOASYNC:
3247 error = file_has_perm(cred, file, 0);
3248 break;
3249
3250 case KDSKBENT:
3251 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003252 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3253 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003254 break;
3255
3256 /* default case assumes that the command will go
3257 * to the file's ioctl() function.
3258 */
3259 default:
3260 error = file_has_perm(cred, file, FILE__IOCTL);
3261 }
3262 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263}
3264
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003265static int default_noexec;
3266
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3268{
David Howells88e67f32008-11-14 10:39:21 +11003269 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003270 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003271
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003272 if (default_noexec &&
3273 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 /*
3275 * We are making executable an anonymous mapping or a
3276 * private file mapping that will also be writable.
3277 * This has an additional check.
3278 */
David Howellsd84f4f92008-11-14 10:39:23 +11003279 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003281 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
3284 if (file) {
3285 /* read access is always possible with a mapping */
3286 u32 av = FILE__READ;
3287
3288 /* write access only matters if the mapping is shared */
3289 if (shared && (prot & PROT_WRITE))
3290 av |= FILE__WRITE;
3291
3292 if (prot & PROT_EXEC)
3293 av |= FILE__EXECUTE;
3294
David Howells88e67f32008-11-14 10:39:21 +11003295 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 }
David Howellsd84f4f92008-11-14 10:39:23 +11003297
3298error:
3299 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300}
3301
Al Viroe5467852012-05-30 13:30:51 -04003302static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003304 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003305
3306 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3307 u32 sid = current_sid();
3308 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3309 MEMPROTECT__MMAP_ZERO, NULL);
3310 }
3311
3312 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003313}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Al Viroe5467852012-05-30 13:30:51 -04003315static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3316 unsigned long prot, unsigned long flags)
3317{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 if (selinux_checkreqprot)
3319 prot = reqprot;
3320
3321 return file_map_prot_check(file, prot,
3322 (flags & MAP_TYPE) == MAP_SHARED);
3323}
3324
3325static int selinux_file_mprotect(struct vm_area_struct *vma,
3326 unsigned long reqprot,
3327 unsigned long prot)
3328{
David Howells88e67f32008-11-14 10:39:21 +11003329 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
3331 if (selinux_checkreqprot)
3332 prot = reqprot;
3333
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003334 if (default_noexec &&
3335 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003336 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003337 if (vma->vm_start >= vma->vm_mm->start_brk &&
3338 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003339 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003340 } else if (!vma->vm_file &&
3341 vma->vm_start <= vma->vm_mm->start_stack &&
3342 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003343 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003344 } else if (vma->vm_file && vma->anon_vma) {
3345 /*
3346 * We are making executable a file mapping that has
3347 * had some COW done. Since pages might have been
3348 * written, check ability to execute the possibly
3349 * modified content. This typically should only
3350 * occur for text relocations.
3351 */
David Howellsd84f4f92008-11-14 10:39:23 +11003352 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003353 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003354 if (rc)
3355 return rc;
3356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
3358 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3359}
3360
3361static int selinux_file_lock(struct file *file, unsigned int cmd)
3362{
David Howells88e67f32008-11-14 10:39:21 +11003363 const struct cred *cred = current_cred();
3364
3365 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366}
3367
3368static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3369 unsigned long arg)
3370{
David Howells88e67f32008-11-14 10:39:21 +11003371 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 int err = 0;
3373
3374 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003375 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003376 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003377 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003379 }
3380 /* fall through */
3381 case F_SETOWN:
3382 case F_SETSIG:
3383 case F_GETFL:
3384 case F_GETOWN:
3385 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003386 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003387 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003388 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003389 break;
3390 case F_GETLK:
3391 case F_SETLK:
3392 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003393 case F_OFD_GETLK:
3394 case F_OFD_SETLK:
3395 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003397 case F_GETLK64:
3398 case F_SETLK64:
3399 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400#endif
David Howells88e67f32008-11-14 10:39:21 +11003401 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003402 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403 }
3404
3405 return err;
3406}
3407
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003408static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 struct file_security_struct *fsec;
3411
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003413 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414}
3415
3416static int selinux_file_send_sigiotask(struct task_struct *tsk,
3417 struct fown_struct *fown, int signum)
3418{
Eric Paris828dfe12008-04-17 13:17:49 -04003419 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003420 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 struct file_security_struct *fsec;
3423
3424 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003425 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 fsec = file->f_security;
3428
3429 if (!signum)
3430 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3431 else
3432 perm = signal_to_av(signum);
3433
David Howells275bb412008-11-14 10:39:19 +11003434 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 SECCLASS_PROCESS, perm, NULL);
3436}
3437
3438static int selinux_file_receive(struct file *file)
3439{
David Howells88e67f32008-11-14 10:39:21 +11003440 const struct cred *cred = current_cred();
3441
3442 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443}
3444
Eric Paris83d49852012-04-04 13:45:40 -04003445static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003446{
3447 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003448 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003449
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003450 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003451 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003452 /*
3453 * Save inode label and policy sequence number
3454 * at open-time so that selinux_file_permission
3455 * can determine whether revalidation is necessary.
3456 * Task label is already saved in the file security
3457 * struct as its SID.
3458 */
3459 fsec->isid = isec->sid;
3460 fsec->pseqno = avc_policy_seqno();
3461 /*
3462 * Since the inode label or policy seqno may have changed
3463 * between the selinux_inode_permission check and the saving
3464 * of state above, recheck that access is still permitted.
3465 * Otherwise, access might never be revalidated against the
3466 * new inode label or new policy.
3467 * This check is not redundant - do not remove.
3468 */
David Howells13f8e982013-06-13 23:37:55 +01003469 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003470}
3471
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472/* task security operations */
3473
3474static int selinux_task_create(unsigned long clone_flags)
3475{
David Howells3b11a1d2008-11-14 10:39:26 +11003476 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477}
3478
David Howellsf1752ee2008-11-14 10:39:17 +11003479/*
David Howellsee18d642009-09-02 09:14:21 +01003480 * allocate the SELinux part of blank credentials
3481 */
3482static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3483{
3484 struct task_security_struct *tsec;
3485
3486 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3487 if (!tsec)
3488 return -ENOMEM;
3489
3490 cred->security = tsec;
3491 return 0;
3492}
3493
3494/*
David Howellsf1752ee2008-11-14 10:39:17 +11003495 * detach and free the LSM part of a set of credentials
3496 */
3497static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498{
David Howellsf1752ee2008-11-14 10:39:17 +11003499 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003500
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003501 /*
3502 * cred->security == NULL if security_cred_alloc_blank() or
3503 * security_prepare_creds() returned an error.
3504 */
3505 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003506 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003507 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508}
3509
David Howellsd84f4f92008-11-14 10:39:23 +11003510/*
3511 * prepare a new set of credentials for modification
3512 */
3513static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3514 gfp_t gfp)
3515{
3516 const struct task_security_struct *old_tsec;
3517 struct task_security_struct *tsec;
3518
3519 old_tsec = old->security;
3520
3521 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3522 if (!tsec)
3523 return -ENOMEM;
3524
3525 new->security = tsec;
3526 return 0;
3527}
3528
3529/*
David Howellsee18d642009-09-02 09:14:21 +01003530 * transfer the SELinux data to a blank set of creds
3531 */
3532static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3533{
3534 const struct task_security_struct *old_tsec = old->security;
3535 struct task_security_struct *tsec = new->security;
3536
3537 *tsec = *old_tsec;
3538}
3539
3540/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003541 * set the security data for a kernel service
3542 * - all the creation contexts are set to unlabelled
3543 */
3544static int selinux_kernel_act_as(struct cred *new, u32 secid)
3545{
3546 struct task_security_struct *tsec = new->security;
3547 u32 sid = current_sid();
3548 int ret;
3549
3550 ret = avc_has_perm(sid, secid,
3551 SECCLASS_KERNEL_SERVICE,
3552 KERNEL_SERVICE__USE_AS_OVERRIDE,
3553 NULL);
3554 if (ret == 0) {
3555 tsec->sid = secid;
3556 tsec->create_sid = 0;
3557 tsec->keycreate_sid = 0;
3558 tsec->sockcreate_sid = 0;
3559 }
3560 return ret;
3561}
3562
3563/*
3564 * set the file creation context in a security record to the same as the
3565 * objective context of the specified inode
3566 */
3567static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3568{
3569 struct inode_security_struct *isec = inode->i_security;
3570 struct task_security_struct *tsec = new->security;
3571 u32 sid = current_sid();
3572 int ret;
3573
3574 ret = avc_has_perm(sid, isec->sid,
3575 SECCLASS_KERNEL_SERVICE,
3576 KERNEL_SERVICE__CREATE_FILES_AS,
3577 NULL);
3578
3579 if (ret == 0)
3580 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003581 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003582}
3583
Eric Parisdd8dbf22009-11-03 16:35:32 +11003584static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003585{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003586 u32 sid;
3587 struct common_audit_data ad;
3588
3589 sid = task_sid(current);
3590
Eric Paris50c205f2012-04-04 15:01:43 -04003591 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003592 ad.u.kmod_name = kmod_name;
3593
3594 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3595 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003596}
3597
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3599{
David Howells3b11a1d2008-11-14 10:39:26 +11003600 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601}
3602
3603static int selinux_task_getpgid(struct task_struct *p)
3604{
David Howells3b11a1d2008-11-14 10:39:26 +11003605 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606}
3607
3608static int selinux_task_getsid(struct task_struct *p)
3609{
David Howells3b11a1d2008-11-14 10:39:26 +11003610 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611}
3612
David Quigleyf9008e42006-06-30 01:55:46 -07003613static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3614{
David Howells275bb412008-11-14 10:39:19 +11003615 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003616}
3617
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618static int selinux_task_setnice(struct task_struct *p, int nice)
3619{
David Howells3b11a1d2008-11-14 10:39:26 +11003620 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621}
3622
James Morris03e68062006-06-23 02:03:58 -07003623static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3624{
David Howells3b11a1d2008-11-14 10:39:26 +11003625 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003626}
3627
David Quigleya1836a42006-06-30 01:55:49 -07003628static int selinux_task_getioprio(struct task_struct *p)
3629{
David Howells3b11a1d2008-11-14 10:39:26 +11003630 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003631}
3632
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003633static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3634 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003636 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
3638 /* Control the ability to change the hard limit (whether
3639 lowering or raising it), so that the hard limit can
3640 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003641 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003643 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644
3645 return 0;
3646}
3647
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003648static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649{
David Howells3b11a1d2008-11-14 10:39:26 +11003650 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651}
3652
3653static int selinux_task_getscheduler(struct task_struct *p)
3654{
David Howells3b11a1d2008-11-14 10:39:26 +11003655 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656}
3657
David Quigley35601542006-06-23 02:04:01 -07003658static int selinux_task_movememory(struct task_struct *p)
3659{
David Howells3b11a1d2008-11-14 10:39:26 +11003660 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003661}
3662
David Quigleyf9008e42006-06-30 01:55:46 -07003663static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3664 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665{
3666 u32 perm;
3667 int rc;
3668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 if (!sig)
3670 perm = PROCESS__SIGNULL; /* null signal; existence test */
3671 else
3672 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003673 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003674 rc = avc_has_perm(secid, task_sid(p),
3675 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003676 else
David Howells3b11a1d2008-11-14 10:39:26 +11003677 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003678 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679}
3680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681static int selinux_task_wait(struct task_struct *p)
3682{
Eric Paris8a535142007-10-22 16:10:31 -04003683 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684}
3685
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686static void selinux_task_to_inode(struct task_struct *p,
3687 struct inode *inode)
3688{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003690 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691
David Howells275bb412008-11-14 10:39:19 +11003692 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694}
3695
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003697static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003698 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
3700 int offset, ihlen, ret = -EINVAL;
3701 struct iphdr _iph, *ih;
3702
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003703 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3705 if (ih == NULL)
3706 goto out;
3707
3708 ihlen = ih->ihl * 4;
3709 if (ihlen < sizeof(_iph))
3710 goto out;
3711
Eric Paris48c62af2012-04-02 13:15:44 -04003712 ad->u.net->v4info.saddr = ih->saddr;
3713 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 ret = 0;
3715
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003716 if (proto)
3717 *proto = ih->protocol;
3718
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003720 case IPPROTO_TCP: {
3721 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Eric Paris828dfe12008-04-17 13:17:49 -04003723 if (ntohs(ih->frag_off) & IP_OFFSET)
3724 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
3726 offset += ihlen;
3727 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3728 if (th == NULL)
3729 break;
3730
Eric Paris48c62af2012-04-02 13:15:44 -04003731 ad->u.net->sport = th->source;
3732 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003734 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Eric Paris828dfe12008-04-17 13:17:49 -04003736 case IPPROTO_UDP: {
3737 struct udphdr _udph, *uh;
3738
3739 if (ntohs(ih->frag_off) & IP_OFFSET)
3740 break;
3741
3742 offset += ihlen;
3743 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3744 if (uh == NULL)
3745 break;
3746
Eric Paris48c62af2012-04-02 13:15:44 -04003747 ad->u.net->sport = uh->source;
3748 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003749 break;
3750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
James Morris2ee92d42006-11-13 16:09:01 -08003752 case IPPROTO_DCCP: {
3753 struct dccp_hdr _dccph, *dh;
3754
3755 if (ntohs(ih->frag_off) & IP_OFFSET)
3756 break;
3757
3758 offset += ihlen;
3759 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3760 if (dh == NULL)
3761 break;
3762
Eric Paris48c62af2012-04-02 13:15:44 -04003763 ad->u.net->sport = dh->dccph_sport;
3764 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003765 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003766 }
James Morris2ee92d42006-11-13 16:09:01 -08003767
Eric Paris828dfe12008-04-17 13:17:49 -04003768 default:
3769 break;
3770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771out:
3772 return ret;
3773}
3774
3775#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3776
3777/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003778static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003779 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780{
3781 u8 nexthdr;
3782 int ret = -EINVAL, offset;
3783 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003784 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003786 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3788 if (ip6 == NULL)
3789 goto out;
3790
Eric Paris48c62af2012-04-02 13:15:44 -04003791 ad->u.net->v6info.saddr = ip6->saddr;
3792 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 ret = 0;
3794
3795 nexthdr = ip6->nexthdr;
3796 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003797 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 if (offset < 0)
3799 goto out;
3800
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003801 if (proto)
3802 *proto = nexthdr;
3803
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 switch (nexthdr) {
3805 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003806 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3809 if (th == NULL)
3810 break;
3811
Eric Paris48c62af2012-04-02 13:15:44 -04003812 ad->u.net->sport = th->source;
3813 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 break;
3815 }
3816
3817 case IPPROTO_UDP: {
3818 struct udphdr _udph, *uh;
3819
3820 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3821 if (uh == NULL)
3822 break;
3823
Eric Paris48c62af2012-04-02 13:15:44 -04003824 ad->u.net->sport = uh->source;
3825 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 break;
3827 }
3828
James Morris2ee92d42006-11-13 16:09:01 -08003829 case IPPROTO_DCCP: {
3830 struct dccp_hdr _dccph, *dh;
3831
3832 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3833 if (dh == NULL)
3834 break;
3835
Eric Paris48c62af2012-04-02 13:15:44 -04003836 ad->u.net->sport = dh->dccph_sport;
3837 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003838 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003839 }
James Morris2ee92d42006-11-13 16:09:01 -08003840
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 /* includes fragments */
3842 default:
3843 break;
3844 }
3845out:
3846 return ret;
3847}
3848
3849#endif /* IPV6 */
3850
Thomas Liu2bf49692009-07-14 12:14:09 -04003851static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003852 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
David Howellscf9481e2008-07-27 21:31:07 +10003854 char *addrp;
3855 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Eric Paris48c62af2012-04-02 13:15:44 -04003857 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003859 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003860 if (ret)
3861 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003862 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3863 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003864 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
3866#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3867 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003868 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003869 if (ret)
3870 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003871 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3872 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003873 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874#endif /* IPV6 */
3875 default:
David Howellscf9481e2008-07-27 21:31:07 +10003876 addrp = NULL;
3877 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 }
3879
David Howellscf9481e2008-07-27 21:31:07 +10003880parse_error:
3881 printk(KERN_WARNING
3882 "SELinux: failure in selinux_parse_skb(),"
3883 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003885
3886okay:
3887 if (_addrp)
3888 *_addrp = addrp;
3889 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890}
3891
Paul Moore4f6a9932007-03-01 14:35:22 -05003892/**
Paul Moore220deb92008-01-29 08:38:23 -05003893 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003894 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003895 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003896 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003897 *
3898 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003899 * Check the various different forms of network peer labeling and determine
3900 * the peer label/SID for the packet; most of the magic actually occurs in
3901 * the security server function security_net_peersid_cmp(). The function
3902 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3903 * or -EACCES if @sid is invalid due to inconsistencies with the different
3904 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003905 *
3906 */
Paul Moore220deb92008-01-29 08:38:23 -05003907static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003908{
Paul Moore71f1cb02008-01-29 08:51:16 -05003909 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003910 u32 xfrm_sid;
3911 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003912 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003913
Paul Moore817eff72013-12-10 14:57:54 -05003914 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003915 if (unlikely(err))
3916 return -EACCES;
3917 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3918 if (unlikely(err))
3919 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003920
Paul Moore71f1cb02008-01-29 08:51:16 -05003921 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3922 if (unlikely(err)) {
3923 printk(KERN_WARNING
3924 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3925 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003926 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003927 }
Paul Moore220deb92008-01-29 08:38:23 -05003928
3929 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003930}
3931
Paul Moore446b8022013-12-04 16:10:51 -05003932/**
3933 * selinux_conn_sid - Determine the child socket label for a connection
3934 * @sk_sid: the parent socket's SID
3935 * @skb_sid: the packet's SID
3936 * @conn_sid: the resulting connection SID
3937 *
3938 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3939 * combined with the MLS information from @skb_sid in order to create
3940 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3941 * of @sk_sid. Returns zero on success, negative values on failure.
3942 *
3943 */
3944static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3945{
3946 int err = 0;
3947
3948 if (skb_sid != SECSID_NULL)
3949 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3950 else
3951 *conn_sid = sk_sid;
3952
3953 return err;
3954}
3955
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003957
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003958static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3959 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003960{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003961 if (tsec->sockcreate_sid > SECSID_NULL) {
3962 *socksid = tsec->sockcreate_sid;
3963 return 0;
3964 }
3965
3966 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3967 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003968}
3969
Paul Moore253bfae2010-04-22 14:46:19 -04003970static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971{
Paul Moore253bfae2010-04-22 14:46:19 -04003972 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003973 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003974 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003975 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976
Paul Moore253bfae2010-04-22 14:46:19 -04003977 if (sksec->sid == SECINITSID_KERNEL)
3978 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979
Eric Paris50c205f2012-04-04 15:01:43 -04003980 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003981 ad.u.net = &net;
3982 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983
Paul Moore253bfae2010-04-22 14:46:19 -04003984 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985}
3986
3987static int selinux_socket_create(int family, int type,
3988 int protocol, int kern)
3989{
Paul Moore5fb49872010-04-22 14:46:19 -04003990 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003991 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003992 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003993 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
3995 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003996 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997
David Howells275bb412008-11-14 10:39:19 +11003998 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003999 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4000 if (rc)
4001 return rc;
4002
Paul Moored4f2d972010-04-22 14:46:18 -04004003 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004}
4005
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004006static int selinux_socket_post_create(struct socket *sock, int family,
4007 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008{
Paul Moore5fb49872010-04-22 14:46:19 -04004009 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004010 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004011 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004012 int err = 0;
4013
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004014 isec->sclass = socket_type_to_security_class(family, type, protocol);
4015
David Howells275bb412008-11-14 10:39:19 +11004016 if (kern)
4017 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004018 else {
4019 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4020 if (err)
4021 return err;
4022 }
David Howells275bb412008-11-14 10:39:19 +11004023
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 isec->initialized = 1;
4025
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004026 if (sock->sk) {
4027 sksec = sock->sk->sk_security;
4028 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004029 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004030 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004031 }
4032
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004033 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034}
4035
4036/* Range of port numbers used to automatically bind.
4037 Need to determine whether we should perform a name_bind
4038 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
4040static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4041{
Paul Moore253bfae2010-04-22 14:46:19 -04004042 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 u16 family;
4044 int err;
4045
Paul Moore253bfae2010-04-22 14:46:19 -04004046 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 if (err)
4048 goto out;
4049
4050 /*
4051 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004052 * Multiple address binding for SCTP is not supported yet: we just
4053 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 */
Paul Moore253bfae2010-04-22 14:46:19 -04004055 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 if (family == PF_INET || family == PF_INET6) {
4057 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004058 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004059 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004060 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 struct sockaddr_in *addr4 = NULL;
4062 struct sockaddr_in6 *addr6 = NULL;
4063 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004064 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 if (family == PF_INET) {
4067 addr4 = (struct sockaddr_in *)address;
4068 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 addrp = (char *)&addr4->sin_addr.s_addr;
4070 } else {
4071 addr6 = (struct sockaddr_in6 *)address;
4072 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 addrp = (char *)&addr6->sin6_addr.s6_addr;
4074 }
4075
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004076 if (snum) {
4077 int low, high;
4078
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004079 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004080
4081 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004082 err = sel_netport_sid(sk->sk_protocol,
4083 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004084 if (err)
4085 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004086 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004087 ad.u.net = &net;
4088 ad.u.net->sport = htons(snum);
4089 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004090 err = avc_has_perm(sksec->sid, sid,
4091 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004092 SOCKET__NAME_BIND, &ad);
4093 if (err)
4094 goto out;
4095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 }
Eric Paris828dfe12008-04-17 13:17:49 -04004097
Paul Moore253bfae2010-04-22 14:46:19 -04004098 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004099 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 node_perm = TCP_SOCKET__NODE_BIND;
4101 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004102
James Morris13402582005-09-30 14:24:34 -04004103 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 node_perm = UDP_SOCKET__NODE_BIND;
4105 break;
James Morris2ee92d42006-11-13 16:09:01 -08004106
4107 case SECCLASS_DCCP_SOCKET:
4108 node_perm = DCCP_SOCKET__NODE_BIND;
4109 break;
4110
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 default:
4112 node_perm = RAWIP_SOCKET__NODE_BIND;
4113 break;
4114 }
Eric Paris828dfe12008-04-17 13:17:49 -04004115
Paul Moore224dfbd2008-01-29 08:38:13 -05004116 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 if (err)
4118 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004119
Eric Paris50c205f2012-04-04 15:01:43 -04004120 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004121 ad.u.net = &net;
4122 ad.u.net->sport = htons(snum);
4123 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
4125 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004126 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 else
Eric Paris48c62af2012-04-02 13:15:44 -04004128 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
Paul Moore253bfae2010-04-22 14:46:19 -04004130 err = avc_has_perm(sksec->sid, sid,
4131 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 if (err)
4133 goto out;
4134 }
4135out:
4136 return err;
4137}
4138
4139static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4140{
Paul Moore014ab192008-10-10 10:16:33 -04004141 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004142 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 int err;
4144
Paul Moore253bfae2010-04-22 14:46:19 -04004145 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 if (err)
4147 return err;
4148
4149 /*
James Morris2ee92d42006-11-13 16:09:01 -08004150 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 */
Paul Moore253bfae2010-04-22 14:46:19 -04004152 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4153 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004154 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004155 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 struct sockaddr_in *addr4 = NULL;
4157 struct sockaddr_in6 *addr6 = NULL;
4158 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004159 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
4161 if (sk->sk_family == PF_INET) {
4162 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004163 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 return -EINVAL;
4165 snum = ntohs(addr4->sin_port);
4166 } else {
4167 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004168 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 return -EINVAL;
4170 snum = ntohs(addr6->sin6_port);
4171 }
4172
Paul Moore3e112172008-04-10 10:48:14 -04004173 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 if (err)
4175 goto out;
4176
Paul Moore253bfae2010-04-22 14:46:19 -04004177 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004178 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4179
Eric Paris50c205f2012-04-04 15:01:43 -04004180 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004181 ad.u.net = &net;
4182 ad.u.net->dport = htons(snum);
4183 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004184 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 if (err)
4186 goto out;
4187 }
4188
Paul Moore014ab192008-10-10 10:16:33 -04004189 err = selinux_netlbl_socket_connect(sk, address);
4190
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191out:
4192 return err;
4193}
4194
4195static int selinux_socket_listen(struct socket *sock, int backlog)
4196{
Paul Moore253bfae2010-04-22 14:46:19 -04004197 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198}
4199
4200static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4201{
4202 int err;
4203 struct inode_security_struct *isec;
4204 struct inode_security_struct *newisec;
4205
Paul Moore253bfae2010-04-22 14:46:19 -04004206 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 if (err)
4208 return err;
4209
4210 newisec = SOCK_INODE(newsock)->i_security;
4211
4212 isec = SOCK_INODE(sock)->i_security;
4213 newisec->sclass = isec->sclass;
4214 newisec->sid = isec->sid;
4215 newisec->initialized = 1;
4216
4217 return 0;
4218}
4219
4220static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004221 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222{
Paul Moore253bfae2010-04-22 14:46:19 -04004223 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224}
4225
4226static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4227 int size, int flags)
4228{
Paul Moore253bfae2010-04-22 14:46:19 -04004229 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230}
4231
4232static int selinux_socket_getsockname(struct socket *sock)
4233{
Paul Moore253bfae2010-04-22 14:46:19 -04004234 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235}
4236
4237static int selinux_socket_getpeername(struct socket *sock)
4238{
Paul Moore253bfae2010-04-22 14:46:19 -04004239 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240}
4241
Eric Paris828dfe12008-04-17 13:17:49 -04004242static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243{
Paul Mooref8687af2006-10-30 15:22:15 -08004244 int err;
4245
Paul Moore253bfae2010-04-22 14:46:19 -04004246 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004247 if (err)
4248 return err;
4249
4250 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251}
4252
4253static int selinux_socket_getsockopt(struct socket *sock, int level,
4254 int optname)
4255{
Paul Moore253bfae2010-04-22 14:46:19 -04004256 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257}
4258
4259static int selinux_socket_shutdown(struct socket *sock, int how)
4260{
Paul Moore253bfae2010-04-22 14:46:19 -04004261 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262}
4263
David S. Miller3610cda2011-01-05 15:38:53 -08004264static int selinux_socket_unix_stream_connect(struct sock *sock,
4265 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 struct sock *newsk)
4267{
David S. Miller3610cda2011-01-05 15:38:53 -08004268 struct sk_security_struct *sksec_sock = sock->sk_security;
4269 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004270 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004271 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004272 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 int err;
4274
Eric Paris50c205f2012-04-04 15:01:43 -04004275 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004276 ad.u.net = &net;
4277 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
Paul Moore4d1e2452010-04-22 14:46:18 -04004279 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4280 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4282 if (err)
4283 return err;
4284
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004286 sksec_new->peer_sid = sksec_sock->sid;
4287 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4288 &sksec_new->sid);
4289 if (err)
4290 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004291
Paul Moore4d1e2452010-04-22 14:46:18 -04004292 /* connecting socket */
4293 sksec_sock->peer_sid = sksec_new->sid;
4294
4295 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296}
4297
4298static int selinux_socket_unix_may_send(struct socket *sock,
4299 struct socket *other)
4300{
Paul Moore253bfae2010-04-22 14:46:19 -04004301 struct sk_security_struct *ssec = sock->sk->sk_security;
4302 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004303 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004304 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Eric Paris50c205f2012-04-04 15:01:43 -04004306 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004307 ad.u.net = &net;
4308 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Paul Moore253bfae2010-04-22 14:46:19 -04004310 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4311 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312}
4313
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004314static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4315 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004316 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004317{
4318 int err;
4319 u32 if_sid;
4320 u32 node_sid;
4321
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004322 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004323 if (err)
4324 return err;
4325 err = avc_has_perm(peer_sid, if_sid,
4326 SECCLASS_NETIF, NETIF__INGRESS, ad);
4327 if (err)
4328 return err;
4329
4330 err = sel_netnode_sid(addrp, family, &node_sid);
4331 if (err)
4332 return err;
4333 return avc_has_perm(peer_sid, node_sid,
4334 SECCLASS_NODE, NODE__RECVFROM, ad);
4335}
4336
Paul Moore220deb92008-01-29 08:38:23 -05004337static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004338 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004339{
Paul Moore277d3422008-12-31 12:54:11 -05004340 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004341 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004342 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004343 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004344 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004345 char *addrp;
4346
Eric Paris50c205f2012-04-04 15:01:43 -04004347 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004348 ad.u.net = &net;
4349 ad.u.net->netif = skb->skb_iif;
4350 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004351 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4352 if (err)
4353 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004354
Paul Moore58bfbb52009-03-27 17:10:41 -04004355 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004356 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004357 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004358 if (err)
4359 return err;
4360 }
Paul Moore220deb92008-01-29 08:38:23 -05004361
Steffen Klassertb9679a72011-02-23 12:55:21 +01004362 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4363 if (err)
4364 return err;
4365 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004366
James Morris4e5ab4c2006-06-09 00:33:33 -07004367 return err;
4368}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004369
James Morris4e5ab4c2006-06-09 00:33:33 -07004370static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4371{
Paul Moore220deb92008-01-29 08:38:23 -05004372 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004373 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004374 u16 family = sk->sk_family;
4375 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004376 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004377 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004378 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004379 u8 secmark_active;
4380 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004381
James Morris4e5ab4c2006-06-09 00:33:33 -07004382 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004383 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004384
4385 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004386 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004387 family = PF_INET;
4388
Paul Moored8395c82008-10-10 10:16:30 -04004389 /* If any sort of compatibility mode is enabled then handoff processing
4390 * to the selinux_sock_rcv_skb_compat() function to deal with the
4391 * special handling. We do this in an attempt to keep this function
4392 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004393 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004394 return selinux_sock_rcv_skb_compat(sk, skb, family);
4395
4396 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004397 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004398 if (!secmark_active && !peerlbl_active)
4399 return 0;
4400
Eric Paris50c205f2012-04-04 15:01:43 -04004401 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004402 ad.u.net = &net;
4403 ad.u.net->netif = skb->skb_iif;
4404 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004405 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004406 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004407 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004408
Paul Moored8395c82008-10-10 10:16:30 -04004409 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004410 u32 peer_sid;
4411
4412 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4413 if (err)
4414 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004415 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4416 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004417 if (err) {
4418 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004419 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004420 }
Paul Moored621d352008-01-29 08:43:36 -05004421 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4422 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004423 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004424 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004425 return err;
4426 }
Paul Moored621d352008-01-29 08:43:36 -05004427 }
4428
Paul Moored8395c82008-10-10 10:16:30 -04004429 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004430 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4431 PACKET__RECV, &ad);
4432 if (err)
4433 return err;
4434 }
4435
Paul Moored621d352008-01-29 08:43:36 -05004436 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437}
4438
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004439static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4440 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441{
4442 int err = 0;
4443 char *scontext;
4444 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004445 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004446 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
Paul Moore253bfae2010-04-22 14:46:19 -04004448 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4449 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004450 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004451 if (peer_sid == SECSID_NULL)
4452 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004454 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004456 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
4458 if (scontext_len > len) {
4459 err = -ERANGE;
4460 goto out_len;
4461 }
4462
4463 if (copy_to_user(optval, scontext, scontext_len))
4464 err = -EFAULT;
4465
4466out_len:
4467 if (put_user(scontext_len, optlen))
4468 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 return err;
4471}
4472
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004473static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004474{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004475 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004476 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004477
Paul Mooreaa862902008-10-10 10:16:29 -04004478 if (skb && skb->protocol == htons(ETH_P_IP))
4479 family = PF_INET;
4480 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4481 family = PF_INET6;
4482 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004483 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004484 else
4485 goto out;
4486
4487 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004488 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004489 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004490 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004491
Paul Moore75e22912008-01-29 08:38:04 -05004492out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004493 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004494 if (peer_secid == SECSID_NULL)
4495 return -EINVAL;
4496 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004497}
4498
Al Viro7d877f32005-10-21 03:20:43 -04004499static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500{
Paul Moore84914b72010-04-22 14:46:18 -04004501 struct sk_security_struct *sksec;
4502
4503 sksec = kzalloc(sizeof(*sksec), priority);
4504 if (!sksec)
4505 return -ENOMEM;
4506
4507 sksec->peer_sid = SECINITSID_UNLABELED;
4508 sksec->sid = SECINITSID_UNLABELED;
4509 selinux_netlbl_sk_security_reset(sksec);
4510 sk->sk_security = sksec;
4511
4512 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513}
4514
4515static void selinux_sk_free_security(struct sock *sk)
4516{
Paul Moore84914b72010-04-22 14:46:18 -04004517 struct sk_security_struct *sksec = sk->sk_security;
4518
4519 sk->sk_security = NULL;
4520 selinux_netlbl_sk_security_free(sksec);
4521 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522}
4523
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004524static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4525{
Eric Parisdd3e7832010-04-07 15:08:46 -04004526 struct sk_security_struct *sksec = sk->sk_security;
4527 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004528
Eric Parisdd3e7832010-04-07 15:08:46 -04004529 newsksec->sid = sksec->sid;
4530 newsksec->peer_sid = sksec->peer_sid;
4531 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004532
Eric Parisdd3e7832010-04-07 15:08:46 -04004533 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004534}
4535
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004536static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004537{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004538 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004539 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004540 else {
4541 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004542
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004543 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004544 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004545}
4546
Eric Paris828dfe12008-04-17 13:17:49 -04004547static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004548{
4549 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4550 struct sk_security_struct *sksec = sk->sk_security;
4551
Paul Moore2873ead2014-07-28 10:42:48 -04004552 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4553 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004554 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004555 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004556}
4557
Adrian Bunk9a673e52006-08-15 00:03:53 -07004558static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4559 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004560{
4561 struct sk_security_struct *sksec = sk->sk_security;
4562 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004563 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004564 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004565 u32 peersid;
4566
Paul Mooreaa862902008-10-10 10:16:29 -04004567 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004568 if (err)
4569 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004570 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4571 if (err)
4572 return err;
4573 req->secid = connsid;
4574 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004575
Paul Moore389fb8002009-03-27 17:10:34 -04004576 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004577}
4578
Adrian Bunk9a673e52006-08-15 00:03:53 -07004579static void selinux_inet_csk_clone(struct sock *newsk,
4580 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581{
4582 struct sk_security_struct *newsksec = newsk->sk_security;
4583
4584 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004585 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004586 /* NOTE: Ideally, we should also get the isec->sid for the
4587 new socket in sync, but we don't have the isec available yet.
4588 So we will wait until sock_graft to do it, by which
4589 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004590
Paul Moore9f2ad662006-11-17 17:38:53 -05004591 /* We don't need to take any sort of lock here as we are the only
4592 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004593 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004594}
4595
Paul Moore014ab192008-10-10 10:16:33 -04004596static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004597{
Paul Mooreaa862902008-10-10 10:16:29 -04004598 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004599 struct sk_security_struct *sksec = sk->sk_security;
4600
Paul Mooreaa862902008-10-10 10:16:29 -04004601 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4602 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4603 family = PF_INET;
4604
4605 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004606}
4607
Eric Paris2606fd12010-10-13 16:24:41 -04004608static int selinux_secmark_relabel_packet(u32 sid)
4609{
4610 const struct task_security_struct *__tsec;
4611 u32 tsid;
4612
4613 __tsec = current_security();
4614 tsid = __tsec->sid;
4615
4616 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4617}
4618
4619static void selinux_secmark_refcount_inc(void)
4620{
4621 atomic_inc(&selinux_secmark_refcount);
4622}
4623
4624static void selinux_secmark_refcount_dec(void)
4625{
4626 atomic_dec(&selinux_secmark_refcount);
4627}
4628
Adrian Bunk9a673e52006-08-15 00:03:53 -07004629static void selinux_req_classify_flow(const struct request_sock *req,
4630 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004631{
David S. Miller1d28f422011-03-12 00:29:39 -05004632 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004633}
4634
Paul Moore5dbbaf22013-01-14 07:12:19 +00004635static int selinux_tun_dev_alloc_security(void **security)
4636{
4637 struct tun_security_struct *tunsec;
4638
4639 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4640 if (!tunsec)
4641 return -ENOMEM;
4642 tunsec->sid = current_sid();
4643
4644 *security = tunsec;
4645 return 0;
4646}
4647
4648static void selinux_tun_dev_free_security(void *security)
4649{
4650 kfree(security);
4651}
4652
Paul Mooreed6d76e2009-08-28 18:12:49 -04004653static int selinux_tun_dev_create(void)
4654{
4655 u32 sid = current_sid();
4656
4657 /* we aren't taking into account the "sockcreate" SID since the socket
4658 * that is being created here is not a socket in the traditional sense,
4659 * instead it is a private sock, accessible only to the kernel, and
4660 * representing a wide range of network traffic spanning multiple
4661 * connections unlike traditional sockets - check the TUN driver to
4662 * get a better understanding of why this socket is special */
4663
4664 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4665 NULL);
4666}
4667
Paul Moore5dbbaf22013-01-14 07:12:19 +00004668static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004669{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004670 struct tun_security_struct *tunsec = security;
4671
4672 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4673 TUN_SOCKET__ATTACH_QUEUE, NULL);
4674}
4675
4676static int selinux_tun_dev_attach(struct sock *sk, void *security)
4677{
4678 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004679 struct sk_security_struct *sksec = sk->sk_security;
4680
4681 /* we don't currently perform any NetLabel based labeling here and it
4682 * isn't clear that we would want to do so anyway; while we could apply
4683 * labeling without the support of the TUN user the resulting labeled
4684 * traffic from the other end of the connection would almost certainly
4685 * cause confusion to the TUN user that had no idea network labeling
4686 * protocols were being used */
4687
Paul Moore5dbbaf22013-01-14 07:12:19 +00004688 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004689 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004690
4691 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004692}
4693
Paul Moore5dbbaf22013-01-14 07:12:19 +00004694static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004695{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004696 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004697 u32 sid = current_sid();
4698 int err;
4699
Paul Moore5dbbaf22013-01-14 07:12:19 +00004700 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004701 TUN_SOCKET__RELABELFROM, NULL);
4702 if (err)
4703 return err;
4704 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4705 TUN_SOCKET__RELABELTO, NULL);
4706 if (err)
4707 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004708 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004709
4710 return 0;
4711}
4712
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4714{
4715 int err = 0;
4716 u32 perm;
4717 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004718 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004719
Hong zhi guo77954982013-03-27 06:49:35 +00004720 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721 err = -EINVAL;
4722 goto out;
4723 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004724 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004725
Paul Moore253bfae2010-04-22 14:46:19 -04004726 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 if (err) {
4728 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004729 printk(KERN_WARNING
4730 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004731 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4732 sk->sk_protocol, nlh->nlmsg_type,
4733 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004734 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 err = 0;
4736 }
4737
4738 /* Ignore */
4739 if (err == -ENOENT)
4740 err = 0;
4741 goto out;
4742 }
4743
Paul Moore253bfae2010-04-22 14:46:19 -04004744 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745out:
4746 return err;
4747}
4748
4749#ifdef CONFIG_NETFILTER
4750
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004751static unsigned int selinux_ip_forward(struct sk_buff *skb,
4752 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004753 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754{
Paul Mooredfaebe92008-10-10 10:16:31 -04004755 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004756 char *addrp;
4757 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004758 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004759 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004760 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004761 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004763
Paul Mooreeffad8d2008-01-29 08:49:27 -05004764 if (!selinux_policycap_netpeer)
4765 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004766
Paul Mooreeffad8d2008-01-29 08:49:27 -05004767 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004768 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004769 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004770 if (!secmark_active && !peerlbl_active)
4771 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004772
Paul Moored8395c82008-10-10 10:16:30 -04004773 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4774 return NF_DROP;
4775
Eric Paris50c205f2012-04-04 15:01:43 -04004776 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004777 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004778 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004779 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004780 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4781 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782
Paul Mooredfaebe92008-10-10 10:16:31 -04004783 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004784 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4785 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004786 if (err) {
4787 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004788 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004789 }
4790 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004791
4792 if (secmark_active)
4793 if (avc_has_perm(peer_sid, skb->secmark,
4794 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4795 return NF_DROP;
4796
Paul Moore948bf852008-10-10 10:16:32 -04004797 if (netlbl_active)
4798 /* we do this in the FORWARD path and not the POST_ROUTING
4799 * path because we want to make sure we apply the necessary
4800 * labeling before IPsec is applied so we can leverage AH
4801 * protection */
4802 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4803 return NF_DROP;
4804
Paul Mooreeffad8d2008-01-29 08:49:27 -05004805 return NF_ACCEPT;
4806}
4807
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004808static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004809 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004810 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004811{
David S. Miller238e54c2015-04-03 20:32:56 -04004812 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004813}
4814
4815#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004816static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004817 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004818 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004819{
David S. Miller238e54c2015-04-03 20:32:56 -04004820 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004821}
4822#endif /* IPV6 */
4823
Paul Moore948bf852008-10-10 10:16:32 -04004824static unsigned int selinux_ip_output(struct sk_buff *skb,
4825 u16 family)
4826{
Paul Moore47180062013-12-04 16:10:45 -05004827 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004828 u32 sid;
4829
4830 if (!netlbl_enabled())
4831 return NF_ACCEPT;
4832
4833 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4834 * because we want to make sure we apply the necessary labeling
4835 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004836 sk = skb->sk;
4837 if (sk) {
4838 struct sk_security_struct *sksec;
4839
4840 if (sk->sk_state == TCP_LISTEN)
4841 /* if the socket is the listening state then this
4842 * packet is a SYN-ACK packet which means it needs to
4843 * be labeled based on the connection/request_sock and
4844 * not the parent socket. unfortunately, we can't
4845 * lookup the request_sock yet as it isn't queued on
4846 * the parent socket until after the SYN-ACK is sent.
4847 * the "solution" is to simply pass the packet as-is
4848 * as any IP option based labeling should be copied
4849 * from the initial connection request (in the IP
4850 * layer). it is far from ideal, but until we get a
4851 * security label in the packet itself this is the
4852 * best we can do. */
4853 return NF_ACCEPT;
4854
4855 /* standard practice, label using the parent socket */
4856 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004857 sid = sksec->sid;
4858 } else
4859 sid = SECINITSID_KERNEL;
4860 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4861 return NF_DROP;
4862
4863 return NF_ACCEPT;
4864}
4865
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004866static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004867 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004868 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004869{
4870 return selinux_ip_output(skb, PF_INET);
4871}
4872
Paul Mooreeffad8d2008-01-29 08:49:27 -05004873static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4874 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004875 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004876{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004877 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004878 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004879 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004880 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004881 char *addrp;
4882 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004883
Paul Mooreeffad8d2008-01-29 08:49:27 -05004884 if (sk == NULL)
4885 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004886 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004887
Eric Paris50c205f2012-04-04 15:01:43 -04004888 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004889 ad.u.net = &net;
4890 ad.u.net->netif = ifindex;
4891 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004892 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4893 return NF_DROP;
4894
Paul Moore58bfbb52009-03-27 17:10:41 -04004895 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004896 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004897 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004898 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004899
Steffen Klassertb9679a72011-02-23 12:55:21 +01004900 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4901 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004902
Paul Mooreeffad8d2008-01-29 08:49:27 -05004903 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904}
4905
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004906static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4907 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004908 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004910 u32 secmark_perm;
4911 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004912 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004913 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004914 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004915 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004916 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004917 u8 secmark_active;
4918 u8 peerlbl_active;
4919
Paul Mooreeffad8d2008-01-29 08:49:27 -05004920 /* If any sort of compatibility mode is enabled then handoff processing
4921 * to the selinux_ip_postroute_compat() function to deal with the
4922 * special handling. We do this in an attempt to keep this function
4923 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004924 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004925 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004926
Paul Mooreeffad8d2008-01-29 08:49:27 -05004927 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004928 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004929 if (!secmark_active && !peerlbl_active)
4930 return NF_ACCEPT;
4931
Paul Mooreeffad8d2008-01-29 08:49:27 -05004932 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004933
Paul Mooreeffad8d2008-01-29 08:49:27 -05004934#ifdef CONFIG_XFRM
4935 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4936 * packet transformation so allow the packet to pass without any checks
4937 * since we'll have another chance to perform access control checks
4938 * when the packet is on it's final way out.
4939 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004940 * is NULL, in this case go ahead and apply access control.
4941 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4942 * TCP listening state we cannot wait until the XFRM processing
4943 * is done as we will miss out on the SA label if we do;
4944 * unfortunately, this means more work, but it is only once per
4945 * connection. */
4946 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4947 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004948 return NF_ACCEPT;
4949#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004950
Paul Moored8395c82008-10-10 10:16:30 -04004951 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05004952 /* Without an associated socket the packet is either coming
4953 * from the kernel or it is being forwarded; check the packet
4954 * to determine which and if the packet is being forwarded
4955 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004956 if (skb->skb_iif) {
4957 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004958 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004959 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004960 } else {
4961 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004962 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004963 }
Paul Moore446b8022013-12-04 16:10:51 -05004964 } else if (sk->sk_state == TCP_LISTEN) {
4965 /* Locally generated packet but the associated socket is in the
4966 * listening state which means this is a SYN-ACK packet. In
4967 * this particular case the correct security label is assigned
4968 * to the connection/request_sock but unfortunately we can't
4969 * query the request_sock as it isn't queued on the parent
4970 * socket until after the SYN-ACK packet is sent; the only
4971 * viable choice is to regenerate the label like we do in
4972 * selinux_inet_conn_request(). See also selinux_ip_output()
4973 * for similar problems. */
4974 u32 skb_sid;
4975 struct sk_security_struct *sksec = sk->sk_security;
4976 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4977 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05004978 /* At this point, if the returned skb peerlbl is SECSID_NULL
4979 * and the packet has been through at least one XFRM
4980 * transformation then we must be dealing with the "final"
4981 * form of labeled IPsec packet; since we've already applied
4982 * all of our access controls on this packet we can safely
4983 * pass the packet. */
4984 if (skb_sid == SECSID_NULL) {
4985 switch (family) {
4986 case PF_INET:
4987 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4988 return NF_ACCEPT;
4989 break;
4990 case PF_INET6:
4991 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4992 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04004993 break;
Paul Moorec0828e52013-12-10 14:58:01 -05004994 default:
4995 return NF_DROP_ERR(-ECONNREFUSED);
4996 }
4997 }
Paul Moore446b8022013-12-04 16:10:51 -05004998 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4999 return NF_DROP;
5000 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005001 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005002 /* Locally generated packet, fetch the security label from the
5003 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005004 struct sk_security_struct *sksec = sk->sk_security;
5005 peer_sid = sksec->sid;
5006 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005007 }
5008
Eric Paris50c205f2012-04-04 15:01:43 -04005009 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005010 ad.u.net = &net;
5011 ad.u.net->netif = ifindex;
5012 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005013 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005014 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005015
Paul Mooreeffad8d2008-01-29 08:49:27 -05005016 if (secmark_active)
5017 if (avc_has_perm(peer_sid, skb->secmark,
5018 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005019 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005020
5021 if (peerlbl_active) {
5022 u32 if_sid;
5023 u32 node_sid;
5024
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005025 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005026 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005027 if (avc_has_perm(peer_sid, if_sid,
5028 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005029 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005030
5031 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005032 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005033 if (avc_has_perm(peer_sid, node_sid,
5034 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005035 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005036 }
5037
5038 return NF_ACCEPT;
5039}
5040
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005041static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005042 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005043 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005044{
David S. Miller238e54c2015-04-03 20:32:56 -04005045 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046}
5047
5048#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005049static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005050 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005051 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052{
David S. Miller238e54c2015-04-03 20:32:56 -04005053 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005054}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055#endif /* IPV6 */
5056
5057#endif /* CONFIG_NETFILTER */
5058
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5060{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005061 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062}
5063
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064static int ipc_alloc_security(struct task_struct *task,
5065 struct kern_ipc_perm *perm,
5066 u16 sclass)
5067{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005069 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070
James Morris89d155e2005-10-30 14:59:21 -08005071 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072 if (!isec)
5073 return -ENOMEM;
5074
David Howells275bb412008-11-14 10:39:19 +11005075 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005077 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078 perm->security = isec;
5079
5080 return 0;
5081}
5082
5083static void ipc_free_security(struct kern_ipc_perm *perm)
5084{
5085 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086 perm->security = NULL;
5087 kfree(isec);
5088}
5089
5090static int msg_msg_alloc_security(struct msg_msg *msg)
5091{
5092 struct msg_security_struct *msec;
5093
James Morris89d155e2005-10-30 14:59:21 -08005094 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095 if (!msec)
5096 return -ENOMEM;
5097
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 msec->sid = SECINITSID_UNLABELED;
5099 msg->security = msec;
5100
5101 return 0;
5102}
5103
5104static void msg_msg_free_security(struct msg_msg *msg)
5105{
5106 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
5108 msg->security = NULL;
5109 kfree(msec);
5110}
5111
5112static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005113 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005116 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005117 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 isec = ipc_perms->security;
5120
Eric Paris50c205f2012-04-04 15:01:43 -04005121 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122 ad.u.ipc_id = ipc_perms->key;
5123
David Howells275bb412008-11-14 10:39:19 +11005124 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125}
5126
5127static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5128{
5129 return msg_msg_alloc_security(msg);
5130}
5131
5132static void selinux_msg_msg_free_security(struct msg_msg *msg)
5133{
5134 msg_msg_free_security(msg);
5135}
5136
5137/* message queue security operations */
5138static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5139{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005141 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005142 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143 int rc;
5144
5145 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5146 if (rc)
5147 return rc;
5148
Linus Torvalds1da177e2005-04-16 15:20:36 -07005149 isec = msq->q_perm.security;
5150
Eric Paris50c205f2012-04-04 15:01:43 -04005151 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005152 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153
David Howells275bb412008-11-14 10:39:19 +11005154 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155 MSGQ__CREATE, &ad);
5156 if (rc) {
5157 ipc_free_security(&msq->q_perm);
5158 return rc;
5159 }
5160 return 0;
5161}
5162
5163static void selinux_msg_queue_free_security(struct msg_queue *msq)
5164{
5165 ipc_free_security(&msq->q_perm);
5166}
5167
5168static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5169{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005171 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005172 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174 isec = msq->q_perm.security;
5175
Eric Paris50c205f2012-04-04 15:01:43 -04005176 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177 ad.u.ipc_id = msq->q_perm.key;
5178
David Howells275bb412008-11-14 10:39:19 +11005179 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 MSGQ__ASSOCIATE, &ad);
5181}
5182
5183static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5184{
5185 int err;
5186 int perms;
5187
Eric Paris828dfe12008-04-17 13:17:49 -04005188 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189 case IPC_INFO:
5190 case MSG_INFO:
5191 /* No specific object, just general system-wide information. */
5192 return task_has_system(current, SYSTEM__IPC_INFO);
5193 case IPC_STAT:
5194 case MSG_STAT:
5195 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5196 break;
5197 case IPC_SET:
5198 perms = MSGQ__SETATTR;
5199 break;
5200 case IPC_RMID:
5201 perms = MSGQ__DESTROY;
5202 break;
5203 default:
5204 return 0;
5205 }
5206
Stephen Smalley6af963f2005-05-01 08:58:39 -07005207 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208 return err;
5209}
5210
5211static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5212{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213 struct ipc_security_struct *isec;
5214 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005215 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005216 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 int rc;
5218
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219 isec = msq->q_perm.security;
5220 msec = msg->security;
5221
5222 /*
5223 * First time through, need to assign label to the message
5224 */
5225 if (msec->sid == SECINITSID_UNLABELED) {
5226 /*
5227 * Compute new sid based on current process and
5228 * message queue this message will be stored in
5229 */
David Howells275bb412008-11-14 10:39:19 +11005230 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005231 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232 if (rc)
5233 return rc;
5234 }
5235
Eric Paris50c205f2012-04-04 15:01:43 -04005236 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237 ad.u.ipc_id = msq->q_perm.key;
5238
5239 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005240 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 MSGQ__WRITE, &ad);
5242 if (!rc)
5243 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005244 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5245 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 if (!rc)
5247 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005248 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5249 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250
5251 return rc;
5252}
5253
5254static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5255 struct task_struct *target,
5256 long type, int mode)
5257{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 struct ipc_security_struct *isec;
5259 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005260 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005261 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 int rc;
5263
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264 isec = msq->q_perm.security;
5265 msec = msg->security;
5266
Eric Paris50c205f2012-04-04 15:01:43 -04005267 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005268 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
David Howells275bb412008-11-14 10:39:19 +11005270 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 SECCLASS_MSGQ, MSGQ__READ, &ad);
5272 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005273 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 SECCLASS_MSG, MSG__RECEIVE, &ad);
5275 return rc;
5276}
5277
5278/* Shared Memory security operations */
5279static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5280{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005282 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005283 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284 int rc;
5285
5286 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5287 if (rc)
5288 return rc;
5289
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290 isec = shp->shm_perm.security;
5291
Eric Paris50c205f2012-04-04 15:01:43 -04005292 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005293 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294
David Howells275bb412008-11-14 10:39:19 +11005295 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296 SHM__CREATE, &ad);
5297 if (rc) {
5298 ipc_free_security(&shp->shm_perm);
5299 return rc;
5300 }
5301 return 0;
5302}
5303
5304static void selinux_shm_free_security(struct shmid_kernel *shp)
5305{
5306 ipc_free_security(&shp->shm_perm);
5307}
5308
5309static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5310{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005312 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005313 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Linus Torvalds1da177e2005-04-16 15:20:36 -07005315 isec = shp->shm_perm.security;
5316
Eric Paris50c205f2012-04-04 15:01:43 -04005317 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318 ad.u.ipc_id = shp->shm_perm.key;
5319
David Howells275bb412008-11-14 10:39:19 +11005320 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 SHM__ASSOCIATE, &ad);
5322}
5323
5324/* Note, at this point, shp is locked down */
5325static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5326{
5327 int perms;
5328 int err;
5329
Eric Paris828dfe12008-04-17 13:17:49 -04005330 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331 case IPC_INFO:
5332 case SHM_INFO:
5333 /* No specific object, just general system-wide information. */
5334 return task_has_system(current, SYSTEM__IPC_INFO);
5335 case IPC_STAT:
5336 case SHM_STAT:
5337 perms = SHM__GETATTR | SHM__ASSOCIATE;
5338 break;
5339 case IPC_SET:
5340 perms = SHM__SETATTR;
5341 break;
5342 case SHM_LOCK:
5343 case SHM_UNLOCK:
5344 perms = SHM__LOCK;
5345 break;
5346 case IPC_RMID:
5347 perms = SHM__DESTROY;
5348 break;
5349 default:
5350 return 0;
5351 }
5352
Stephen Smalley6af963f2005-05-01 08:58:39 -07005353 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005354 return err;
5355}
5356
5357static int selinux_shm_shmat(struct shmid_kernel *shp,
5358 char __user *shmaddr, int shmflg)
5359{
5360 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361
5362 if (shmflg & SHM_RDONLY)
5363 perms = SHM__READ;
5364 else
5365 perms = SHM__READ | SHM__WRITE;
5366
Stephen Smalley6af963f2005-05-01 08:58:39 -07005367 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368}
5369
5370/* Semaphore security operations */
5371static int selinux_sem_alloc_security(struct sem_array *sma)
5372{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005374 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005375 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 int rc;
5377
5378 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5379 if (rc)
5380 return rc;
5381
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 isec = sma->sem_perm.security;
5383
Eric Paris50c205f2012-04-04 15:01:43 -04005384 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005385 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386
David Howells275bb412008-11-14 10:39:19 +11005387 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388 SEM__CREATE, &ad);
5389 if (rc) {
5390 ipc_free_security(&sma->sem_perm);
5391 return rc;
5392 }
5393 return 0;
5394}
5395
5396static void selinux_sem_free_security(struct sem_array *sma)
5397{
5398 ipc_free_security(&sma->sem_perm);
5399}
5400
5401static int selinux_sem_associate(struct sem_array *sma, int semflg)
5402{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005404 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005405 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407 isec = sma->sem_perm.security;
5408
Eric Paris50c205f2012-04-04 15:01:43 -04005409 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410 ad.u.ipc_id = sma->sem_perm.key;
5411
David Howells275bb412008-11-14 10:39:19 +11005412 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413 SEM__ASSOCIATE, &ad);
5414}
5415
5416/* Note, at this point, sma is locked down */
5417static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5418{
5419 int err;
5420 u32 perms;
5421
Eric Paris828dfe12008-04-17 13:17:49 -04005422 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423 case IPC_INFO:
5424 case SEM_INFO:
5425 /* No specific object, just general system-wide information. */
5426 return task_has_system(current, SYSTEM__IPC_INFO);
5427 case GETPID:
5428 case GETNCNT:
5429 case GETZCNT:
5430 perms = SEM__GETATTR;
5431 break;
5432 case GETVAL:
5433 case GETALL:
5434 perms = SEM__READ;
5435 break;
5436 case SETVAL:
5437 case SETALL:
5438 perms = SEM__WRITE;
5439 break;
5440 case IPC_RMID:
5441 perms = SEM__DESTROY;
5442 break;
5443 case IPC_SET:
5444 perms = SEM__SETATTR;
5445 break;
5446 case IPC_STAT:
5447 case SEM_STAT:
5448 perms = SEM__GETATTR | SEM__ASSOCIATE;
5449 break;
5450 default:
5451 return 0;
5452 }
5453
Stephen Smalley6af963f2005-05-01 08:58:39 -07005454 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455 return err;
5456}
5457
5458static int selinux_sem_semop(struct sem_array *sma,
5459 struct sembuf *sops, unsigned nsops, int alter)
5460{
5461 u32 perms;
5462
5463 if (alter)
5464 perms = SEM__READ | SEM__WRITE;
5465 else
5466 perms = SEM__READ;
5467
Stephen Smalley6af963f2005-05-01 08:58:39 -07005468 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469}
5470
5471static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5472{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473 u32 av = 0;
5474
Linus Torvalds1da177e2005-04-16 15:20:36 -07005475 av = 0;
5476 if (flag & S_IRUGO)
5477 av |= IPC__UNIX_READ;
5478 if (flag & S_IWUGO)
5479 av |= IPC__UNIX_WRITE;
5480
5481 if (av == 0)
5482 return 0;
5483
Stephen Smalley6af963f2005-05-01 08:58:39 -07005484 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005485}
5486
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005487static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5488{
5489 struct ipc_security_struct *isec = ipcp->security;
5490 *secid = isec->sid;
5491}
5492
Eric Paris828dfe12008-04-17 13:17:49 -04005493static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494{
5495 if (inode)
5496 inode_doinit_with_dentry(inode, dentry);
5497}
5498
5499static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005500 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501{
David Howells275bb412008-11-14 10:39:19 +11005502 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005503 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005505 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506
5507 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005508 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509 if (error)
5510 return error;
5511 }
5512
David Howells275bb412008-11-14 10:39:19 +11005513 rcu_read_lock();
5514 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515
5516 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005517 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005519 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005521 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005523 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005524 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005525 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005526 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005527 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528 else
David Howells275bb412008-11-14 10:39:19 +11005529 goto invalid;
5530 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531
5532 if (!sid)
5533 return 0;
5534
Al Viro04ff9702007-03-12 16:17:58 +00005535 error = security_sid_to_context(sid, value, &len);
5536 if (error)
5537 return error;
5538 return len;
David Howells275bb412008-11-14 10:39:19 +11005539
5540invalid:
5541 rcu_read_unlock();
5542 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543}
5544
5545static int selinux_setprocattr(struct task_struct *p,
5546 char *name, void *value, size_t size)
5547{
5548 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005549 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005550 struct cred *new;
5551 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 int error;
5553 char *str = value;
5554
5555 if (current != p) {
5556 /* SELinux only allows a process to change its own
5557 security attributes. */
5558 return -EACCES;
5559 }
5560
5561 /*
5562 * Basic control over ability to set these attributes at all.
5563 * current == p, but we'll pass them separately in case the
5564 * above restriction is ever removed.
5565 */
5566 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005567 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005569 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005570 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005571 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005572 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005573 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005575 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576 else
5577 error = -EINVAL;
5578 if (error)
5579 return error;
5580
5581 /* Obtain a SID for the context, if one was specified. */
5582 if (size && str[1] && str[1] != '\n') {
5583 if (str[size-1] == '\n') {
5584 str[size-1] = 0;
5585 size--;
5586 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005587 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005588 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005589 if (!capable(CAP_MAC_ADMIN)) {
5590 struct audit_buffer *ab;
5591 size_t audit_size;
5592
5593 /* We strip a nul only if it is at the end, otherwise the
5594 * context contains a nul and we should audit that */
5595 if (str[size - 1] == '\0')
5596 audit_size = size - 1;
5597 else
5598 audit_size = size;
5599 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5600 audit_log_format(ab, "op=fscreate invalid_context=");
5601 audit_log_n_untrustedstring(ab, value, audit_size);
5602 audit_log_end(ab);
5603
Stephen Smalley12b29f32008-05-07 13:03:20 -04005604 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005605 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005606 error = security_context_to_sid_force(value, size,
5607 &sid);
5608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 if (error)
5610 return error;
5611 }
5612
David Howellsd84f4f92008-11-14 10:39:23 +11005613 new = prepare_creds();
5614 if (!new)
5615 return -ENOMEM;
5616
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 /* Permission checking based on the specified context is
5618 performed during the actual operation (execve,
5619 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005620 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621 checks and may_create for the file creation checks. The
5622 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005623 tsec = new->security;
5624 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005626 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005628 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005629 error = may_create_key(sid, p);
5630 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005631 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005632 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005633 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005634 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005635 } else if (!strcmp(name, "current")) {
5636 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005638 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005639
David Howellsd84f4f92008-11-14 10:39:23 +11005640 /* Only allow single threaded processes to change context */
5641 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005642 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005643 error = security_bounded_transition(tsec->sid, sid);
5644 if (error)
5645 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
5648 /* Check permissions for the transition. */
5649 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005650 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005652 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653
5654 /* Check for ptracing, and update the task SID if ok.
5655 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005656 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005657 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005658 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005659 if (tracer)
5660 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005661 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662
David Howellsd84f4f92008-11-14 10:39:23 +11005663 if (tracer) {
5664 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5665 PROCESS__PTRACE, NULL);
5666 if (error)
5667 goto abort_change;
5668 }
5669
5670 tsec->sid = sid;
5671 } else {
5672 error = -EINVAL;
5673 goto abort_change;
5674 }
5675
5676 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005678
5679abort_change:
5680 abort_creds(new);
5681 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682}
5683
David Quigley746df9b2013-05-22 12:50:35 -04005684static int selinux_ismaclabel(const char *name)
5685{
5686 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5687}
5688
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005689static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5690{
5691 return security_sid_to_context(secid, secdata, seclen);
5692}
5693
David Howells7bf570d2008-04-29 20:52:51 +01005694static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005695{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005696 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005697}
5698
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005699static void selinux_release_secctx(char *secdata, u32 seclen)
5700{
Paul Moore088999e2007-08-01 11:12:58 -04005701 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005702}
5703
David P. Quigley1ee65e32009-09-03 14:25:57 -04005704/*
5705 * called with inode->i_mutex locked
5706 */
5707static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5708{
5709 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5710}
5711
5712/*
5713 * called with inode->i_mutex locked
5714 */
5715static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5716{
5717 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5718}
5719
5720static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5721{
5722 int len = 0;
5723 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5724 ctx, true);
5725 if (len < 0)
5726 return len;
5727 *ctxlen = len;
5728 return 0;
5729}
Michael LeMayd7200242006-06-22 14:47:17 -07005730#ifdef CONFIG_KEYS
5731
David Howellsd84f4f92008-11-14 10:39:23 +11005732static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005733 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005734{
David Howellsd84f4f92008-11-14 10:39:23 +11005735 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005736 struct key_security_struct *ksec;
5737
5738 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5739 if (!ksec)
5740 return -ENOMEM;
5741
David Howellsd84f4f92008-11-14 10:39:23 +11005742 tsec = cred->security;
5743 if (tsec->keycreate_sid)
5744 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005745 else
David Howellsd84f4f92008-11-14 10:39:23 +11005746 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005747
David Howells275bb412008-11-14 10:39:19 +11005748 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005749 return 0;
5750}
5751
5752static void selinux_key_free(struct key *k)
5753{
5754 struct key_security_struct *ksec = k->security;
5755
5756 k->security = NULL;
5757 kfree(ksec);
5758}
5759
5760static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005761 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005762 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005763{
5764 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005765 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005766 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005767
5768 /* if no specific permissions are requested, we skip the
5769 permission check. No serious, additional covert channels
5770 appear to be created. */
5771 if (perm == 0)
5772 return 0;
5773
David Howellsd84f4f92008-11-14 10:39:23 +11005774 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005775
5776 key = key_ref_to_ptr(key_ref);
5777 ksec = key->security;
5778
5779 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005780}
5781
David Howells70a5bb72008-04-29 01:01:26 -07005782static int selinux_key_getsecurity(struct key *key, char **_buffer)
5783{
5784 struct key_security_struct *ksec = key->security;
5785 char *context = NULL;
5786 unsigned len;
5787 int rc;
5788
5789 rc = security_sid_to_context(ksec->sid, &context, &len);
5790 if (!rc)
5791 rc = len;
5792 *_buffer = context;
5793 return rc;
5794}
5795
Michael LeMayd7200242006-06-22 14:47:17 -07005796#endif
5797
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005798static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005799 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5800 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5801 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5802 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Stephen Smalley79af7302015-01-21 10:54:10 -05005803
Casey Schauflere20b0432015-05-02 15:11:36 -07005804 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5805 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5806 LSM_HOOK_INIT(capget, selinux_capget),
5807 LSM_HOOK_INIT(capset, selinux_capset),
5808 LSM_HOOK_INIT(capable, selinux_capable),
5809 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5810 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5811 LSM_HOOK_INIT(syslog, selinux_syslog),
5812 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813
Casey Schauflere20b0432015-05-02 15:11:36 -07005814 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815
Casey Schauflere20b0432015-05-02 15:11:36 -07005816 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5817 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5818 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5819 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820
Casey Schauflere20b0432015-05-02 15:11:36 -07005821 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5822 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5823 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5824 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5825 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5826 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5827 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5828 LSM_HOOK_INIT(sb_mount, selinux_mount),
5829 LSM_HOOK_INIT(sb_umount, selinux_umount),
5830 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5831 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5832 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Eric Parise0007522008-03-05 10:31:54 -05005833
Casey Schauflere20b0432015-05-02 15:11:36 -07005834 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835
Casey Schauflere20b0432015-05-02 15:11:36 -07005836 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5837 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5838 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5839 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5840 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5841 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5842 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5843 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5844 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5845 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5846 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5847 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5848 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5849 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5850 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5851 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5852 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5853 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5854 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5855 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5856 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5857 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5858 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5859 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5860 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861
Casey Schauflere20b0432015-05-02 15:11:36 -07005862 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5863 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5864 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5865 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5866 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5867 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5868 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5869 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5870 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5871 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5872 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5873 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Casey Schauflere20b0432015-05-02 15:11:36 -07005875 LSM_HOOK_INIT(file_open, selinux_file_open),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005876
Casey Schauflere20b0432015-05-02 15:11:36 -07005877 LSM_HOOK_INIT(task_create, selinux_task_create),
5878 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5879 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5880 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5881 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5882 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5883 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5884 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5885 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5886 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5887 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5888 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5889 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5890 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5891 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5892 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5893 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5894 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5895 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5896 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5897 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5898 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Casey Schauflere20b0432015-05-02 15:11:36 -07005900 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5901 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902
Casey Schauflere20b0432015-05-02 15:11:36 -07005903 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5904 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905
Casey Schauflere20b0432015-05-02 15:11:36 -07005906 LSM_HOOK_INIT(msg_queue_alloc_security,
5907 selinux_msg_queue_alloc_security),
5908 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5909 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5910 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5911 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5912 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913
Casey Schauflere20b0432015-05-02 15:11:36 -07005914 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5915 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5916 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5917 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5918 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
Casey Schauflere20b0432015-05-02 15:11:36 -07005920 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5921 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5922 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5923 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5924 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925
Casey Schauflere20b0432015-05-02 15:11:36 -07005926 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
Casey Schauflere20b0432015-05-02 15:11:36 -07005928 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5929 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
Casey Schauflere20b0432015-05-02 15:11:36 -07005931 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5932 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5933 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5934 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5935 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5936 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5937 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005938
Casey Schauflere20b0432015-05-02 15:11:36 -07005939 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
5940 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Casey Schauflere20b0432015-05-02 15:11:36 -07005942 LSM_HOOK_INIT(socket_create, selinux_socket_create),
5943 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
5944 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
5945 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
5946 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
5947 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
5948 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
5949 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
5950 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
5951 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
5952 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
5953 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
5954 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
5955 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
5956 LSM_HOOK_INIT(socket_getpeersec_stream,
5957 selinux_socket_getpeersec_stream),
5958 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
5959 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
5960 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
5961 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
5962 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
5963 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
5964 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
5965 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
5966 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
5967 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
5968 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
5969 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
5970 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
5971 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
5972 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
5973 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
5974 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
5975 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
5976 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005977
5978#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07005979 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
5980 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
5981 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
5982 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
5983 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
5984 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
5985 selinux_xfrm_state_alloc_acquire),
5986 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
5987 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
5988 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
5989 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
5990 selinux_xfrm_state_pol_flow_match),
5991 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005993
5994#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07005995 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
5996 LSM_HOOK_INIT(key_free, selinux_key_free),
5997 LSM_HOOK_INIT(key_permission, selinux_key_permission),
5998 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07005999#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006000
6001#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006002 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6003 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6004 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6005 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006006#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006007};
6008
6009static __init int selinux_init(void)
6010{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006011 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006012 selinux_enabled = 0;
6013 return 0;
6014 }
6015
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016 if (!selinux_enabled) {
6017 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6018 return 0;
6019 }
6020
6021 printk(KERN_INFO "SELinux: Initializing.\n");
6022
6023 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006024 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006026 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6027
James Morris7cae7e22006-03-22 00:09:22 -08006028 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6029 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006030 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031 avc_init();
6032
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006033 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Paul Moore615e51f2014-06-26 14:33:56 -04006035 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6036 panic("SELinux: Unable to register AVC netcache callback\n");
6037
Eric Paris828dfe12008-04-17 13:17:49 -04006038 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006039 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006040 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006041 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006042
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043 return 0;
6044}
6045
Al Viroe8c26252010-03-23 06:36:54 -04006046static void delayed_superblock_init(struct super_block *sb, void *unused)
6047{
6048 superblock_doinit(sb, NULL);
6049}
6050
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051void selinux_complete_init(void)
6052{
Eric Parisfadcdb42007-02-22 18:11:31 -05006053 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054
6055 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006056 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006057 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058}
6059
6060/* SELinux requires early initialization in order to label
6061 all processes and objects when they are created. */
6062security_initcall(selinux_init);
6063
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006064#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Jiri Pirko25db6be2014-09-03 17:42:13 +02006066static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006067 {
6068 .hook = selinux_ipv4_postroute,
6069 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006070 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006071 .hooknum = NF_INET_POST_ROUTING,
6072 .priority = NF_IP_PRI_SELINUX_LAST,
6073 },
6074 {
6075 .hook = selinux_ipv4_forward,
6076 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006077 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006078 .hooknum = NF_INET_FORWARD,
6079 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006080 },
6081 {
6082 .hook = selinux_ipv4_output,
6083 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006084 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006085 .hooknum = NF_INET_LOCAL_OUT,
6086 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006087 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006089 {
6090 .hook = selinux_ipv6_postroute,
6091 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006092 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006093 .hooknum = NF_INET_POST_ROUTING,
6094 .priority = NF_IP6_PRI_SELINUX_LAST,
6095 },
6096 {
6097 .hook = selinux_ipv6_forward,
6098 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006099 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006100 .hooknum = NF_INET_FORWARD,
6101 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006102 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006104};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105
6106static int __init selinux_nf_ip_init(void)
6107{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006108 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109
6110 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006111 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006112
6113 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6114
Jiri Pirko25db6be2014-09-03 17:42:13 +02006115 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006116 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006117 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
Jiri Pirko25db6be2014-09-03 17:42:13 +02006119 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120}
6121
6122__initcall(selinux_nf_ip_init);
6123
6124#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6125static void selinux_nf_ip_exit(void)
6126{
Eric Parisfadcdb42007-02-22 18:11:31 -05006127 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128
Jiri Pirko25db6be2014-09-03 17:42:13 +02006129 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130}
6131#endif
6132
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006133#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134
6135#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6136#define selinux_nf_ip_exit()
6137#endif
6138
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006139#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140
6141#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006142static int selinux_disabled;
6143
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144int selinux_disable(void)
6145{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146 if (ss_initialized) {
6147 /* Not permitted after initial policy load. */
6148 return -EINVAL;
6149 }
6150
6151 if (selinux_disabled) {
6152 /* Only do this once. */
6153 return -EINVAL;
6154 }
6155
6156 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6157
6158 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006159 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006161 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162
Eric Parisaf8ff042009-09-20 21:23:01 -04006163 /* Try to destroy the avc node cache */
6164 avc_disable();
6165
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166 /* Unregister netfilter hooks. */
6167 selinux_nf_ip_exit();
6168
6169 /* Unregister selinuxfs. */
6170 exit_sel_fs();
6171
6172 return 0;
6173}
6174#endif