xref: /OK3568_Linux_fs/kernel/security/selinux/hooks.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  NSA Security-Enhanced Linux (SELinux) security module
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  This file contains the SELinux hook function implementations.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Authors:  Stephen Smalley, <sds@tycho.nsa.gov>
8*4882a593Smuzhiyun  *	      Chris Vance, <cvance@nai.com>
9*4882a593Smuzhiyun  *	      Wayne Salamon, <wsalamon@nai.com>
10*4882a593Smuzhiyun  *	      James Morris <jmorris@redhat.com>
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
13*4882a593Smuzhiyun  *  Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
14*4882a593Smuzhiyun  *					   Eric Paris <eparis@redhat.com>
15*4882a593Smuzhiyun  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
16*4882a593Smuzhiyun  *			    <dgoeddel@trustedcs.com>
17*4882a593Smuzhiyun  *  Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
18*4882a593Smuzhiyun  *	Paul Moore <paul@paul-moore.com>
19*4882a593Smuzhiyun  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
20*4882a593Smuzhiyun  *		       Yuichi Nakamura <ynakam@hitachisoft.jp>
21*4882a593Smuzhiyun  *  Copyright (C) 2016 Mellanox Technologies
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <linux/init.h>
25*4882a593Smuzhiyun #include <linux/kd.h>
26*4882a593Smuzhiyun #include <linux/kernel.h>
27*4882a593Smuzhiyun #include <linux/kernel_read_file.h>
28*4882a593Smuzhiyun #include <linux/tracehook.h>
29*4882a593Smuzhiyun #include <linux/errno.h>
30*4882a593Smuzhiyun #include <linux/sched/signal.h>
31*4882a593Smuzhiyun #include <linux/sched/task.h>
32*4882a593Smuzhiyun #include <linux/lsm_hooks.h>
33*4882a593Smuzhiyun #include <linux/xattr.h>
34*4882a593Smuzhiyun #include <linux/capability.h>
35*4882a593Smuzhiyun #include <linux/unistd.h>
36*4882a593Smuzhiyun #include <linux/mm.h>
37*4882a593Smuzhiyun #include <linux/mman.h>
38*4882a593Smuzhiyun #include <linux/slab.h>
39*4882a593Smuzhiyun #include <linux/pagemap.h>
40*4882a593Smuzhiyun #include <linux/proc_fs.h>
41*4882a593Smuzhiyun #include <linux/swap.h>
42*4882a593Smuzhiyun #include <linux/spinlock.h>
43*4882a593Smuzhiyun #include <linux/syscalls.h>
44*4882a593Smuzhiyun #include <linux/dcache.h>
45*4882a593Smuzhiyun #include <linux/file.h>
46*4882a593Smuzhiyun #include <linux/fdtable.h>
47*4882a593Smuzhiyun #include <linux/namei.h>
48*4882a593Smuzhiyun #include <linux/mount.h>
49*4882a593Smuzhiyun #include <linux/fs_context.h>
50*4882a593Smuzhiyun #include <linux/fs_parser.h>
51*4882a593Smuzhiyun #include <linux/netfilter_ipv4.h>
52*4882a593Smuzhiyun #include <linux/netfilter_ipv6.h>
53*4882a593Smuzhiyun #include <linux/tty.h>
54*4882a593Smuzhiyun #include <net/icmp.h>
55*4882a593Smuzhiyun #include <net/ip.h>		/* for local_port_range[] */
56*4882a593Smuzhiyun #include <net/tcp.h>		/* struct or_callable used in sock_rcv_skb */
57*4882a593Smuzhiyun #include <net/inet_connection_sock.h>
58*4882a593Smuzhiyun #include <net/net_namespace.h>
59*4882a593Smuzhiyun #include <net/netlabel.h>
60*4882a593Smuzhiyun #include <linux/uaccess.h>
61*4882a593Smuzhiyun #include <asm/ioctls.h>
62*4882a593Smuzhiyun #include <linux/atomic.h>
63*4882a593Smuzhiyun #include <linux/bitops.h>
64*4882a593Smuzhiyun #include <linux/interrupt.h>
65*4882a593Smuzhiyun #include <linux/netdevice.h>	/* for network interface checks */
66*4882a593Smuzhiyun #include <net/netlink.h>
67*4882a593Smuzhiyun #include <linux/tcp.h>
68*4882a593Smuzhiyun #include <linux/udp.h>
69*4882a593Smuzhiyun #include <linux/dccp.h>
70*4882a593Smuzhiyun #include <linux/sctp.h>
71*4882a593Smuzhiyun #include <net/sctp/structs.h>
72*4882a593Smuzhiyun #include <linux/quota.h>
73*4882a593Smuzhiyun #include <linux/un.h>		/* for Unix socket types */
74*4882a593Smuzhiyun #include <net/af_unix.h>	/* for Unix socket types */
75*4882a593Smuzhiyun #include <linux/parser.h>
76*4882a593Smuzhiyun #include <linux/nfs_mount.h>
77*4882a593Smuzhiyun #include <net/ipv6.h>
78*4882a593Smuzhiyun #include <linux/hugetlb.h>
79*4882a593Smuzhiyun #include <linux/personality.h>
80*4882a593Smuzhiyun #include <linux/audit.h>
81*4882a593Smuzhiyun #include <linux/string.h>
82*4882a593Smuzhiyun #include <linux/mutex.h>
83*4882a593Smuzhiyun #include <linux/posix-timers.h>
84*4882a593Smuzhiyun #include <linux/syslog.h>
85*4882a593Smuzhiyun #include <linux/user_namespace.h>
86*4882a593Smuzhiyun #include <linux/export.h>
87*4882a593Smuzhiyun #include <linux/msg.h>
88*4882a593Smuzhiyun #include <linux/shm.h>
89*4882a593Smuzhiyun #include <linux/bpf.h>
90*4882a593Smuzhiyun #include <linux/kernfs.h>
91*4882a593Smuzhiyun #include <linux/stringhash.h>	/* for hashlen_string() */
92*4882a593Smuzhiyun #include <uapi/linux/mount.h>
93*4882a593Smuzhiyun #include <linux/fsnotify.h>
94*4882a593Smuzhiyun #include <linux/fanotify.h>
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #include "avc.h"
97*4882a593Smuzhiyun #include "objsec.h"
98*4882a593Smuzhiyun #include "netif.h"
99*4882a593Smuzhiyun #include "netnode.h"
100*4882a593Smuzhiyun #include "netport.h"
101*4882a593Smuzhiyun #include "ibpkey.h"
102*4882a593Smuzhiyun #include "xfrm.h"
103*4882a593Smuzhiyun #include "netlabel.h"
104*4882a593Smuzhiyun #include "audit.h"
105*4882a593Smuzhiyun #include "avc_ss.h"
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun struct selinux_state selinux_state;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /* SECMARK reference count */
110*4882a593Smuzhiyun static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
113*4882a593Smuzhiyun static int selinux_enforcing_boot __initdata;
114*4882a593Smuzhiyun 
enforcing_setup(char * str)115*4882a593Smuzhiyun static int __init enforcing_setup(char *str)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	unsigned long enforcing;
118*4882a593Smuzhiyun 	if (!kstrtoul(str, 0, &enforcing))
119*4882a593Smuzhiyun 		selinux_enforcing_boot = enforcing ? 1 : 0;
120*4882a593Smuzhiyun 	return 1;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun __setup("enforcing=", enforcing_setup);
123*4882a593Smuzhiyun #else
124*4882a593Smuzhiyun #define selinux_enforcing_boot 1
125*4882a593Smuzhiyun #endif
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun int selinux_enabled_boot __initdata = 1;
128*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
selinux_enabled_setup(char * str)129*4882a593Smuzhiyun static int __init selinux_enabled_setup(char *str)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	unsigned long enabled;
132*4882a593Smuzhiyun 	if (!kstrtoul(str, 0, &enabled))
133*4882a593Smuzhiyun 		selinux_enabled_boot = enabled ? 1 : 0;
134*4882a593Smuzhiyun 	return 1;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun __setup("selinux=", selinux_enabled_setup);
137*4882a593Smuzhiyun #endif
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static unsigned int selinux_checkreqprot_boot =
140*4882a593Smuzhiyun 	CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
141*4882a593Smuzhiyun 
checkreqprot_setup(char * str)142*4882a593Smuzhiyun static int __init checkreqprot_setup(char *str)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	unsigned long checkreqprot;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (!kstrtoul(str, 0, &checkreqprot)) {
147*4882a593Smuzhiyun 		selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
148*4882a593Smuzhiyun 		if (checkreqprot)
149*4882a593Smuzhiyun 			pr_warn("SELinux: checkreqprot set to 1 via kernel parameter.  This is deprecated and will be rejected in a future kernel release.\n");
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 	return 1;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun __setup("checkreqprot=", checkreqprot_setup);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /**
156*4882a593Smuzhiyun  * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
157*4882a593Smuzhiyun  *
158*4882a593Smuzhiyun  * Description:
159*4882a593Smuzhiyun  * This function checks the SECMARK reference counter to see if any SECMARK
160*4882a593Smuzhiyun  * targets are currently configured, if the reference counter is greater than
161*4882a593Smuzhiyun  * zero SECMARK is considered to be enabled.  Returns true (1) if SECMARK is
162*4882a593Smuzhiyun  * enabled, false (0) if SECMARK is disabled.  If the always_check_network
163*4882a593Smuzhiyun  * policy capability is enabled, SECMARK is always considered enabled.
164*4882a593Smuzhiyun  *
165*4882a593Smuzhiyun  */
selinux_secmark_enabled(void)166*4882a593Smuzhiyun static int selinux_secmark_enabled(void)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	return (selinux_policycap_alwaysnetwork() ||
169*4882a593Smuzhiyun 		atomic_read(&selinux_secmark_refcount));
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun /**
173*4882a593Smuzhiyun  * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
174*4882a593Smuzhiyun  *
175*4882a593Smuzhiyun  * Description:
176*4882a593Smuzhiyun  * This function checks if NetLabel or labeled IPSEC is enabled.  Returns true
177*4882a593Smuzhiyun  * (1) if any are enabled or false (0) if neither are enabled.  If the
178*4882a593Smuzhiyun  * always_check_network policy capability is enabled, peer labeling
179*4882a593Smuzhiyun  * is always considered enabled.
180*4882a593Smuzhiyun  *
181*4882a593Smuzhiyun  */
selinux_peerlbl_enabled(void)182*4882a593Smuzhiyun static int selinux_peerlbl_enabled(void)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	return (selinux_policycap_alwaysnetwork() ||
185*4882a593Smuzhiyun 		netlbl_enabled() || selinux_xfrm_enabled());
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
selinux_netcache_avc_callback(u32 event)188*4882a593Smuzhiyun static int selinux_netcache_avc_callback(u32 event)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	if (event == AVC_CALLBACK_RESET) {
191*4882a593Smuzhiyun 		sel_netif_flush();
192*4882a593Smuzhiyun 		sel_netnode_flush();
193*4882a593Smuzhiyun 		sel_netport_flush();
194*4882a593Smuzhiyun 		synchronize_net();
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 	return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
selinux_lsm_notifier_avc_callback(u32 event)199*4882a593Smuzhiyun static int selinux_lsm_notifier_avc_callback(u32 event)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	if (event == AVC_CALLBACK_RESET) {
202*4882a593Smuzhiyun 		sel_ib_pkey_flush();
203*4882a593Smuzhiyun 		call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun /*
210*4882a593Smuzhiyun  * initialise the security for the init task
211*4882a593Smuzhiyun  */
cred_init_security(void)212*4882a593Smuzhiyun static void cred_init_security(void)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct cred *cred = (struct cred *) current->real_cred;
215*4882a593Smuzhiyun 	struct task_security_struct *tsec;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	tsec = selinux_cred(cred);
218*4882a593Smuzhiyun 	tsec->osid = tsec->sid = SECINITSID_KERNEL;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun  * get the security ID of a set of credentials
223*4882a593Smuzhiyun  */
cred_sid(const struct cred * cred)224*4882a593Smuzhiyun static inline u32 cred_sid(const struct cred *cred)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	const struct task_security_struct *tsec;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	tsec = selinux_cred(cred);
229*4882a593Smuzhiyun 	return tsec->sid;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /*
233*4882a593Smuzhiyun  * get the objective security ID of a task
234*4882a593Smuzhiyun  */
task_sid(const struct task_struct * task)235*4882a593Smuzhiyun static inline u32 task_sid(const struct task_struct *task)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	u32 sid;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	rcu_read_lock();
240*4882a593Smuzhiyun 	sid = cred_sid(__task_cred(task));
241*4882a593Smuzhiyun 	rcu_read_unlock();
242*4882a593Smuzhiyun 	return sid;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun /*
248*4882a593Smuzhiyun  * Try reloading inode security labels that have been marked as invalid.  The
249*4882a593Smuzhiyun  * @may_sleep parameter indicates when sleeping and thus reloading labels is
250*4882a593Smuzhiyun  * allowed; when set to false, returns -ECHILD when the label is
251*4882a593Smuzhiyun  * invalid.  The @dentry parameter should be set to a dentry of the inode.
252*4882a593Smuzhiyun  */
__inode_security_revalidate(struct inode * inode,struct dentry * dentry,bool may_sleep)253*4882a593Smuzhiyun static int __inode_security_revalidate(struct inode *inode,
254*4882a593Smuzhiyun 				       struct dentry *dentry,
255*4882a593Smuzhiyun 				       bool may_sleep)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	might_sleep_if(may_sleep);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	if (selinux_initialized(&selinux_state) &&
262*4882a593Smuzhiyun 	    isec->initialized != LABEL_INITIALIZED) {
263*4882a593Smuzhiyun 		if (!may_sleep)
264*4882a593Smuzhiyun 			return -ECHILD;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 		/*
267*4882a593Smuzhiyun 		 * Try reloading the inode security label.  This will fail if
268*4882a593Smuzhiyun 		 * @opt_dentry is NULL and no dentry for this inode can be
269*4882a593Smuzhiyun 		 * found; in that case, continue using the old label.
270*4882a593Smuzhiyun 		 */
271*4882a593Smuzhiyun 		inode_doinit_with_dentry(inode, dentry);
272*4882a593Smuzhiyun 	}
273*4882a593Smuzhiyun 	return 0;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
inode_security_novalidate(struct inode * inode)276*4882a593Smuzhiyun static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	return selinux_inode(inode);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
inode_security_rcu(struct inode * inode,bool rcu)281*4882a593Smuzhiyun static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	int error;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	error = __inode_security_revalidate(inode, NULL, !rcu);
286*4882a593Smuzhiyun 	if (error)
287*4882a593Smuzhiyun 		return ERR_PTR(error);
288*4882a593Smuzhiyun 	return selinux_inode(inode);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /*
292*4882a593Smuzhiyun  * Get the security label of an inode.
293*4882a593Smuzhiyun  */
inode_security(struct inode * inode)294*4882a593Smuzhiyun static struct inode_security_struct *inode_security(struct inode *inode)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	__inode_security_revalidate(inode, NULL, true);
297*4882a593Smuzhiyun 	return selinux_inode(inode);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
backing_inode_security_novalidate(struct dentry * dentry)300*4882a593Smuzhiyun static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return selinux_inode(inode);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun /*
308*4882a593Smuzhiyun  * Get the security label of a dentry's backing inode.
309*4882a593Smuzhiyun  */
backing_inode_security(struct dentry * dentry)310*4882a593Smuzhiyun static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	__inode_security_revalidate(inode, dentry, true);
315*4882a593Smuzhiyun 	return selinux_inode(inode);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
inode_free_security(struct inode * inode)318*4882a593Smuzhiyun static void inode_free_security(struct inode *inode)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
321*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (!isec)
324*4882a593Smuzhiyun 		return;
325*4882a593Smuzhiyun 	sbsec = inode->i_sb->s_security;
326*4882a593Smuzhiyun 	/*
327*4882a593Smuzhiyun 	 * As not all inode security structures are in a list, we check for
328*4882a593Smuzhiyun 	 * empty list outside of the lock to make sure that we won't waste
329*4882a593Smuzhiyun 	 * time taking a lock doing nothing.
330*4882a593Smuzhiyun 	 *
331*4882a593Smuzhiyun 	 * The list_del_init() function can be safely called more than once.
332*4882a593Smuzhiyun 	 * It should not be possible for this function to be called with
333*4882a593Smuzhiyun 	 * concurrent list_add(), but for better safety against future changes
334*4882a593Smuzhiyun 	 * in the code, we use list_empty_careful() here.
335*4882a593Smuzhiyun 	 */
336*4882a593Smuzhiyun 	if (!list_empty_careful(&isec->list)) {
337*4882a593Smuzhiyun 		spin_lock(&sbsec->isec_lock);
338*4882a593Smuzhiyun 		list_del_init(&isec->list);
339*4882a593Smuzhiyun 		spin_unlock(&sbsec->isec_lock);
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
superblock_free_security(struct super_block * sb)343*4882a593Smuzhiyun static void superblock_free_security(struct super_block *sb)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
346*4882a593Smuzhiyun 	sb->s_security = NULL;
347*4882a593Smuzhiyun 	kfree(sbsec);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun struct selinux_mnt_opts {
351*4882a593Smuzhiyun 	const char *fscontext, *context, *rootcontext, *defcontext;
352*4882a593Smuzhiyun };
353*4882a593Smuzhiyun 
selinux_free_mnt_opts(void * mnt_opts)354*4882a593Smuzhiyun static void selinux_free_mnt_opts(void *mnt_opts)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	struct selinux_mnt_opts *opts = mnt_opts;
357*4882a593Smuzhiyun 	kfree(opts->fscontext);
358*4882a593Smuzhiyun 	kfree(opts->context);
359*4882a593Smuzhiyun 	kfree(opts->rootcontext);
360*4882a593Smuzhiyun 	kfree(opts->defcontext);
361*4882a593Smuzhiyun 	kfree(opts);
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun enum {
365*4882a593Smuzhiyun 	Opt_error = -1,
366*4882a593Smuzhiyun 	Opt_context = 0,
367*4882a593Smuzhiyun 	Opt_defcontext = 1,
368*4882a593Smuzhiyun 	Opt_fscontext = 2,
369*4882a593Smuzhiyun 	Opt_rootcontext = 3,
370*4882a593Smuzhiyun 	Opt_seclabel = 4,
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun #define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
374*4882a593Smuzhiyun static struct {
375*4882a593Smuzhiyun 	const char *name;
376*4882a593Smuzhiyun 	int len;
377*4882a593Smuzhiyun 	int opt;
378*4882a593Smuzhiyun 	bool has_arg;
379*4882a593Smuzhiyun } tokens[] = {
380*4882a593Smuzhiyun 	A(context, true),
381*4882a593Smuzhiyun 	A(fscontext, true),
382*4882a593Smuzhiyun 	A(defcontext, true),
383*4882a593Smuzhiyun 	A(rootcontext, true),
384*4882a593Smuzhiyun 	A(seclabel, false),
385*4882a593Smuzhiyun };
386*4882a593Smuzhiyun #undef A
387*4882a593Smuzhiyun 
match_opt_prefix(char * s,int l,char ** arg)388*4882a593Smuzhiyun static int match_opt_prefix(char *s, int l, char **arg)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	int i;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
393*4882a593Smuzhiyun 		size_t len = tokens[i].len;
394*4882a593Smuzhiyun 		if (len > l || memcmp(s, tokens[i].name, len))
395*4882a593Smuzhiyun 			continue;
396*4882a593Smuzhiyun 		if (tokens[i].has_arg) {
397*4882a593Smuzhiyun 			if (len == l || s[len] != '=')
398*4882a593Smuzhiyun 				continue;
399*4882a593Smuzhiyun 			*arg = s + len + 1;
400*4882a593Smuzhiyun 		} else if (len != l)
401*4882a593Smuzhiyun 			continue;
402*4882a593Smuzhiyun 		return tokens[i].opt;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 	return Opt_error;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun #define SEL_MOUNT_FAIL_MSG "SELinux:  duplicate or incompatible mount options\n"
408*4882a593Smuzhiyun 
may_context_mount_sb_relabel(u32 sid,struct superblock_security_struct * sbsec,const struct cred * cred)409*4882a593Smuzhiyun static int may_context_mount_sb_relabel(u32 sid,
410*4882a593Smuzhiyun 			struct superblock_security_struct *sbsec,
411*4882a593Smuzhiyun 			const struct cred *cred)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(cred);
414*4882a593Smuzhiyun 	int rc;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
417*4882a593Smuzhiyun 			  tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
418*4882a593Smuzhiyun 			  FILESYSTEM__RELABELFROM, NULL);
419*4882a593Smuzhiyun 	if (rc)
420*4882a593Smuzhiyun 		return rc;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
423*4882a593Smuzhiyun 			  tsec->sid, sid, SECCLASS_FILESYSTEM,
424*4882a593Smuzhiyun 			  FILESYSTEM__RELABELTO, NULL);
425*4882a593Smuzhiyun 	return rc;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun 
may_context_mount_inode_relabel(u32 sid,struct superblock_security_struct * sbsec,const struct cred * cred)428*4882a593Smuzhiyun static int may_context_mount_inode_relabel(u32 sid,
429*4882a593Smuzhiyun 			struct superblock_security_struct *sbsec,
430*4882a593Smuzhiyun 			const struct cred *cred)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(cred);
433*4882a593Smuzhiyun 	int rc;
434*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
435*4882a593Smuzhiyun 			  tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
436*4882a593Smuzhiyun 			  FILESYSTEM__RELABELFROM, NULL);
437*4882a593Smuzhiyun 	if (rc)
438*4882a593Smuzhiyun 		return rc;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
441*4882a593Smuzhiyun 			  sid, sbsec->sid, SECCLASS_FILESYSTEM,
442*4882a593Smuzhiyun 			  FILESYSTEM__ASSOCIATE, NULL);
443*4882a593Smuzhiyun 	return rc;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
selinux_is_genfs_special_handling(struct super_block * sb)446*4882a593Smuzhiyun static int selinux_is_genfs_special_handling(struct super_block *sb)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun 	/* Special handling. Genfs but also in-core setxattr handler */
449*4882a593Smuzhiyun 	return	!strcmp(sb->s_type->name, "sysfs") ||
450*4882a593Smuzhiyun 		!strcmp(sb->s_type->name, "pstore") ||
451*4882a593Smuzhiyun 		!strcmp(sb->s_type->name, "debugfs") ||
452*4882a593Smuzhiyun 		!strcmp(sb->s_type->name, "tracefs") ||
453*4882a593Smuzhiyun 		!strcmp(sb->s_type->name, "rootfs") ||
454*4882a593Smuzhiyun 		(selinux_policycap_cgroupseclabel() &&
455*4882a593Smuzhiyun 		 (!strcmp(sb->s_type->name, "cgroup") ||
456*4882a593Smuzhiyun 		  !strcmp(sb->s_type->name, "cgroup2")));
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
selinux_is_sblabel_mnt(struct super_block * sb)459*4882a593Smuzhiyun static int selinux_is_sblabel_mnt(struct super_block *sb)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	/*
464*4882a593Smuzhiyun 	 * IMPORTANT: Double-check logic in this function when adding a new
465*4882a593Smuzhiyun 	 * SECURITY_FS_USE_* definition!
466*4882a593Smuzhiyun 	 */
467*4882a593Smuzhiyun 	BUILD_BUG_ON(SECURITY_FS_USE_MAX != 7);
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	switch (sbsec->behavior) {
470*4882a593Smuzhiyun 	case SECURITY_FS_USE_XATTR:
471*4882a593Smuzhiyun 	case SECURITY_FS_USE_TRANS:
472*4882a593Smuzhiyun 	case SECURITY_FS_USE_TASK:
473*4882a593Smuzhiyun 	case SECURITY_FS_USE_NATIVE:
474*4882a593Smuzhiyun 		return 1;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	case SECURITY_FS_USE_GENFS:
477*4882a593Smuzhiyun 		return selinux_is_genfs_special_handling(sb);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	/* Never allow relabeling on context mounts */
480*4882a593Smuzhiyun 	case SECURITY_FS_USE_MNTPOINT:
481*4882a593Smuzhiyun 	case SECURITY_FS_USE_NONE:
482*4882a593Smuzhiyun 	default:
483*4882a593Smuzhiyun 		return 0;
484*4882a593Smuzhiyun 	}
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
sb_finish_set_opts(struct super_block * sb)487*4882a593Smuzhiyun static int sb_finish_set_opts(struct super_block *sb)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
490*4882a593Smuzhiyun 	struct dentry *root = sb->s_root;
491*4882a593Smuzhiyun 	struct inode *root_inode = d_backing_inode(root);
492*4882a593Smuzhiyun 	int rc = 0;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
495*4882a593Smuzhiyun 		/* Make sure that the xattr handler exists and that no
496*4882a593Smuzhiyun 		   error other than -ENODATA is returned by getxattr on
497*4882a593Smuzhiyun 		   the root directory.  -ENODATA is ok, as this may be
498*4882a593Smuzhiyun 		   the first boot of the SELinux kernel before we have
499*4882a593Smuzhiyun 		   assigned xattr values to the filesystem. */
500*4882a593Smuzhiyun 		if (!(root_inode->i_opflags & IOP_XATTR)) {
501*4882a593Smuzhiyun 			pr_warn("SELinux: (dev %s, type %s) has no "
502*4882a593Smuzhiyun 			       "xattr support\n", sb->s_id, sb->s_type->name);
503*4882a593Smuzhiyun 			rc = -EOPNOTSUPP;
504*4882a593Smuzhiyun 			goto out;
505*4882a593Smuzhiyun 		}
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 		rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL,
508*4882a593Smuzhiyun 				    0, XATTR_NOSECURITY);
509*4882a593Smuzhiyun 		if (rc < 0 && rc != -ENODATA) {
510*4882a593Smuzhiyun 			if (rc == -EOPNOTSUPP)
511*4882a593Smuzhiyun 				pr_warn("SELinux: (dev %s, type "
512*4882a593Smuzhiyun 				       "%s) has no security xattr handler\n",
513*4882a593Smuzhiyun 				       sb->s_id, sb->s_type->name);
514*4882a593Smuzhiyun 			else
515*4882a593Smuzhiyun 				pr_warn("SELinux: (dev %s, type "
516*4882a593Smuzhiyun 				       "%s) getxattr errno %d\n", sb->s_id,
517*4882a593Smuzhiyun 				       sb->s_type->name, -rc);
518*4882a593Smuzhiyun 			goto out;
519*4882a593Smuzhiyun 		}
520*4882a593Smuzhiyun 	}
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	sbsec->flags |= SE_SBINITIALIZED;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	/*
525*4882a593Smuzhiyun 	 * Explicitly set or clear SBLABEL_MNT.  It's not sufficient to simply
526*4882a593Smuzhiyun 	 * leave the flag untouched because sb_clone_mnt_opts might be handing
527*4882a593Smuzhiyun 	 * us a superblock that needs the flag to be cleared.
528*4882a593Smuzhiyun 	 */
529*4882a593Smuzhiyun 	if (selinux_is_sblabel_mnt(sb))
530*4882a593Smuzhiyun 		sbsec->flags |= SBLABEL_MNT;
531*4882a593Smuzhiyun 	else
532*4882a593Smuzhiyun 		sbsec->flags &= ~SBLABEL_MNT;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	/* Initialize the root inode. */
535*4882a593Smuzhiyun 	rc = inode_doinit_with_dentry(root_inode, root);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	/* Initialize any other inodes associated with the superblock, e.g.
538*4882a593Smuzhiyun 	   inodes created prior to initial policy load or inodes created
539*4882a593Smuzhiyun 	   during get_sb by a pseudo filesystem that directly
540*4882a593Smuzhiyun 	   populates itself. */
541*4882a593Smuzhiyun 	spin_lock(&sbsec->isec_lock);
542*4882a593Smuzhiyun 	while (!list_empty(&sbsec->isec_head)) {
543*4882a593Smuzhiyun 		struct inode_security_struct *isec =
544*4882a593Smuzhiyun 				list_first_entry(&sbsec->isec_head,
545*4882a593Smuzhiyun 					   struct inode_security_struct, list);
546*4882a593Smuzhiyun 		struct inode *inode = isec->inode;
547*4882a593Smuzhiyun 		list_del_init(&isec->list);
548*4882a593Smuzhiyun 		spin_unlock(&sbsec->isec_lock);
549*4882a593Smuzhiyun 		inode = igrab(inode);
550*4882a593Smuzhiyun 		if (inode) {
551*4882a593Smuzhiyun 			if (!IS_PRIVATE(inode))
552*4882a593Smuzhiyun 				inode_doinit_with_dentry(inode, NULL);
553*4882a593Smuzhiyun 			iput(inode);
554*4882a593Smuzhiyun 		}
555*4882a593Smuzhiyun 		spin_lock(&sbsec->isec_lock);
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 	spin_unlock(&sbsec->isec_lock);
558*4882a593Smuzhiyun out:
559*4882a593Smuzhiyun 	return rc;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
bad_option(struct superblock_security_struct * sbsec,char flag,u32 old_sid,u32 new_sid)562*4882a593Smuzhiyun static int bad_option(struct superblock_security_struct *sbsec, char flag,
563*4882a593Smuzhiyun 		      u32 old_sid, u32 new_sid)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun 	char mnt_flags = sbsec->flags & SE_MNTMASK;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/* check if the old mount command had the same options */
568*4882a593Smuzhiyun 	if (sbsec->flags & SE_SBINITIALIZED)
569*4882a593Smuzhiyun 		if (!(sbsec->flags & flag) ||
570*4882a593Smuzhiyun 		    (old_sid != new_sid))
571*4882a593Smuzhiyun 			return 1;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	/* check if we were passed the same options twice,
574*4882a593Smuzhiyun 	 * aka someone passed context=a,context=b
575*4882a593Smuzhiyun 	 */
576*4882a593Smuzhiyun 	if (!(sbsec->flags & SE_SBINITIALIZED))
577*4882a593Smuzhiyun 		if (mnt_flags & flag)
578*4882a593Smuzhiyun 			return 1;
579*4882a593Smuzhiyun 	return 0;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
parse_sid(struct super_block * sb,const char * s,u32 * sid)582*4882a593Smuzhiyun static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	int rc = security_context_str_to_sid(&selinux_state, s,
585*4882a593Smuzhiyun 					     sid, GFP_KERNEL);
586*4882a593Smuzhiyun 	if (rc)
587*4882a593Smuzhiyun 		pr_warn("SELinux: security_context_str_to_sid"
588*4882a593Smuzhiyun 		       "(%s) failed for (dev %s, type %s) errno=%d\n",
589*4882a593Smuzhiyun 		       s, sb->s_id, sb->s_type->name, rc);
590*4882a593Smuzhiyun 	return rc;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun /*
594*4882a593Smuzhiyun  * Allow filesystems with binary mount data to explicitly set mount point
595*4882a593Smuzhiyun  * labeling information.
596*4882a593Smuzhiyun  */
selinux_set_mnt_opts(struct super_block * sb,void * mnt_opts,unsigned long kern_flags,unsigned long * set_kern_flags)597*4882a593Smuzhiyun static int selinux_set_mnt_opts(struct super_block *sb,
598*4882a593Smuzhiyun 				void *mnt_opts,
599*4882a593Smuzhiyun 				unsigned long kern_flags,
600*4882a593Smuzhiyun 				unsigned long *set_kern_flags)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
603*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
604*4882a593Smuzhiyun 	struct dentry *root = sbsec->sb->s_root;
605*4882a593Smuzhiyun 	struct selinux_mnt_opts *opts = mnt_opts;
606*4882a593Smuzhiyun 	struct inode_security_struct *root_isec;
607*4882a593Smuzhiyun 	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
608*4882a593Smuzhiyun 	u32 defcontext_sid = 0;
609*4882a593Smuzhiyun 	int rc = 0;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	mutex_lock(&sbsec->lock);
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state)) {
614*4882a593Smuzhiyun 		if (!opts) {
615*4882a593Smuzhiyun 			/* Defer initialization until selinux_complete_init,
616*4882a593Smuzhiyun 			   after the initial policy is loaded and the security
617*4882a593Smuzhiyun 			   server is ready to handle calls. */
618*4882a593Smuzhiyun 			goto out;
619*4882a593Smuzhiyun 		}
620*4882a593Smuzhiyun 		rc = -EINVAL;
621*4882a593Smuzhiyun 		pr_warn("SELinux: Unable to set superblock options "
622*4882a593Smuzhiyun 			"before the security server is initialized\n");
623*4882a593Smuzhiyun 		goto out;
624*4882a593Smuzhiyun 	}
625*4882a593Smuzhiyun 	if (kern_flags && !set_kern_flags) {
626*4882a593Smuzhiyun 		/* Specifying internal flags without providing a place to
627*4882a593Smuzhiyun 		 * place the results is not allowed */
628*4882a593Smuzhiyun 		rc = -EINVAL;
629*4882a593Smuzhiyun 		goto out;
630*4882a593Smuzhiyun 	}
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	/*
633*4882a593Smuzhiyun 	 * Binary mount data FS will come through this function twice.  Once
634*4882a593Smuzhiyun 	 * from an explicit call and once from the generic calls from the vfs.
635*4882a593Smuzhiyun 	 * Since the generic VFS calls will not contain any security mount data
636*4882a593Smuzhiyun 	 * we need to skip the double mount verification.
637*4882a593Smuzhiyun 	 *
638*4882a593Smuzhiyun 	 * This does open a hole in which we will not notice if the first
639*4882a593Smuzhiyun 	 * mount using this sb set explict options and a second mount using
640*4882a593Smuzhiyun 	 * this sb does not set any security options.  (The first options
641*4882a593Smuzhiyun 	 * will be used for both mounts)
642*4882a593Smuzhiyun 	 */
643*4882a593Smuzhiyun 	if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
644*4882a593Smuzhiyun 	    && !opts)
645*4882a593Smuzhiyun 		goto out;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	root_isec = backing_inode_security_novalidate(root);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	/*
650*4882a593Smuzhiyun 	 * parse the mount options, check if they are valid sids.
651*4882a593Smuzhiyun 	 * also check if someone is trying to mount the same sb more
652*4882a593Smuzhiyun 	 * than once with different security options.
653*4882a593Smuzhiyun 	 */
654*4882a593Smuzhiyun 	if (opts) {
655*4882a593Smuzhiyun 		if (opts->fscontext) {
656*4882a593Smuzhiyun 			rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
657*4882a593Smuzhiyun 			if (rc)
658*4882a593Smuzhiyun 				goto out;
659*4882a593Smuzhiyun 			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
660*4882a593Smuzhiyun 					fscontext_sid))
661*4882a593Smuzhiyun 				goto out_double_mount;
662*4882a593Smuzhiyun 			sbsec->flags |= FSCONTEXT_MNT;
663*4882a593Smuzhiyun 		}
664*4882a593Smuzhiyun 		if (opts->context) {
665*4882a593Smuzhiyun 			rc = parse_sid(sb, opts->context, &context_sid);
666*4882a593Smuzhiyun 			if (rc)
667*4882a593Smuzhiyun 				goto out;
668*4882a593Smuzhiyun 			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
669*4882a593Smuzhiyun 					context_sid))
670*4882a593Smuzhiyun 				goto out_double_mount;
671*4882a593Smuzhiyun 			sbsec->flags |= CONTEXT_MNT;
672*4882a593Smuzhiyun 		}
673*4882a593Smuzhiyun 		if (opts->rootcontext) {
674*4882a593Smuzhiyun 			rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
675*4882a593Smuzhiyun 			if (rc)
676*4882a593Smuzhiyun 				goto out;
677*4882a593Smuzhiyun 			if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
678*4882a593Smuzhiyun 					rootcontext_sid))
679*4882a593Smuzhiyun 				goto out_double_mount;
680*4882a593Smuzhiyun 			sbsec->flags |= ROOTCONTEXT_MNT;
681*4882a593Smuzhiyun 		}
682*4882a593Smuzhiyun 		if (opts->defcontext) {
683*4882a593Smuzhiyun 			rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
684*4882a593Smuzhiyun 			if (rc)
685*4882a593Smuzhiyun 				goto out;
686*4882a593Smuzhiyun 			if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
687*4882a593Smuzhiyun 					defcontext_sid))
688*4882a593Smuzhiyun 				goto out_double_mount;
689*4882a593Smuzhiyun 			sbsec->flags |= DEFCONTEXT_MNT;
690*4882a593Smuzhiyun 		}
691*4882a593Smuzhiyun 	}
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	if (sbsec->flags & SE_SBINITIALIZED) {
694*4882a593Smuzhiyun 		/* previously mounted with options, but not on this attempt? */
695*4882a593Smuzhiyun 		if ((sbsec->flags & SE_MNTMASK) && !opts)
696*4882a593Smuzhiyun 			goto out_double_mount;
697*4882a593Smuzhiyun 		rc = 0;
698*4882a593Smuzhiyun 		goto out;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	if (strcmp(sb->s_type->name, "proc") == 0)
702*4882a593Smuzhiyun 		sbsec->flags |= SE_SBPROC | SE_SBGENFS;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	if (!strcmp(sb->s_type->name, "debugfs") ||
705*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "tracefs") ||
706*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "binder") ||
707*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "bpf") ||
708*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "pstore"))
709*4882a593Smuzhiyun 		sbsec->flags |= SE_SBGENFS;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	if (!strcmp(sb->s_type->name, "sysfs") ||
712*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "cgroup") ||
713*4882a593Smuzhiyun 	    !strcmp(sb->s_type->name, "cgroup2"))
714*4882a593Smuzhiyun 		sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (!sbsec->behavior) {
717*4882a593Smuzhiyun 		/*
718*4882a593Smuzhiyun 		 * Determine the labeling behavior to use for this
719*4882a593Smuzhiyun 		 * filesystem type.
720*4882a593Smuzhiyun 		 */
721*4882a593Smuzhiyun 		rc = security_fs_use(&selinux_state, sb);
722*4882a593Smuzhiyun 		if (rc) {
723*4882a593Smuzhiyun 			pr_warn("%s: security_fs_use(%s) returned %d\n",
724*4882a593Smuzhiyun 					__func__, sb->s_type->name, rc);
725*4882a593Smuzhiyun 			goto out;
726*4882a593Smuzhiyun 		}
727*4882a593Smuzhiyun 	}
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	/*
730*4882a593Smuzhiyun 	 * If this is a user namespace mount and the filesystem type is not
731*4882a593Smuzhiyun 	 * explicitly whitelisted, then no contexts are allowed on the command
732*4882a593Smuzhiyun 	 * line and security labels must be ignored.
733*4882a593Smuzhiyun 	 */
734*4882a593Smuzhiyun 	if (sb->s_user_ns != &init_user_ns &&
735*4882a593Smuzhiyun 	    strcmp(sb->s_type->name, "tmpfs") &&
736*4882a593Smuzhiyun 	    strcmp(sb->s_type->name, "ramfs") &&
737*4882a593Smuzhiyun 	    strcmp(sb->s_type->name, "devpts")) {
738*4882a593Smuzhiyun 		if (context_sid || fscontext_sid || rootcontext_sid ||
739*4882a593Smuzhiyun 		    defcontext_sid) {
740*4882a593Smuzhiyun 			rc = -EACCES;
741*4882a593Smuzhiyun 			goto out;
742*4882a593Smuzhiyun 		}
743*4882a593Smuzhiyun 		if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
744*4882a593Smuzhiyun 			sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
745*4882a593Smuzhiyun 			rc = security_transition_sid(&selinux_state,
746*4882a593Smuzhiyun 						     current_sid(),
747*4882a593Smuzhiyun 						     current_sid(),
748*4882a593Smuzhiyun 						     SECCLASS_FILE, NULL,
749*4882a593Smuzhiyun 						     &sbsec->mntpoint_sid);
750*4882a593Smuzhiyun 			if (rc)
751*4882a593Smuzhiyun 				goto out;
752*4882a593Smuzhiyun 		}
753*4882a593Smuzhiyun 		goto out_set_opts;
754*4882a593Smuzhiyun 	}
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	/* sets the context of the superblock for the fs being mounted. */
757*4882a593Smuzhiyun 	if (fscontext_sid) {
758*4882a593Smuzhiyun 		rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
759*4882a593Smuzhiyun 		if (rc)
760*4882a593Smuzhiyun 			goto out;
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 		sbsec->sid = fscontext_sid;
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	/*
766*4882a593Smuzhiyun 	 * Switch to using mount point labeling behavior.
767*4882a593Smuzhiyun 	 * sets the label used on all file below the mountpoint, and will set
768*4882a593Smuzhiyun 	 * the superblock context if not already set.
769*4882a593Smuzhiyun 	 */
770*4882a593Smuzhiyun 	if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
771*4882a593Smuzhiyun 		sbsec->behavior = SECURITY_FS_USE_NATIVE;
772*4882a593Smuzhiyun 		*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
773*4882a593Smuzhiyun 	}
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	if (context_sid) {
776*4882a593Smuzhiyun 		if (!fscontext_sid) {
777*4882a593Smuzhiyun 			rc = may_context_mount_sb_relabel(context_sid, sbsec,
778*4882a593Smuzhiyun 							  cred);
779*4882a593Smuzhiyun 			if (rc)
780*4882a593Smuzhiyun 				goto out;
781*4882a593Smuzhiyun 			sbsec->sid = context_sid;
782*4882a593Smuzhiyun 		} else {
783*4882a593Smuzhiyun 			rc = may_context_mount_inode_relabel(context_sid, sbsec,
784*4882a593Smuzhiyun 							     cred);
785*4882a593Smuzhiyun 			if (rc)
786*4882a593Smuzhiyun 				goto out;
787*4882a593Smuzhiyun 		}
788*4882a593Smuzhiyun 		if (!rootcontext_sid)
789*4882a593Smuzhiyun 			rootcontext_sid = context_sid;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 		sbsec->mntpoint_sid = context_sid;
792*4882a593Smuzhiyun 		sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
793*4882a593Smuzhiyun 	}
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 	if (rootcontext_sid) {
796*4882a593Smuzhiyun 		rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
797*4882a593Smuzhiyun 						     cred);
798*4882a593Smuzhiyun 		if (rc)
799*4882a593Smuzhiyun 			goto out;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 		root_isec->sid = rootcontext_sid;
802*4882a593Smuzhiyun 		root_isec->initialized = LABEL_INITIALIZED;
803*4882a593Smuzhiyun 	}
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	if (defcontext_sid) {
806*4882a593Smuzhiyun 		if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
807*4882a593Smuzhiyun 			sbsec->behavior != SECURITY_FS_USE_NATIVE) {
808*4882a593Smuzhiyun 			rc = -EINVAL;
809*4882a593Smuzhiyun 			pr_warn("SELinux: defcontext option is "
810*4882a593Smuzhiyun 			       "invalid for this filesystem type\n");
811*4882a593Smuzhiyun 			goto out;
812*4882a593Smuzhiyun 		}
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 		if (defcontext_sid != sbsec->def_sid) {
815*4882a593Smuzhiyun 			rc = may_context_mount_inode_relabel(defcontext_sid,
816*4882a593Smuzhiyun 							     sbsec, cred);
817*4882a593Smuzhiyun 			if (rc)
818*4882a593Smuzhiyun 				goto out;
819*4882a593Smuzhiyun 		}
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 		sbsec->def_sid = defcontext_sid;
822*4882a593Smuzhiyun 	}
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun out_set_opts:
825*4882a593Smuzhiyun 	rc = sb_finish_set_opts(sb);
826*4882a593Smuzhiyun out:
827*4882a593Smuzhiyun 	mutex_unlock(&sbsec->lock);
828*4882a593Smuzhiyun 	return rc;
829*4882a593Smuzhiyun out_double_mount:
830*4882a593Smuzhiyun 	rc = -EINVAL;
831*4882a593Smuzhiyun 	pr_warn("SELinux: mount invalid.  Same superblock, different "
832*4882a593Smuzhiyun 	       "security settings for (dev %s, type %s)\n", sb->s_id,
833*4882a593Smuzhiyun 	       sb->s_type->name);
834*4882a593Smuzhiyun 	goto out;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun 
selinux_cmp_sb_context(const struct super_block * oldsb,const struct super_block * newsb)837*4882a593Smuzhiyun static int selinux_cmp_sb_context(const struct super_block *oldsb,
838*4882a593Smuzhiyun 				    const struct super_block *newsb)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun 	struct superblock_security_struct *old = oldsb->s_security;
841*4882a593Smuzhiyun 	struct superblock_security_struct *new = newsb->s_security;
842*4882a593Smuzhiyun 	char oldflags = old->flags & SE_MNTMASK;
843*4882a593Smuzhiyun 	char newflags = new->flags & SE_MNTMASK;
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	if (oldflags != newflags)
846*4882a593Smuzhiyun 		goto mismatch;
847*4882a593Smuzhiyun 	if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
848*4882a593Smuzhiyun 		goto mismatch;
849*4882a593Smuzhiyun 	if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
850*4882a593Smuzhiyun 		goto mismatch;
851*4882a593Smuzhiyun 	if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
852*4882a593Smuzhiyun 		goto mismatch;
853*4882a593Smuzhiyun 	if (oldflags & ROOTCONTEXT_MNT) {
854*4882a593Smuzhiyun 		struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
855*4882a593Smuzhiyun 		struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
856*4882a593Smuzhiyun 		if (oldroot->sid != newroot->sid)
857*4882a593Smuzhiyun 			goto mismatch;
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 	return 0;
860*4882a593Smuzhiyun mismatch:
861*4882a593Smuzhiyun 	pr_warn("SELinux: mount invalid.  Same superblock, "
862*4882a593Smuzhiyun 			    "different security settings for (dev %s, "
863*4882a593Smuzhiyun 			    "type %s)\n", newsb->s_id, newsb->s_type->name);
864*4882a593Smuzhiyun 	return -EBUSY;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
selinux_sb_clone_mnt_opts(const struct super_block * oldsb,struct super_block * newsb,unsigned long kern_flags,unsigned long * set_kern_flags)867*4882a593Smuzhiyun static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
868*4882a593Smuzhiyun 					struct super_block *newsb,
869*4882a593Smuzhiyun 					unsigned long kern_flags,
870*4882a593Smuzhiyun 					unsigned long *set_kern_flags)
871*4882a593Smuzhiyun {
872*4882a593Smuzhiyun 	int rc = 0;
873*4882a593Smuzhiyun 	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
874*4882a593Smuzhiyun 	struct superblock_security_struct *newsbsec = newsb->s_security;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
877*4882a593Smuzhiyun 	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
878*4882a593Smuzhiyun 	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	/*
881*4882a593Smuzhiyun 	 * if the parent was able to be mounted it clearly had no special lsm
882*4882a593Smuzhiyun 	 * mount options.  thus we can safely deal with this superblock later
883*4882a593Smuzhiyun 	 */
884*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state))
885*4882a593Smuzhiyun 		return 0;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	/*
888*4882a593Smuzhiyun 	 * Specifying internal flags without providing a place to
889*4882a593Smuzhiyun 	 * place the results is not allowed.
890*4882a593Smuzhiyun 	 */
891*4882a593Smuzhiyun 	if (kern_flags && !set_kern_flags)
892*4882a593Smuzhiyun 		return -EINVAL;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 	/* how can we clone if the old one wasn't set up?? */
895*4882a593Smuzhiyun 	BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	/* if fs is reusing a sb, make sure that the contexts match */
898*4882a593Smuzhiyun 	if (newsbsec->flags & SE_SBINITIALIZED) {
899*4882a593Smuzhiyun 		if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
900*4882a593Smuzhiyun 			*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
901*4882a593Smuzhiyun 		return selinux_cmp_sb_context(oldsb, newsb);
902*4882a593Smuzhiyun 	}
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	mutex_lock(&newsbsec->lock);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	newsbsec->flags = oldsbsec->flags;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	newsbsec->sid = oldsbsec->sid;
909*4882a593Smuzhiyun 	newsbsec->def_sid = oldsbsec->def_sid;
910*4882a593Smuzhiyun 	newsbsec->behavior = oldsbsec->behavior;
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
913*4882a593Smuzhiyun 		!(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
914*4882a593Smuzhiyun 		rc = security_fs_use(&selinux_state, newsb);
915*4882a593Smuzhiyun 		if (rc)
916*4882a593Smuzhiyun 			goto out;
917*4882a593Smuzhiyun 	}
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
920*4882a593Smuzhiyun 		newsbsec->behavior = SECURITY_FS_USE_NATIVE;
921*4882a593Smuzhiyun 		*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
922*4882a593Smuzhiyun 	}
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	if (set_context) {
925*4882a593Smuzhiyun 		u32 sid = oldsbsec->mntpoint_sid;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 		if (!set_fscontext)
928*4882a593Smuzhiyun 			newsbsec->sid = sid;
929*4882a593Smuzhiyun 		if (!set_rootcontext) {
930*4882a593Smuzhiyun 			struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
931*4882a593Smuzhiyun 			newisec->sid = sid;
932*4882a593Smuzhiyun 		}
933*4882a593Smuzhiyun 		newsbsec->mntpoint_sid = sid;
934*4882a593Smuzhiyun 	}
935*4882a593Smuzhiyun 	if (set_rootcontext) {
936*4882a593Smuzhiyun 		const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
937*4882a593Smuzhiyun 		struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 		newisec->sid = oldisec->sid;
940*4882a593Smuzhiyun 	}
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	sb_finish_set_opts(newsb);
943*4882a593Smuzhiyun out:
944*4882a593Smuzhiyun 	mutex_unlock(&newsbsec->lock);
945*4882a593Smuzhiyun 	return rc;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun 
selinux_add_opt(int token,const char * s,void ** mnt_opts)948*4882a593Smuzhiyun static int selinux_add_opt(int token, const char *s, void **mnt_opts)
949*4882a593Smuzhiyun {
950*4882a593Smuzhiyun 	struct selinux_mnt_opts *opts = *mnt_opts;
951*4882a593Smuzhiyun 	bool is_alloc_opts = false;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	if (token == Opt_seclabel)	/* eaten and completely ignored */
954*4882a593Smuzhiyun 		return 0;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	if (!s)
957*4882a593Smuzhiyun 		return -ENOMEM;
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	if (!opts) {
960*4882a593Smuzhiyun 		opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
961*4882a593Smuzhiyun 		if (!opts)
962*4882a593Smuzhiyun 			return -ENOMEM;
963*4882a593Smuzhiyun 		*mnt_opts = opts;
964*4882a593Smuzhiyun 		is_alloc_opts = true;
965*4882a593Smuzhiyun 	}
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 	switch (token) {
968*4882a593Smuzhiyun 	case Opt_context:
969*4882a593Smuzhiyun 		if (opts->context || opts->defcontext)
970*4882a593Smuzhiyun 			goto Einval;
971*4882a593Smuzhiyun 		opts->context = s;
972*4882a593Smuzhiyun 		break;
973*4882a593Smuzhiyun 	case Opt_fscontext:
974*4882a593Smuzhiyun 		if (opts->fscontext)
975*4882a593Smuzhiyun 			goto Einval;
976*4882a593Smuzhiyun 		opts->fscontext = s;
977*4882a593Smuzhiyun 		break;
978*4882a593Smuzhiyun 	case Opt_rootcontext:
979*4882a593Smuzhiyun 		if (opts->rootcontext)
980*4882a593Smuzhiyun 			goto Einval;
981*4882a593Smuzhiyun 		opts->rootcontext = s;
982*4882a593Smuzhiyun 		break;
983*4882a593Smuzhiyun 	case Opt_defcontext:
984*4882a593Smuzhiyun 		if (opts->context || opts->defcontext)
985*4882a593Smuzhiyun 			goto Einval;
986*4882a593Smuzhiyun 		opts->defcontext = s;
987*4882a593Smuzhiyun 		break;
988*4882a593Smuzhiyun 	}
989*4882a593Smuzhiyun 	return 0;
990*4882a593Smuzhiyun Einval:
991*4882a593Smuzhiyun 	if (is_alloc_opts) {
992*4882a593Smuzhiyun 		kfree(opts);
993*4882a593Smuzhiyun 		*mnt_opts = NULL;
994*4882a593Smuzhiyun 	}
995*4882a593Smuzhiyun 	pr_warn(SEL_MOUNT_FAIL_MSG);
996*4882a593Smuzhiyun 	return -EINVAL;
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun 
selinux_add_mnt_opt(const char * option,const char * val,int len,void ** mnt_opts)999*4882a593Smuzhiyun static int selinux_add_mnt_opt(const char *option, const char *val, int len,
1000*4882a593Smuzhiyun 			       void **mnt_opts)
1001*4882a593Smuzhiyun {
1002*4882a593Smuzhiyun 	int token = Opt_error;
1003*4882a593Smuzhiyun 	int rc, i;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
1006*4882a593Smuzhiyun 		if (strcmp(option, tokens[i].name) == 0) {
1007*4882a593Smuzhiyun 			token = tokens[i].opt;
1008*4882a593Smuzhiyun 			break;
1009*4882a593Smuzhiyun 		}
1010*4882a593Smuzhiyun 	}
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	if (token == Opt_error)
1013*4882a593Smuzhiyun 		return -EINVAL;
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 	if (token != Opt_seclabel) {
1016*4882a593Smuzhiyun 		val = kmemdup_nul(val, len, GFP_KERNEL);
1017*4882a593Smuzhiyun 		if (!val) {
1018*4882a593Smuzhiyun 			rc = -ENOMEM;
1019*4882a593Smuzhiyun 			goto free_opt;
1020*4882a593Smuzhiyun 		}
1021*4882a593Smuzhiyun 	}
1022*4882a593Smuzhiyun 	rc = selinux_add_opt(token, val, mnt_opts);
1023*4882a593Smuzhiyun 	if (unlikely(rc)) {
1024*4882a593Smuzhiyun 		kfree(val);
1025*4882a593Smuzhiyun 		goto free_opt;
1026*4882a593Smuzhiyun 	}
1027*4882a593Smuzhiyun 	return rc;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun free_opt:
1030*4882a593Smuzhiyun 	if (*mnt_opts) {
1031*4882a593Smuzhiyun 		selinux_free_mnt_opts(*mnt_opts);
1032*4882a593Smuzhiyun 		*mnt_opts = NULL;
1033*4882a593Smuzhiyun 	}
1034*4882a593Smuzhiyun 	return rc;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
show_sid(struct seq_file * m,u32 sid)1037*4882a593Smuzhiyun static int show_sid(struct seq_file *m, u32 sid)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	char *context = NULL;
1040*4882a593Smuzhiyun 	u32 len;
1041*4882a593Smuzhiyun 	int rc;
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	rc = security_sid_to_context(&selinux_state, sid,
1044*4882a593Smuzhiyun 					     &context, &len);
1045*4882a593Smuzhiyun 	if (!rc) {
1046*4882a593Smuzhiyun 		bool has_comma = context && strchr(context, ',');
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 		seq_putc(m, '=');
1049*4882a593Smuzhiyun 		if (has_comma)
1050*4882a593Smuzhiyun 			seq_putc(m, '\"');
1051*4882a593Smuzhiyun 		seq_escape(m, context, "\"\n\\");
1052*4882a593Smuzhiyun 		if (has_comma)
1053*4882a593Smuzhiyun 			seq_putc(m, '\"');
1054*4882a593Smuzhiyun 	}
1055*4882a593Smuzhiyun 	kfree(context);
1056*4882a593Smuzhiyun 	return rc;
1057*4882a593Smuzhiyun }
1058*4882a593Smuzhiyun 
selinux_sb_show_options(struct seq_file * m,struct super_block * sb)1059*4882a593Smuzhiyun static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1060*4882a593Smuzhiyun {
1061*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
1062*4882a593Smuzhiyun 	int rc;
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	if (!(sbsec->flags & SE_SBINITIALIZED))
1065*4882a593Smuzhiyun 		return 0;
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state))
1068*4882a593Smuzhiyun 		return 0;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	if (sbsec->flags & FSCONTEXT_MNT) {
1071*4882a593Smuzhiyun 		seq_putc(m, ',');
1072*4882a593Smuzhiyun 		seq_puts(m, FSCONTEXT_STR);
1073*4882a593Smuzhiyun 		rc = show_sid(m, sbsec->sid);
1074*4882a593Smuzhiyun 		if (rc)
1075*4882a593Smuzhiyun 			return rc;
1076*4882a593Smuzhiyun 	}
1077*4882a593Smuzhiyun 	if (sbsec->flags & CONTEXT_MNT) {
1078*4882a593Smuzhiyun 		seq_putc(m, ',');
1079*4882a593Smuzhiyun 		seq_puts(m, CONTEXT_STR);
1080*4882a593Smuzhiyun 		rc = show_sid(m, sbsec->mntpoint_sid);
1081*4882a593Smuzhiyun 		if (rc)
1082*4882a593Smuzhiyun 			return rc;
1083*4882a593Smuzhiyun 	}
1084*4882a593Smuzhiyun 	if (sbsec->flags & DEFCONTEXT_MNT) {
1085*4882a593Smuzhiyun 		seq_putc(m, ',');
1086*4882a593Smuzhiyun 		seq_puts(m, DEFCONTEXT_STR);
1087*4882a593Smuzhiyun 		rc = show_sid(m, sbsec->def_sid);
1088*4882a593Smuzhiyun 		if (rc)
1089*4882a593Smuzhiyun 			return rc;
1090*4882a593Smuzhiyun 	}
1091*4882a593Smuzhiyun 	if (sbsec->flags & ROOTCONTEXT_MNT) {
1092*4882a593Smuzhiyun 		struct dentry *root = sbsec->sb->s_root;
1093*4882a593Smuzhiyun 		struct inode_security_struct *isec = backing_inode_security(root);
1094*4882a593Smuzhiyun 		seq_putc(m, ',');
1095*4882a593Smuzhiyun 		seq_puts(m, ROOTCONTEXT_STR);
1096*4882a593Smuzhiyun 		rc = show_sid(m, isec->sid);
1097*4882a593Smuzhiyun 		if (rc)
1098*4882a593Smuzhiyun 			return rc;
1099*4882a593Smuzhiyun 	}
1100*4882a593Smuzhiyun 	if (sbsec->flags & SBLABEL_MNT) {
1101*4882a593Smuzhiyun 		seq_putc(m, ',');
1102*4882a593Smuzhiyun 		seq_puts(m, SECLABEL_STR);
1103*4882a593Smuzhiyun 	}
1104*4882a593Smuzhiyun 	return 0;
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun 
inode_mode_to_security_class(umode_t mode)1107*4882a593Smuzhiyun static inline u16 inode_mode_to_security_class(umode_t mode)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun 	switch (mode & S_IFMT) {
1110*4882a593Smuzhiyun 	case S_IFSOCK:
1111*4882a593Smuzhiyun 		return SECCLASS_SOCK_FILE;
1112*4882a593Smuzhiyun 	case S_IFLNK:
1113*4882a593Smuzhiyun 		return SECCLASS_LNK_FILE;
1114*4882a593Smuzhiyun 	case S_IFREG:
1115*4882a593Smuzhiyun 		return SECCLASS_FILE;
1116*4882a593Smuzhiyun 	case S_IFBLK:
1117*4882a593Smuzhiyun 		return SECCLASS_BLK_FILE;
1118*4882a593Smuzhiyun 	case S_IFDIR:
1119*4882a593Smuzhiyun 		return SECCLASS_DIR;
1120*4882a593Smuzhiyun 	case S_IFCHR:
1121*4882a593Smuzhiyun 		return SECCLASS_CHR_FILE;
1122*4882a593Smuzhiyun 	case S_IFIFO:
1123*4882a593Smuzhiyun 		return SECCLASS_FIFO_FILE;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	}
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	return SECCLASS_FILE;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun 
default_protocol_stream(int protocol)1130*4882a593Smuzhiyun static inline int default_protocol_stream(int protocol)
1131*4882a593Smuzhiyun {
1132*4882a593Smuzhiyun 	return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
default_protocol_dgram(int protocol)1135*4882a593Smuzhiyun static inline int default_protocol_dgram(int protocol)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun 	return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun 
socket_type_to_security_class(int family,int type,int protocol)1140*4882a593Smuzhiyun static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1141*4882a593Smuzhiyun {
1142*4882a593Smuzhiyun 	int extsockclass = selinux_policycap_extsockclass();
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun 	switch (family) {
1145*4882a593Smuzhiyun 	case PF_UNIX:
1146*4882a593Smuzhiyun 		switch (type) {
1147*4882a593Smuzhiyun 		case SOCK_STREAM:
1148*4882a593Smuzhiyun 		case SOCK_SEQPACKET:
1149*4882a593Smuzhiyun 			return SECCLASS_UNIX_STREAM_SOCKET;
1150*4882a593Smuzhiyun 		case SOCK_DGRAM:
1151*4882a593Smuzhiyun 		case SOCK_RAW:
1152*4882a593Smuzhiyun 			return SECCLASS_UNIX_DGRAM_SOCKET;
1153*4882a593Smuzhiyun 		}
1154*4882a593Smuzhiyun 		break;
1155*4882a593Smuzhiyun 	case PF_INET:
1156*4882a593Smuzhiyun 	case PF_INET6:
1157*4882a593Smuzhiyun 		switch (type) {
1158*4882a593Smuzhiyun 		case SOCK_STREAM:
1159*4882a593Smuzhiyun 		case SOCK_SEQPACKET:
1160*4882a593Smuzhiyun 			if (default_protocol_stream(protocol))
1161*4882a593Smuzhiyun 				return SECCLASS_TCP_SOCKET;
1162*4882a593Smuzhiyun 			else if (extsockclass && protocol == IPPROTO_SCTP)
1163*4882a593Smuzhiyun 				return SECCLASS_SCTP_SOCKET;
1164*4882a593Smuzhiyun 			else
1165*4882a593Smuzhiyun 				return SECCLASS_RAWIP_SOCKET;
1166*4882a593Smuzhiyun 		case SOCK_DGRAM:
1167*4882a593Smuzhiyun 			if (default_protocol_dgram(protocol))
1168*4882a593Smuzhiyun 				return SECCLASS_UDP_SOCKET;
1169*4882a593Smuzhiyun 			else if (extsockclass && (protocol == IPPROTO_ICMP ||
1170*4882a593Smuzhiyun 						  protocol == IPPROTO_ICMPV6))
1171*4882a593Smuzhiyun 				return SECCLASS_ICMP_SOCKET;
1172*4882a593Smuzhiyun 			else
1173*4882a593Smuzhiyun 				return SECCLASS_RAWIP_SOCKET;
1174*4882a593Smuzhiyun 		case SOCK_DCCP:
1175*4882a593Smuzhiyun 			return SECCLASS_DCCP_SOCKET;
1176*4882a593Smuzhiyun 		default:
1177*4882a593Smuzhiyun 			return SECCLASS_RAWIP_SOCKET;
1178*4882a593Smuzhiyun 		}
1179*4882a593Smuzhiyun 		break;
1180*4882a593Smuzhiyun 	case PF_NETLINK:
1181*4882a593Smuzhiyun 		switch (protocol) {
1182*4882a593Smuzhiyun 		case NETLINK_ROUTE:
1183*4882a593Smuzhiyun 			return SECCLASS_NETLINK_ROUTE_SOCKET;
1184*4882a593Smuzhiyun 		case NETLINK_SOCK_DIAG:
1185*4882a593Smuzhiyun 			return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1186*4882a593Smuzhiyun 		case NETLINK_NFLOG:
1187*4882a593Smuzhiyun 			return SECCLASS_NETLINK_NFLOG_SOCKET;
1188*4882a593Smuzhiyun 		case NETLINK_XFRM:
1189*4882a593Smuzhiyun 			return SECCLASS_NETLINK_XFRM_SOCKET;
1190*4882a593Smuzhiyun 		case NETLINK_SELINUX:
1191*4882a593Smuzhiyun 			return SECCLASS_NETLINK_SELINUX_SOCKET;
1192*4882a593Smuzhiyun 		case NETLINK_ISCSI:
1193*4882a593Smuzhiyun 			return SECCLASS_NETLINK_ISCSI_SOCKET;
1194*4882a593Smuzhiyun 		case NETLINK_AUDIT:
1195*4882a593Smuzhiyun 			return SECCLASS_NETLINK_AUDIT_SOCKET;
1196*4882a593Smuzhiyun 		case NETLINK_FIB_LOOKUP:
1197*4882a593Smuzhiyun 			return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1198*4882a593Smuzhiyun 		case NETLINK_CONNECTOR:
1199*4882a593Smuzhiyun 			return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1200*4882a593Smuzhiyun 		case NETLINK_NETFILTER:
1201*4882a593Smuzhiyun 			return SECCLASS_NETLINK_NETFILTER_SOCKET;
1202*4882a593Smuzhiyun 		case NETLINK_DNRTMSG:
1203*4882a593Smuzhiyun 			return SECCLASS_NETLINK_DNRT_SOCKET;
1204*4882a593Smuzhiyun 		case NETLINK_KOBJECT_UEVENT:
1205*4882a593Smuzhiyun 			return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
1206*4882a593Smuzhiyun 		case NETLINK_GENERIC:
1207*4882a593Smuzhiyun 			return SECCLASS_NETLINK_GENERIC_SOCKET;
1208*4882a593Smuzhiyun 		case NETLINK_SCSITRANSPORT:
1209*4882a593Smuzhiyun 			return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1210*4882a593Smuzhiyun 		case NETLINK_RDMA:
1211*4882a593Smuzhiyun 			return SECCLASS_NETLINK_RDMA_SOCKET;
1212*4882a593Smuzhiyun 		case NETLINK_CRYPTO:
1213*4882a593Smuzhiyun 			return SECCLASS_NETLINK_CRYPTO_SOCKET;
1214*4882a593Smuzhiyun 		default:
1215*4882a593Smuzhiyun 			return SECCLASS_NETLINK_SOCKET;
1216*4882a593Smuzhiyun 		}
1217*4882a593Smuzhiyun 	case PF_PACKET:
1218*4882a593Smuzhiyun 		return SECCLASS_PACKET_SOCKET;
1219*4882a593Smuzhiyun 	case PF_KEY:
1220*4882a593Smuzhiyun 		return SECCLASS_KEY_SOCKET;
1221*4882a593Smuzhiyun 	case PF_APPLETALK:
1222*4882a593Smuzhiyun 		return SECCLASS_APPLETALK_SOCKET;
1223*4882a593Smuzhiyun 	}
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	if (extsockclass) {
1226*4882a593Smuzhiyun 		switch (family) {
1227*4882a593Smuzhiyun 		case PF_AX25:
1228*4882a593Smuzhiyun 			return SECCLASS_AX25_SOCKET;
1229*4882a593Smuzhiyun 		case PF_IPX:
1230*4882a593Smuzhiyun 			return SECCLASS_IPX_SOCKET;
1231*4882a593Smuzhiyun 		case PF_NETROM:
1232*4882a593Smuzhiyun 			return SECCLASS_NETROM_SOCKET;
1233*4882a593Smuzhiyun 		case PF_ATMPVC:
1234*4882a593Smuzhiyun 			return SECCLASS_ATMPVC_SOCKET;
1235*4882a593Smuzhiyun 		case PF_X25:
1236*4882a593Smuzhiyun 			return SECCLASS_X25_SOCKET;
1237*4882a593Smuzhiyun 		case PF_ROSE:
1238*4882a593Smuzhiyun 			return SECCLASS_ROSE_SOCKET;
1239*4882a593Smuzhiyun 		case PF_DECnet:
1240*4882a593Smuzhiyun 			return SECCLASS_DECNET_SOCKET;
1241*4882a593Smuzhiyun 		case PF_ATMSVC:
1242*4882a593Smuzhiyun 			return SECCLASS_ATMSVC_SOCKET;
1243*4882a593Smuzhiyun 		case PF_RDS:
1244*4882a593Smuzhiyun 			return SECCLASS_RDS_SOCKET;
1245*4882a593Smuzhiyun 		case PF_IRDA:
1246*4882a593Smuzhiyun 			return SECCLASS_IRDA_SOCKET;
1247*4882a593Smuzhiyun 		case PF_PPPOX:
1248*4882a593Smuzhiyun 			return SECCLASS_PPPOX_SOCKET;
1249*4882a593Smuzhiyun 		case PF_LLC:
1250*4882a593Smuzhiyun 			return SECCLASS_LLC_SOCKET;
1251*4882a593Smuzhiyun 		case PF_CAN:
1252*4882a593Smuzhiyun 			return SECCLASS_CAN_SOCKET;
1253*4882a593Smuzhiyun 		case PF_TIPC:
1254*4882a593Smuzhiyun 			return SECCLASS_TIPC_SOCKET;
1255*4882a593Smuzhiyun 		case PF_BLUETOOTH:
1256*4882a593Smuzhiyun 			return SECCLASS_BLUETOOTH_SOCKET;
1257*4882a593Smuzhiyun 		case PF_IUCV:
1258*4882a593Smuzhiyun 			return SECCLASS_IUCV_SOCKET;
1259*4882a593Smuzhiyun 		case PF_RXRPC:
1260*4882a593Smuzhiyun 			return SECCLASS_RXRPC_SOCKET;
1261*4882a593Smuzhiyun 		case PF_ISDN:
1262*4882a593Smuzhiyun 			return SECCLASS_ISDN_SOCKET;
1263*4882a593Smuzhiyun 		case PF_PHONET:
1264*4882a593Smuzhiyun 			return SECCLASS_PHONET_SOCKET;
1265*4882a593Smuzhiyun 		case PF_IEEE802154:
1266*4882a593Smuzhiyun 			return SECCLASS_IEEE802154_SOCKET;
1267*4882a593Smuzhiyun 		case PF_CAIF:
1268*4882a593Smuzhiyun 			return SECCLASS_CAIF_SOCKET;
1269*4882a593Smuzhiyun 		case PF_ALG:
1270*4882a593Smuzhiyun 			return SECCLASS_ALG_SOCKET;
1271*4882a593Smuzhiyun 		case PF_NFC:
1272*4882a593Smuzhiyun 			return SECCLASS_NFC_SOCKET;
1273*4882a593Smuzhiyun 		case PF_VSOCK:
1274*4882a593Smuzhiyun 			return SECCLASS_VSOCK_SOCKET;
1275*4882a593Smuzhiyun 		case PF_KCM:
1276*4882a593Smuzhiyun 			return SECCLASS_KCM_SOCKET;
1277*4882a593Smuzhiyun 		case PF_QIPCRTR:
1278*4882a593Smuzhiyun 			return SECCLASS_QIPCRTR_SOCKET;
1279*4882a593Smuzhiyun 		case PF_SMC:
1280*4882a593Smuzhiyun 			return SECCLASS_SMC_SOCKET;
1281*4882a593Smuzhiyun 		case PF_XDP:
1282*4882a593Smuzhiyun 			return SECCLASS_XDP_SOCKET;
1283*4882a593Smuzhiyun #if PF_MAX > 45
1284*4882a593Smuzhiyun #error New address family defined, please update this function.
1285*4882a593Smuzhiyun #endif
1286*4882a593Smuzhiyun 		}
1287*4882a593Smuzhiyun 	}
1288*4882a593Smuzhiyun 
1289*4882a593Smuzhiyun 	return SECCLASS_SOCKET;
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun 
selinux_genfs_get_sid(struct dentry * dentry,u16 tclass,u16 flags,u32 * sid)1292*4882a593Smuzhiyun static int selinux_genfs_get_sid(struct dentry *dentry,
1293*4882a593Smuzhiyun 				 u16 tclass,
1294*4882a593Smuzhiyun 				 u16 flags,
1295*4882a593Smuzhiyun 				 u32 *sid)
1296*4882a593Smuzhiyun {
1297*4882a593Smuzhiyun 	int rc;
1298*4882a593Smuzhiyun 	struct super_block *sb = dentry->d_sb;
1299*4882a593Smuzhiyun 	char *buffer, *path;
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	buffer = (char *)__get_free_page(GFP_KERNEL);
1302*4882a593Smuzhiyun 	if (!buffer)
1303*4882a593Smuzhiyun 		return -ENOMEM;
1304*4882a593Smuzhiyun 
1305*4882a593Smuzhiyun 	path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1306*4882a593Smuzhiyun 	if (IS_ERR(path))
1307*4882a593Smuzhiyun 		rc = PTR_ERR(path);
1308*4882a593Smuzhiyun 	else {
1309*4882a593Smuzhiyun 		if (flags & SE_SBPROC) {
1310*4882a593Smuzhiyun 			/* each process gets a /proc/PID/ entry. Strip off the
1311*4882a593Smuzhiyun 			 * PID part to get a valid selinux labeling.
1312*4882a593Smuzhiyun 			 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1313*4882a593Smuzhiyun 			while (path[1] >= '0' && path[1] <= '9') {
1314*4882a593Smuzhiyun 				path[1] = '/';
1315*4882a593Smuzhiyun 				path++;
1316*4882a593Smuzhiyun 			}
1317*4882a593Smuzhiyun 		}
1318*4882a593Smuzhiyun 		rc = security_genfs_sid(&selinux_state, sb->s_type->name,
1319*4882a593Smuzhiyun 					path, tclass, sid);
1320*4882a593Smuzhiyun 		if (rc == -ENOENT) {
1321*4882a593Smuzhiyun 			/* No match in policy, mark as unlabeled. */
1322*4882a593Smuzhiyun 			*sid = SECINITSID_UNLABELED;
1323*4882a593Smuzhiyun 			rc = 0;
1324*4882a593Smuzhiyun 		}
1325*4882a593Smuzhiyun 	}
1326*4882a593Smuzhiyun 	free_page((unsigned long)buffer);
1327*4882a593Smuzhiyun 	return rc;
1328*4882a593Smuzhiyun }
1329*4882a593Smuzhiyun 
inode_doinit_use_xattr(struct inode * inode,struct dentry * dentry,u32 def_sid,u32 * sid)1330*4882a593Smuzhiyun static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
1331*4882a593Smuzhiyun 				  u32 def_sid, u32 *sid)
1332*4882a593Smuzhiyun {
1333*4882a593Smuzhiyun #define INITCONTEXTLEN 255
1334*4882a593Smuzhiyun 	char *context;
1335*4882a593Smuzhiyun 	unsigned int len;
1336*4882a593Smuzhiyun 	int rc;
1337*4882a593Smuzhiyun 
1338*4882a593Smuzhiyun 	len = INITCONTEXTLEN;
1339*4882a593Smuzhiyun 	context = kmalloc(len + 1, GFP_NOFS);
1340*4882a593Smuzhiyun 	if (!context)
1341*4882a593Smuzhiyun 		return -ENOMEM;
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	context[len] = '\0';
1344*4882a593Smuzhiyun 	rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len,
1345*4882a593Smuzhiyun 			    XATTR_NOSECURITY);
1346*4882a593Smuzhiyun 	if (rc == -ERANGE) {
1347*4882a593Smuzhiyun 		kfree(context);
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 		/* Need a larger buffer.  Query for the right size. */
1350*4882a593Smuzhiyun 		rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0,
1351*4882a593Smuzhiyun 				    XATTR_NOSECURITY);
1352*4882a593Smuzhiyun 		if (rc < 0)
1353*4882a593Smuzhiyun 			return rc;
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun 		len = rc;
1356*4882a593Smuzhiyun 		context = kmalloc(len + 1, GFP_NOFS);
1357*4882a593Smuzhiyun 		if (!context)
1358*4882a593Smuzhiyun 			return -ENOMEM;
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun 		context[len] = '\0';
1361*4882a593Smuzhiyun 		rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
1362*4882a593Smuzhiyun 				    context, len, XATTR_NOSECURITY);
1363*4882a593Smuzhiyun 	}
1364*4882a593Smuzhiyun 	if (rc < 0) {
1365*4882a593Smuzhiyun 		kfree(context);
1366*4882a593Smuzhiyun 		if (rc != -ENODATA) {
1367*4882a593Smuzhiyun 			pr_warn("SELinux: %s:  getxattr returned %d for dev=%s ino=%ld\n",
1368*4882a593Smuzhiyun 				__func__, -rc, inode->i_sb->s_id, inode->i_ino);
1369*4882a593Smuzhiyun 			return rc;
1370*4882a593Smuzhiyun 		}
1371*4882a593Smuzhiyun 		*sid = def_sid;
1372*4882a593Smuzhiyun 		return 0;
1373*4882a593Smuzhiyun 	}
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	rc = security_context_to_sid_default(&selinux_state, context, rc, sid,
1376*4882a593Smuzhiyun 					     def_sid, GFP_NOFS);
1377*4882a593Smuzhiyun 	if (rc) {
1378*4882a593Smuzhiyun 		char *dev = inode->i_sb->s_id;
1379*4882a593Smuzhiyun 		unsigned long ino = inode->i_ino;
1380*4882a593Smuzhiyun 
1381*4882a593Smuzhiyun 		if (rc == -EINVAL) {
1382*4882a593Smuzhiyun 			pr_notice_ratelimited("SELinux: inode=%lu on dev=%s was found to have an invalid context=%s.  This indicates you may need to relabel the inode or the filesystem in question.\n",
1383*4882a593Smuzhiyun 					      ino, dev, context);
1384*4882a593Smuzhiyun 		} else {
1385*4882a593Smuzhiyun 			pr_warn("SELinux: %s:  context_to_sid(%s) returned %d for dev=%s ino=%ld\n",
1386*4882a593Smuzhiyun 				__func__, context, -rc, dev, ino);
1387*4882a593Smuzhiyun 		}
1388*4882a593Smuzhiyun 	}
1389*4882a593Smuzhiyun 	kfree(context);
1390*4882a593Smuzhiyun 	return 0;
1391*4882a593Smuzhiyun }
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun /* The inode's security attributes must be initialized before first use. */
inode_doinit_with_dentry(struct inode * inode,struct dentry * opt_dentry)1394*4882a593Smuzhiyun static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1395*4882a593Smuzhiyun {
1396*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = NULL;
1397*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
1398*4882a593Smuzhiyun 	u32 task_sid, sid = 0;
1399*4882a593Smuzhiyun 	u16 sclass;
1400*4882a593Smuzhiyun 	struct dentry *dentry;
1401*4882a593Smuzhiyun 	int rc = 0;
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun 	if (isec->initialized == LABEL_INITIALIZED)
1404*4882a593Smuzhiyun 		return 0;
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun 	spin_lock(&isec->lock);
1407*4882a593Smuzhiyun 	if (isec->initialized == LABEL_INITIALIZED)
1408*4882a593Smuzhiyun 		goto out_unlock;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	if (isec->sclass == SECCLASS_FILE)
1411*4882a593Smuzhiyun 		isec->sclass = inode_mode_to_security_class(inode->i_mode);
1412*4882a593Smuzhiyun 
1413*4882a593Smuzhiyun 	sbsec = inode->i_sb->s_security;
1414*4882a593Smuzhiyun 	if (!(sbsec->flags & SE_SBINITIALIZED)) {
1415*4882a593Smuzhiyun 		/* Defer initialization until selinux_complete_init,
1416*4882a593Smuzhiyun 		   after the initial policy is loaded and the security
1417*4882a593Smuzhiyun 		   server is ready to handle calls. */
1418*4882a593Smuzhiyun 		spin_lock(&sbsec->isec_lock);
1419*4882a593Smuzhiyun 		if (list_empty(&isec->list))
1420*4882a593Smuzhiyun 			list_add(&isec->list, &sbsec->isec_head);
1421*4882a593Smuzhiyun 		spin_unlock(&sbsec->isec_lock);
1422*4882a593Smuzhiyun 		goto out_unlock;
1423*4882a593Smuzhiyun 	}
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun 	sclass = isec->sclass;
1426*4882a593Smuzhiyun 	task_sid = isec->task_sid;
1427*4882a593Smuzhiyun 	sid = isec->sid;
1428*4882a593Smuzhiyun 	isec->initialized = LABEL_PENDING;
1429*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
1430*4882a593Smuzhiyun 
1431*4882a593Smuzhiyun 	switch (sbsec->behavior) {
1432*4882a593Smuzhiyun 	case SECURITY_FS_USE_NATIVE:
1433*4882a593Smuzhiyun 		break;
1434*4882a593Smuzhiyun 	case SECURITY_FS_USE_XATTR:
1435*4882a593Smuzhiyun 		if (!(inode->i_opflags & IOP_XATTR)) {
1436*4882a593Smuzhiyun 			sid = sbsec->def_sid;
1437*4882a593Smuzhiyun 			break;
1438*4882a593Smuzhiyun 		}
1439*4882a593Smuzhiyun 		/* Need a dentry, since the xattr API requires one.
1440*4882a593Smuzhiyun 		   Life would be simpler if we could just pass the inode. */
1441*4882a593Smuzhiyun 		if (opt_dentry) {
1442*4882a593Smuzhiyun 			/* Called from d_instantiate or d_splice_alias. */
1443*4882a593Smuzhiyun 			dentry = dget(opt_dentry);
1444*4882a593Smuzhiyun 		} else {
1445*4882a593Smuzhiyun 			/*
1446*4882a593Smuzhiyun 			 * Called from selinux_complete_init, try to find a dentry.
1447*4882a593Smuzhiyun 			 * Some filesystems really want a connected one, so try
1448*4882a593Smuzhiyun 			 * that first.  We could split SECURITY_FS_USE_XATTR in
1449*4882a593Smuzhiyun 			 * two, depending upon that...
1450*4882a593Smuzhiyun 			 */
1451*4882a593Smuzhiyun 			dentry = d_find_alias(inode);
1452*4882a593Smuzhiyun 			if (!dentry)
1453*4882a593Smuzhiyun 				dentry = d_find_any_alias(inode);
1454*4882a593Smuzhiyun 		}
1455*4882a593Smuzhiyun 		if (!dentry) {
1456*4882a593Smuzhiyun 			/*
1457*4882a593Smuzhiyun 			 * this is can be hit on boot when a file is accessed
1458*4882a593Smuzhiyun 			 * before the policy is loaded.  When we load policy we
1459*4882a593Smuzhiyun 			 * may find inodes that have no dentry on the
1460*4882a593Smuzhiyun 			 * sbsec->isec_head list.  No reason to complain as these
1461*4882a593Smuzhiyun 			 * will get fixed up the next time we go through
1462*4882a593Smuzhiyun 			 * inode_doinit with a dentry, before these inodes could
1463*4882a593Smuzhiyun 			 * be used again by userspace.
1464*4882a593Smuzhiyun 			 */
1465*4882a593Smuzhiyun 			goto out_invalid;
1466*4882a593Smuzhiyun 		}
1467*4882a593Smuzhiyun 
1468*4882a593Smuzhiyun 		rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
1469*4882a593Smuzhiyun 					    &sid);
1470*4882a593Smuzhiyun 		dput(dentry);
1471*4882a593Smuzhiyun 		if (rc)
1472*4882a593Smuzhiyun 			goto out;
1473*4882a593Smuzhiyun 		break;
1474*4882a593Smuzhiyun 	case SECURITY_FS_USE_TASK:
1475*4882a593Smuzhiyun 		sid = task_sid;
1476*4882a593Smuzhiyun 		break;
1477*4882a593Smuzhiyun 	case SECURITY_FS_USE_TRANS:
1478*4882a593Smuzhiyun 		/* Default to the fs SID. */
1479*4882a593Smuzhiyun 		sid = sbsec->sid;
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun 		/* Try to obtain a transition SID. */
1482*4882a593Smuzhiyun 		rc = security_transition_sid(&selinux_state, task_sid, sid,
1483*4882a593Smuzhiyun 					     sclass, NULL, &sid);
1484*4882a593Smuzhiyun 		if (rc)
1485*4882a593Smuzhiyun 			goto out;
1486*4882a593Smuzhiyun 		break;
1487*4882a593Smuzhiyun 	case SECURITY_FS_USE_MNTPOINT:
1488*4882a593Smuzhiyun 		sid = sbsec->mntpoint_sid;
1489*4882a593Smuzhiyun 		break;
1490*4882a593Smuzhiyun 	default:
1491*4882a593Smuzhiyun 		/* Default to the fs superblock SID. */
1492*4882a593Smuzhiyun 		sid = sbsec->sid;
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 		if ((sbsec->flags & SE_SBGENFS) &&
1495*4882a593Smuzhiyun 		     (!S_ISLNK(inode->i_mode) ||
1496*4882a593Smuzhiyun 		      selinux_policycap_genfs_seclabel_symlinks())) {
1497*4882a593Smuzhiyun 			/* We must have a dentry to determine the label on
1498*4882a593Smuzhiyun 			 * procfs inodes */
1499*4882a593Smuzhiyun 			if (opt_dentry) {
1500*4882a593Smuzhiyun 				/* Called from d_instantiate or
1501*4882a593Smuzhiyun 				 * d_splice_alias. */
1502*4882a593Smuzhiyun 				dentry = dget(opt_dentry);
1503*4882a593Smuzhiyun 			} else {
1504*4882a593Smuzhiyun 				/* Called from selinux_complete_init, try to
1505*4882a593Smuzhiyun 				 * find a dentry.  Some filesystems really want
1506*4882a593Smuzhiyun 				 * a connected one, so try that first.
1507*4882a593Smuzhiyun 				 */
1508*4882a593Smuzhiyun 				dentry = d_find_alias(inode);
1509*4882a593Smuzhiyun 				if (!dentry)
1510*4882a593Smuzhiyun 					dentry = d_find_any_alias(inode);
1511*4882a593Smuzhiyun 			}
1512*4882a593Smuzhiyun 			/*
1513*4882a593Smuzhiyun 			 * This can be hit on boot when a file is accessed
1514*4882a593Smuzhiyun 			 * before the policy is loaded.  When we load policy we
1515*4882a593Smuzhiyun 			 * may find inodes that have no dentry on the
1516*4882a593Smuzhiyun 			 * sbsec->isec_head list.  No reason to complain as
1517*4882a593Smuzhiyun 			 * these will get fixed up the next time we go through
1518*4882a593Smuzhiyun 			 * inode_doinit() with a dentry, before these inodes
1519*4882a593Smuzhiyun 			 * could be used again by userspace.
1520*4882a593Smuzhiyun 			 */
1521*4882a593Smuzhiyun 			if (!dentry)
1522*4882a593Smuzhiyun 				goto out_invalid;
1523*4882a593Smuzhiyun 			rc = selinux_genfs_get_sid(dentry, sclass,
1524*4882a593Smuzhiyun 						   sbsec->flags, &sid);
1525*4882a593Smuzhiyun 			if (rc) {
1526*4882a593Smuzhiyun 				dput(dentry);
1527*4882a593Smuzhiyun 				goto out;
1528*4882a593Smuzhiyun 			}
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun 			if ((sbsec->flags & SE_SBGENFS_XATTR) &&
1531*4882a593Smuzhiyun 			    (inode->i_opflags & IOP_XATTR)) {
1532*4882a593Smuzhiyun 				rc = inode_doinit_use_xattr(inode, dentry,
1533*4882a593Smuzhiyun 							    sid, &sid);
1534*4882a593Smuzhiyun 				if (rc) {
1535*4882a593Smuzhiyun 					dput(dentry);
1536*4882a593Smuzhiyun 					goto out;
1537*4882a593Smuzhiyun 				}
1538*4882a593Smuzhiyun 			}
1539*4882a593Smuzhiyun 			dput(dentry);
1540*4882a593Smuzhiyun 		}
1541*4882a593Smuzhiyun 		break;
1542*4882a593Smuzhiyun 	}
1543*4882a593Smuzhiyun 
1544*4882a593Smuzhiyun out:
1545*4882a593Smuzhiyun 	spin_lock(&isec->lock);
1546*4882a593Smuzhiyun 	if (isec->initialized == LABEL_PENDING) {
1547*4882a593Smuzhiyun 		if (rc) {
1548*4882a593Smuzhiyun 			isec->initialized = LABEL_INVALID;
1549*4882a593Smuzhiyun 			goto out_unlock;
1550*4882a593Smuzhiyun 		}
1551*4882a593Smuzhiyun 		isec->initialized = LABEL_INITIALIZED;
1552*4882a593Smuzhiyun 		isec->sid = sid;
1553*4882a593Smuzhiyun 	}
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun out_unlock:
1556*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
1557*4882a593Smuzhiyun 	return rc;
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun out_invalid:
1560*4882a593Smuzhiyun 	spin_lock(&isec->lock);
1561*4882a593Smuzhiyun 	if (isec->initialized == LABEL_PENDING) {
1562*4882a593Smuzhiyun 		isec->initialized = LABEL_INVALID;
1563*4882a593Smuzhiyun 		isec->sid = sid;
1564*4882a593Smuzhiyun 	}
1565*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
1566*4882a593Smuzhiyun 	return 0;
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun 
1569*4882a593Smuzhiyun /* Convert a Linux signal to an access vector. */
signal_to_av(int sig)1570*4882a593Smuzhiyun static inline u32 signal_to_av(int sig)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun 	u32 perm = 0;
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun 	switch (sig) {
1575*4882a593Smuzhiyun 	case SIGCHLD:
1576*4882a593Smuzhiyun 		/* Commonly granted from child to parent. */
1577*4882a593Smuzhiyun 		perm = PROCESS__SIGCHLD;
1578*4882a593Smuzhiyun 		break;
1579*4882a593Smuzhiyun 	case SIGKILL:
1580*4882a593Smuzhiyun 		/* Cannot be caught or ignored */
1581*4882a593Smuzhiyun 		perm = PROCESS__SIGKILL;
1582*4882a593Smuzhiyun 		break;
1583*4882a593Smuzhiyun 	case SIGSTOP:
1584*4882a593Smuzhiyun 		/* Cannot be caught or ignored */
1585*4882a593Smuzhiyun 		perm = PROCESS__SIGSTOP;
1586*4882a593Smuzhiyun 		break;
1587*4882a593Smuzhiyun 	default:
1588*4882a593Smuzhiyun 		/* All other signals. */
1589*4882a593Smuzhiyun 		perm = PROCESS__SIGNAL;
1590*4882a593Smuzhiyun 		break;
1591*4882a593Smuzhiyun 	}
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun 	return perm;
1594*4882a593Smuzhiyun }
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun #if CAP_LAST_CAP > 63
1597*4882a593Smuzhiyun #error Fix SELinux to handle capabilities > 63.
1598*4882a593Smuzhiyun #endif
1599*4882a593Smuzhiyun 
1600*4882a593Smuzhiyun /* Check whether a task is allowed to use a capability. */
cred_has_capability(const struct cred * cred,int cap,unsigned int opts,bool initns)1601*4882a593Smuzhiyun static int cred_has_capability(const struct cred *cred,
1602*4882a593Smuzhiyun 			       int cap, unsigned int opts, bool initns)
1603*4882a593Smuzhiyun {
1604*4882a593Smuzhiyun 	struct common_audit_data ad;
1605*4882a593Smuzhiyun 	struct av_decision avd;
1606*4882a593Smuzhiyun 	u16 sclass;
1607*4882a593Smuzhiyun 	u32 sid = cred_sid(cred);
1608*4882a593Smuzhiyun 	u32 av = CAP_TO_MASK(cap);
1609*4882a593Smuzhiyun 	int rc;
1610*4882a593Smuzhiyun 
1611*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_CAP;
1612*4882a593Smuzhiyun 	ad.u.cap = cap;
1613*4882a593Smuzhiyun 
1614*4882a593Smuzhiyun 	switch (CAP_TO_INDEX(cap)) {
1615*4882a593Smuzhiyun 	case 0:
1616*4882a593Smuzhiyun 		sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
1617*4882a593Smuzhiyun 		break;
1618*4882a593Smuzhiyun 	case 1:
1619*4882a593Smuzhiyun 		sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
1620*4882a593Smuzhiyun 		break;
1621*4882a593Smuzhiyun 	default:
1622*4882a593Smuzhiyun 		pr_err("SELinux:  out of range capability %d\n", cap);
1623*4882a593Smuzhiyun 		BUG();
1624*4882a593Smuzhiyun 		return -EINVAL;
1625*4882a593Smuzhiyun 	}
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	rc = avc_has_perm_noaudit(&selinux_state,
1628*4882a593Smuzhiyun 				  sid, sid, sclass, av, 0, &avd);
1629*4882a593Smuzhiyun 	if (!(opts & CAP_OPT_NOAUDIT)) {
1630*4882a593Smuzhiyun 		int rc2 = avc_audit(&selinux_state,
1631*4882a593Smuzhiyun 				    sid, sid, sclass, av, &avd, rc, &ad, 0);
1632*4882a593Smuzhiyun 		if (rc2)
1633*4882a593Smuzhiyun 			return rc2;
1634*4882a593Smuzhiyun 	}
1635*4882a593Smuzhiyun 	return rc;
1636*4882a593Smuzhiyun }
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun /* Check whether a task has a particular permission to an inode.
1639*4882a593Smuzhiyun    The 'adp' parameter is optional and allows other audit
1640*4882a593Smuzhiyun    data to be passed (e.g. the dentry). */
inode_has_perm(const struct cred * cred,struct inode * inode,u32 perms,struct common_audit_data * adp)1641*4882a593Smuzhiyun static int inode_has_perm(const struct cred *cred,
1642*4882a593Smuzhiyun 			  struct inode *inode,
1643*4882a593Smuzhiyun 			  u32 perms,
1644*4882a593Smuzhiyun 			  struct common_audit_data *adp)
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun 	struct inode_security_struct *isec;
1647*4882a593Smuzhiyun 	u32 sid;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 	validate_creds(cred);
1650*4882a593Smuzhiyun 
1651*4882a593Smuzhiyun 	if (unlikely(IS_PRIVATE(inode)))
1652*4882a593Smuzhiyun 		return 0;
1653*4882a593Smuzhiyun 
1654*4882a593Smuzhiyun 	sid = cred_sid(cred);
1655*4882a593Smuzhiyun 	isec = selinux_inode(inode);
1656*4882a593Smuzhiyun 
1657*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
1658*4882a593Smuzhiyun 			    sid, isec->sid, isec->sclass, perms, adp);
1659*4882a593Smuzhiyun }
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun /* Same as inode_has_perm, but pass explicit audit data containing
1662*4882a593Smuzhiyun    the dentry to help the auditing code to more easily generate the
1663*4882a593Smuzhiyun    pathname if needed. */
dentry_has_perm(const struct cred * cred,struct dentry * dentry,u32 av)1664*4882a593Smuzhiyun static inline int dentry_has_perm(const struct cred *cred,
1665*4882a593Smuzhiyun 				  struct dentry *dentry,
1666*4882a593Smuzhiyun 				  u32 av)
1667*4882a593Smuzhiyun {
1668*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
1669*4882a593Smuzhiyun 	struct common_audit_data ad;
1670*4882a593Smuzhiyun 
1671*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
1672*4882a593Smuzhiyun 	ad.u.dentry = dentry;
1673*4882a593Smuzhiyun 	__inode_security_revalidate(inode, dentry, true);
1674*4882a593Smuzhiyun 	return inode_has_perm(cred, inode, av, &ad);
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun /* Same as inode_has_perm, but pass explicit audit data containing
1678*4882a593Smuzhiyun    the path to help the auditing code to more easily generate the
1679*4882a593Smuzhiyun    pathname if needed. */
path_has_perm(const struct cred * cred,const struct path * path,u32 av)1680*4882a593Smuzhiyun static inline int path_has_perm(const struct cred *cred,
1681*4882a593Smuzhiyun 				const struct path *path,
1682*4882a593Smuzhiyun 				u32 av)
1683*4882a593Smuzhiyun {
1684*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(path->dentry);
1685*4882a593Smuzhiyun 	struct common_audit_data ad;
1686*4882a593Smuzhiyun 
1687*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_PATH;
1688*4882a593Smuzhiyun 	ad.u.path = *path;
1689*4882a593Smuzhiyun 	__inode_security_revalidate(inode, path->dentry, true);
1690*4882a593Smuzhiyun 	return inode_has_perm(cred, inode, av, &ad);
1691*4882a593Smuzhiyun }
1692*4882a593Smuzhiyun 
1693*4882a593Smuzhiyun /* Same as path_has_perm, but uses the inode from the file struct. */
file_path_has_perm(const struct cred * cred,struct file * file,u32 av)1694*4882a593Smuzhiyun static inline int file_path_has_perm(const struct cred *cred,
1695*4882a593Smuzhiyun 				     struct file *file,
1696*4882a593Smuzhiyun 				     u32 av)
1697*4882a593Smuzhiyun {
1698*4882a593Smuzhiyun 	struct common_audit_data ad;
1699*4882a593Smuzhiyun 
1700*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_FILE;
1701*4882a593Smuzhiyun 	ad.u.file = file;
1702*4882a593Smuzhiyun 	return inode_has_perm(cred, file_inode(file), av, &ad);
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun 
1705*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
1706*4882a593Smuzhiyun static int bpf_fd_pass(struct file *file, u32 sid);
1707*4882a593Smuzhiyun #endif
1708*4882a593Smuzhiyun 
1709*4882a593Smuzhiyun /* Check whether a task can use an open file descriptor to
1710*4882a593Smuzhiyun    access an inode in a given way.  Check access to the
1711*4882a593Smuzhiyun    descriptor itself, and then use dentry_has_perm to
1712*4882a593Smuzhiyun    check a particular permission to the file.
1713*4882a593Smuzhiyun    Access to the descriptor is implicitly granted if it
1714*4882a593Smuzhiyun    has the same SID as the process.  If av is zero, then
1715*4882a593Smuzhiyun    access to the file is not checked, e.g. for cases
1716*4882a593Smuzhiyun    where only the descriptor is affected like seek. */
file_has_perm(const struct cred * cred,struct file * file,u32 av)1717*4882a593Smuzhiyun static int file_has_perm(const struct cred *cred,
1718*4882a593Smuzhiyun 			 struct file *file,
1719*4882a593Smuzhiyun 			 u32 av)
1720*4882a593Smuzhiyun {
1721*4882a593Smuzhiyun 	struct file_security_struct *fsec = selinux_file(file);
1722*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
1723*4882a593Smuzhiyun 	struct common_audit_data ad;
1724*4882a593Smuzhiyun 	u32 sid = cred_sid(cred);
1725*4882a593Smuzhiyun 	int rc;
1726*4882a593Smuzhiyun 
1727*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_FILE;
1728*4882a593Smuzhiyun 	ad.u.file = file;
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun 	if (sid != fsec->sid) {
1731*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
1732*4882a593Smuzhiyun 				  sid, fsec->sid,
1733*4882a593Smuzhiyun 				  SECCLASS_FD,
1734*4882a593Smuzhiyun 				  FD__USE,
1735*4882a593Smuzhiyun 				  &ad);
1736*4882a593Smuzhiyun 		if (rc)
1737*4882a593Smuzhiyun 			goto out;
1738*4882a593Smuzhiyun 	}
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
1741*4882a593Smuzhiyun 	rc = bpf_fd_pass(file, cred_sid(cred));
1742*4882a593Smuzhiyun 	if (rc)
1743*4882a593Smuzhiyun 		return rc;
1744*4882a593Smuzhiyun #endif
1745*4882a593Smuzhiyun 
1746*4882a593Smuzhiyun 	/* av is zero if only checking access to the descriptor. */
1747*4882a593Smuzhiyun 	rc = 0;
1748*4882a593Smuzhiyun 	if (av)
1749*4882a593Smuzhiyun 		rc = inode_has_perm(cred, inode, av, &ad);
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun out:
1752*4882a593Smuzhiyun 	return rc;
1753*4882a593Smuzhiyun }
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun /*
1756*4882a593Smuzhiyun  * Determine the label for an inode that might be unioned.
1757*4882a593Smuzhiyun  */
1758*4882a593Smuzhiyun static int
selinux_determine_inode_label(const struct task_security_struct * tsec,struct inode * dir,const struct qstr * name,u16 tclass,u32 * _new_isid)1759*4882a593Smuzhiyun selinux_determine_inode_label(const struct task_security_struct *tsec,
1760*4882a593Smuzhiyun 				 struct inode *dir,
1761*4882a593Smuzhiyun 				 const struct qstr *name, u16 tclass,
1762*4882a593Smuzhiyun 				 u32 *_new_isid)
1763*4882a593Smuzhiyun {
1764*4882a593Smuzhiyun 	const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1765*4882a593Smuzhiyun 
1766*4882a593Smuzhiyun 	if ((sbsec->flags & SE_SBINITIALIZED) &&
1767*4882a593Smuzhiyun 	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1768*4882a593Smuzhiyun 		*_new_isid = sbsec->mntpoint_sid;
1769*4882a593Smuzhiyun 	} else if ((sbsec->flags & SBLABEL_MNT) &&
1770*4882a593Smuzhiyun 		   tsec->create_sid) {
1771*4882a593Smuzhiyun 		*_new_isid = tsec->create_sid;
1772*4882a593Smuzhiyun 	} else {
1773*4882a593Smuzhiyun 		const struct inode_security_struct *dsec = inode_security(dir);
1774*4882a593Smuzhiyun 		return security_transition_sid(&selinux_state, tsec->sid,
1775*4882a593Smuzhiyun 					       dsec->sid, tclass,
1776*4882a593Smuzhiyun 					       name, _new_isid);
1777*4882a593Smuzhiyun 	}
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun 	return 0;
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun /* Check whether a task can create a file. */
may_create(struct inode * dir,struct dentry * dentry,u16 tclass)1783*4882a593Smuzhiyun static int may_create(struct inode *dir,
1784*4882a593Smuzhiyun 		      struct dentry *dentry,
1785*4882a593Smuzhiyun 		      u16 tclass)
1786*4882a593Smuzhiyun {
1787*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
1788*4882a593Smuzhiyun 	struct inode_security_struct *dsec;
1789*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
1790*4882a593Smuzhiyun 	u32 sid, newsid;
1791*4882a593Smuzhiyun 	struct common_audit_data ad;
1792*4882a593Smuzhiyun 	int rc;
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun 	dsec = inode_security(dir);
1795*4882a593Smuzhiyun 	sbsec = dir->i_sb->s_security;
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun 	sid = tsec->sid;
1798*4882a593Smuzhiyun 
1799*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
1800*4882a593Smuzhiyun 	ad.u.dentry = dentry;
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1803*4882a593Smuzhiyun 			  sid, dsec->sid, SECCLASS_DIR,
1804*4882a593Smuzhiyun 			  DIR__ADD_NAME | DIR__SEARCH,
1805*4882a593Smuzhiyun 			  &ad);
1806*4882a593Smuzhiyun 	if (rc)
1807*4882a593Smuzhiyun 		return rc;
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 	rc = selinux_determine_inode_label(tsec, dir, &dentry->d_name, tclass,
1810*4882a593Smuzhiyun 					   &newsid);
1811*4882a593Smuzhiyun 	if (rc)
1812*4882a593Smuzhiyun 		return rc;
1813*4882a593Smuzhiyun 
1814*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1815*4882a593Smuzhiyun 			  sid, newsid, tclass, FILE__CREATE, &ad);
1816*4882a593Smuzhiyun 	if (rc)
1817*4882a593Smuzhiyun 		return rc;
1818*4882a593Smuzhiyun 
1819*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
1820*4882a593Smuzhiyun 			    newsid, sbsec->sid,
1821*4882a593Smuzhiyun 			    SECCLASS_FILESYSTEM,
1822*4882a593Smuzhiyun 			    FILESYSTEM__ASSOCIATE, &ad);
1823*4882a593Smuzhiyun }
1824*4882a593Smuzhiyun 
1825*4882a593Smuzhiyun #define MAY_LINK	0
1826*4882a593Smuzhiyun #define MAY_UNLINK	1
1827*4882a593Smuzhiyun #define MAY_RMDIR	2
1828*4882a593Smuzhiyun 
1829*4882a593Smuzhiyun /* Check whether a task can link, unlink, or rmdir a file/directory. */
may_link(struct inode * dir,struct dentry * dentry,int kind)1830*4882a593Smuzhiyun static int may_link(struct inode *dir,
1831*4882a593Smuzhiyun 		    struct dentry *dentry,
1832*4882a593Smuzhiyun 		    int kind)
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun {
1835*4882a593Smuzhiyun 	struct inode_security_struct *dsec, *isec;
1836*4882a593Smuzhiyun 	struct common_audit_data ad;
1837*4882a593Smuzhiyun 	u32 sid = current_sid();
1838*4882a593Smuzhiyun 	u32 av;
1839*4882a593Smuzhiyun 	int rc;
1840*4882a593Smuzhiyun 
1841*4882a593Smuzhiyun 	dsec = inode_security(dir);
1842*4882a593Smuzhiyun 	isec = backing_inode_security(dentry);
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
1845*4882a593Smuzhiyun 	ad.u.dentry = dentry;
1846*4882a593Smuzhiyun 
1847*4882a593Smuzhiyun 	av = DIR__SEARCH;
1848*4882a593Smuzhiyun 	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1849*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1850*4882a593Smuzhiyun 			  sid, dsec->sid, SECCLASS_DIR, av, &ad);
1851*4882a593Smuzhiyun 	if (rc)
1852*4882a593Smuzhiyun 		return rc;
1853*4882a593Smuzhiyun 
1854*4882a593Smuzhiyun 	switch (kind) {
1855*4882a593Smuzhiyun 	case MAY_LINK:
1856*4882a593Smuzhiyun 		av = FILE__LINK;
1857*4882a593Smuzhiyun 		break;
1858*4882a593Smuzhiyun 	case MAY_UNLINK:
1859*4882a593Smuzhiyun 		av = FILE__UNLINK;
1860*4882a593Smuzhiyun 		break;
1861*4882a593Smuzhiyun 	case MAY_RMDIR:
1862*4882a593Smuzhiyun 		av = DIR__RMDIR;
1863*4882a593Smuzhiyun 		break;
1864*4882a593Smuzhiyun 	default:
1865*4882a593Smuzhiyun 		pr_warn("SELinux: %s:  unrecognized kind %d\n",
1866*4882a593Smuzhiyun 			__func__, kind);
1867*4882a593Smuzhiyun 		return 0;
1868*4882a593Smuzhiyun 	}
1869*4882a593Smuzhiyun 
1870*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1871*4882a593Smuzhiyun 			  sid, isec->sid, isec->sclass, av, &ad);
1872*4882a593Smuzhiyun 	return rc;
1873*4882a593Smuzhiyun }
1874*4882a593Smuzhiyun 
may_rename(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry)1875*4882a593Smuzhiyun static inline int may_rename(struct inode *old_dir,
1876*4882a593Smuzhiyun 			     struct dentry *old_dentry,
1877*4882a593Smuzhiyun 			     struct inode *new_dir,
1878*4882a593Smuzhiyun 			     struct dentry *new_dentry)
1879*4882a593Smuzhiyun {
1880*4882a593Smuzhiyun 	struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1881*4882a593Smuzhiyun 	struct common_audit_data ad;
1882*4882a593Smuzhiyun 	u32 sid = current_sid();
1883*4882a593Smuzhiyun 	u32 av;
1884*4882a593Smuzhiyun 	int old_is_dir, new_is_dir;
1885*4882a593Smuzhiyun 	int rc;
1886*4882a593Smuzhiyun 
1887*4882a593Smuzhiyun 	old_dsec = inode_security(old_dir);
1888*4882a593Smuzhiyun 	old_isec = backing_inode_security(old_dentry);
1889*4882a593Smuzhiyun 	old_is_dir = d_is_dir(old_dentry);
1890*4882a593Smuzhiyun 	new_dsec = inode_security(new_dir);
1891*4882a593Smuzhiyun 
1892*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
1893*4882a593Smuzhiyun 
1894*4882a593Smuzhiyun 	ad.u.dentry = old_dentry;
1895*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1896*4882a593Smuzhiyun 			  sid, old_dsec->sid, SECCLASS_DIR,
1897*4882a593Smuzhiyun 			  DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1898*4882a593Smuzhiyun 	if (rc)
1899*4882a593Smuzhiyun 		return rc;
1900*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1901*4882a593Smuzhiyun 			  sid, old_isec->sid,
1902*4882a593Smuzhiyun 			  old_isec->sclass, FILE__RENAME, &ad);
1903*4882a593Smuzhiyun 	if (rc)
1904*4882a593Smuzhiyun 		return rc;
1905*4882a593Smuzhiyun 	if (old_is_dir && new_dir != old_dir) {
1906*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
1907*4882a593Smuzhiyun 				  sid, old_isec->sid,
1908*4882a593Smuzhiyun 				  old_isec->sclass, DIR__REPARENT, &ad);
1909*4882a593Smuzhiyun 		if (rc)
1910*4882a593Smuzhiyun 			return rc;
1911*4882a593Smuzhiyun 	}
1912*4882a593Smuzhiyun 
1913*4882a593Smuzhiyun 	ad.u.dentry = new_dentry;
1914*4882a593Smuzhiyun 	av = DIR__ADD_NAME | DIR__SEARCH;
1915*4882a593Smuzhiyun 	if (d_is_positive(new_dentry))
1916*4882a593Smuzhiyun 		av |= DIR__REMOVE_NAME;
1917*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
1918*4882a593Smuzhiyun 			  sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1919*4882a593Smuzhiyun 	if (rc)
1920*4882a593Smuzhiyun 		return rc;
1921*4882a593Smuzhiyun 	if (d_is_positive(new_dentry)) {
1922*4882a593Smuzhiyun 		new_isec = backing_inode_security(new_dentry);
1923*4882a593Smuzhiyun 		new_is_dir = d_is_dir(new_dentry);
1924*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
1925*4882a593Smuzhiyun 				  sid, new_isec->sid,
1926*4882a593Smuzhiyun 				  new_isec->sclass,
1927*4882a593Smuzhiyun 				  (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1928*4882a593Smuzhiyun 		if (rc)
1929*4882a593Smuzhiyun 			return rc;
1930*4882a593Smuzhiyun 	}
1931*4882a593Smuzhiyun 
1932*4882a593Smuzhiyun 	return 0;
1933*4882a593Smuzhiyun }
1934*4882a593Smuzhiyun 
1935*4882a593Smuzhiyun /* Check whether a task can perform a filesystem operation. */
superblock_has_perm(const struct cred * cred,struct super_block * sb,u32 perms,struct common_audit_data * ad)1936*4882a593Smuzhiyun static int superblock_has_perm(const struct cred *cred,
1937*4882a593Smuzhiyun 			       struct super_block *sb,
1938*4882a593Smuzhiyun 			       u32 perms,
1939*4882a593Smuzhiyun 			       struct common_audit_data *ad)
1940*4882a593Smuzhiyun {
1941*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
1942*4882a593Smuzhiyun 	u32 sid = cred_sid(cred);
1943*4882a593Smuzhiyun 
1944*4882a593Smuzhiyun 	sbsec = sb->s_security;
1945*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
1946*4882a593Smuzhiyun 			    sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
1947*4882a593Smuzhiyun }
1948*4882a593Smuzhiyun 
1949*4882a593Smuzhiyun /* Convert a Linux mode and permission mask to an access vector. */
file_mask_to_av(int mode,int mask)1950*4882a593Smuzhiyun static inline u32 file_mask_to_av(int mode, int mask)
1951*4882a593Smuzhiyun {
1952*4882a593Smuzhiyun 	u32 av = 0;
1953*4882a593Smuzhiyun 
1954*4882a593Smuzhiyun 	if (!S_ISDIR(mode)) {
1955*4882a593Smuzhiyun 		if (mask & MAY_EXEC)
1956*4882a593Smuzhiyun 			av |= FILE__EXECUTE;
1957*4882a593Smuzhiyun 		if (mask & MAY_READ)
1958*4882a593Smuzhiyun 			av |= FILE__READ;
1959*4882a593Smuzhiyun 
1960*4882a593Smuzhiyun 		if (mask & MAY_APPEND)
1961*4882a593Smuzhiyun 			av |= FILE__APPEND;
1962*4882a593Smuzhiyun 		else if (mask & MAY_WRITE)
1963*4882a593Smuzhiyun 			av |= FILE__WRITE;
1964*4882a593Smuzhiyun 
1965*4882a593Smuzhiyun 	} else {
1966*4882a593Smuzhiyun 		if (mask & MAY_EXEC)
1967*4882a593Smuzhiyun 			av |= DIR__SEARCH;
1968*4882a593Smuzhiyun 		if (mask & MAY_WRITE)
1969*4882a593Smuzhiyun 			av |= DIR__WRITE;
1970*4882a593Smuzhiyun 		if (mask & MAY_READ)
1971*4882a593Smuzhiyun 			av |= DIR__READ;
1972*4882a593Smuzhiyun 	}
1973*4882a593Smuzhiyun 
1974*4882a593Smuzhiyun 	return av;
1975*4882a593Smuzhiyun }
1976*4882a593Smuzhiyun 
1977*4882a593Smuzhiyun /* Convert a Linux file to an access vector. */
file_to_av(struct file * file)1978*4882a593Smuzhiyun static inline u32 file_to_av(struct file *file)
1979*4882a593Smuzhiyun {
1980*4882a593Smuzhiyun 	u32 av = 0;
1981*4882a593Smuzhiyun 
1982*4882a593Smuzhiyun 	if (file->f_mode & FMODE_READ)
1983*4882a593Smuzhiyun 		av |= FILE__READ;
1984*4882a593Smuzhiyun 	if (file->f_mode & FMODE_WRITE) {
1985*4882a593Smuzhiyun 		if (file->f_flags & O_APPEND)
1986*4882a593Smuzhiyun 			av |= FILE__APPEND;
1987*4882a593Smuzhiyun 		else
1988*4882a593Smuzhiyun 			av |= FILE__WRITE;
1989*4882a593Smuzhiyun 	}
1990*4882a593Smuzhiyun 	if (!av) {
1991*4882a593Smuzhiyun 		/*
1992*4882a593Smuzhiyun 		 * Special file opened with flags 3 for ioctl-only use.
1993*4882a593Smuzhiyun 		 */
1994*4882a593Smuzhiyun 		av = FILE__IOCTL;
1995*4882a593Smuzhiyun 	}
1996*4882a593Smuzhiyun 
1997*4882a593Smuzhiyun 	return av;
1998*4882a593Smuzhiyun }
1999*4882a593Smuzhiyun 
2000*4882a593Smuzhiyun /*
2001*4882a593Smuzhiyun  * Convert a file to an access vector and include the correct
2002*4882a593Smuzhiyun  * open permission.
2003*4882a593Smuzhiyun  */
open_file_to_av(struct file * file)2004*4882a593Smuzhiyun static inline u32 open_file_to_av(struct file *file)
2005*4882a593Smuzhiyun {
2006*4882a593Smuzhiyun 	u32 av = file_to_av(file);
2007*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
2008*4882a593Smuzhiyun 
2009*4882a593Smuzhiyun 	if (selinux_policycap_openperm() &&
2010*4882a593Smuzhiyun 	    inode->i_sb->s_magic != SOCKFS_MAGIC)
2011*4882a593Smuzhiyun 		av |= FILE__OPEN;
2012*4882a593Smuzhiyun 
2013*4882a593Smuzhiyun 	return av;
2014*4882a593Smuzhiyun }
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun /* Hook functions begin here. */
2017*4882a593Smuzhiyun 
selinux_binder_set_context_mgr(const struct cred * mgr)2018*4882a593Smuzhiyun static int selinux_binder_set_context_mgr(const struct cred *mgr)
2019*4882a593Smuzhiyun {
2020*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2021*4882a593Smuzhiyun 			    current_sid(), cred_sid(mgr), SECCLASS_BINDER,
2022*4882a593Smuzhiyun 			    BINDER__SET_CONTEXT_MGR, NULL);
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun 
selinux_binder_transaction(const struct cred * from,const struct cred * to)2025*4882a593Smuzhiyun static int selinux_binder_transaction(const struct cred *from,
2026*4882a593Smuzhiyun 				      const struct cred *to)
2027*4882a593Smuzhiyun {
2028*4882a593Smuzhiyun 	u32 mysid = current_sid();
2029*4882a593Smuzhiyun 	u32 fromsid = cred_sid(from);
2030*4882a593Smuzhiyun 	u32 tosid = cred_sid(to);
2031*4882a593Smuzhiyun 	int rc;
2032*4882a593Smuzhiyun 
2033*4882a593Smuzhiyun 	if (mysid != fromsid) {
2034*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2035*4882a593Smuzhiyun 				  mysid, fromsid, SECCLASS_BINDER,
2036*4882a593Smuzhiyun 				  BINDER__IMPERSONATE, NULL);
2037*4882a593Smuzhiyun 		if (rc)
2038*4882a593Smuzhiyun 			return rc;
2039*4882a593Smuzhiyun 	}
2040*4882a593Smuzhiyun 
2041*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state, fromsid, tosid,
2042*4882a593Smuzhiyun 			    SECCLASS_BINDER, BINDER__CALL, NULL);
2043*4882a593Smuzhiyun }
2044*4882a593Smuzhiyun 
selinux_binder_transfer_binder(const struct cred * from,const struct cred * to)2045*4882a593Smuzhiyun static int selinux_binder_transfer_binder(const struct cred *from,
2046*4882a593Smuzhiyun 					  const struct cred *to)
2047*4882a593Smuzhiyun {
2048*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2049*4882a593Smuzhiyun 			    cred_sid(from), cred_sid(to),
2050*4882a593Smuzhiyun 			    SECCLASS_BINDER, BINDER__TRANSFER,
2051*4882a593Smuzhiyun 			    NULL);
2052*4882a593Smuzhiyun }
2053*4882a593Smuzhiyun 
selinux_binder_transfer_file(const struct cred * from,const struct cred * to,struct file * file)2054*4882a593Smuzhiyun static int selinux_binder_transfer_file(const struct cred *from,
2055*4882a593Smuzhiyun 					const struct cred *to,
2056*4882a593Smuzhiyun 					struct file *file)
2057*4882a593Smuzhiyun {
2058*4882a593Smuzhiyun 	u32 sid = cred_sid(to);
2059*4882a593Smuzhiyun 	struct file_security_struct *fsec = selinux_file(file);
2060*4882a593Smuzhiyun 	struct dentry *dentry = file->f_path.dentry;
2061*4882a593Smuzhiyun 	struct inode_security_struct *isec;
2062*4882a593Smuzhiyun 	struct common_audit_data ad;
2063*4882a593Smuzhiyun 	int rc;
2064*4882a593Smuzhiyun 
2065*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_PATH;
2066*4882a593Smuzhiyun 	ad.u.path = file->f_path;
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun 	if (sid != fsec->sid) {
2069*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2070*4882a593Smuzhiyun 				  sid, fsec->sid,
2071*4882a593Smuzhiyun 				  SECCLASS_FD,
2072*4882a593Smuzhiyun 				  FD__USE,
2073*4882a593Smuzhiyun 				  &ad);
2074*4882a593Smuzhiyun 		if (rc)
2075*4882a593Smuzhiyun 			return rc;
2076*4882a593Smuzhiyun 	}
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
2079*4882a593Smuzhiyun 	rc = bpf_fd_pass(file, sid);
2080*4882a593Smuzhiyun 	if (rc)
2081*4882a593Smuzhiyun 		return rc;
2082*4882a593Smuzhiyun #endif
2083*4882a593Smuzhiyun 
2084*4882a593Smuzhiyun 	if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
2085*4882a593Smuzhiyun 		return 0;
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun 	isec = backing_inode_security(dentry);
2088*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2089*4882a593Smuzhiyun 			    sid, isec->sid, isec->sclass, file_to_av(file),
2090*4882a593Smuzhiyun 			    &ad);
2091*4882a593Smuzhiyun }
2092*4882a593Smuzhiyun 
selinux_ptrace_access_check(struct task_struct * child,unsigned int mode)2093*4882a593Smuzhiyun static int selinux_ptrace_access_check(struct task_struct *child,
2094*4882a593Smuzhiyun 				     unsigned int mode)
2095*4882a593Smuzhiyun {
2096*4882a593Smuzhiyun 	u32 sid = current_sid();
2097*4882a593Smuzhiyun 	u32 csid = task_sid(child);
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 	if (mode & PTRACE_MODE_READ)
2100*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
2101*4882a593Smuzhiyun 				    sid, csid, SECCLASS_FILE, FILE__READ, NULL);
2102*4882a593Smuzhiyun 
2103*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2104*4882a593Smuzhiyun 			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
2105*4882a593Smuzhiyun }
2106*4882a593Smuzhiyun 
selinux_ptrace_traceme(struct task_struct * parent)2107*4882a593Smuzhiyun static int selinux_ptrace_traceme(struct task_struct *parent)
2108*4882a593Smuzhiyun {
2109*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2110*4882a593Smuzhiyun 			    task_sid(parent), current_sid(), SECCLASS_PROCESS,
2111*4882a593Smuzhiyun 			    PROCESS__PTRACE, NULL);
2112*4882a593Smuzhiyun }
2113*4882a593Smuzhiyun 
selinux_capget(struct task_struct * target,kernel_cap_t * effective,kernel_cap_t * inheritable,kernel_cap_t * permitted)2114*4882a593Smuzhiyun static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
2115*4882a593Smuzhiyun 			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
2116*4882a593Smuzhiyun {
2117*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2118*4882a593Smuzhiyun 			    current_sid(), task_sid(target), SECCLASS_PROCESS,
2119*4882a593Smuzhiyun 			    PROCESS__GETCAP, NULL);
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun 
selinux_capset(struct cred * new,const struct cred * old,const kernel_cap_t * effective,const kernel_cap_t * inheritable,const kernel_cap_t * permitted)2122*4882a593Smuzhiyun static int selinux_capset(struct cred *new, const struct cred *old,
2123*4882a593Smuzhiyun 			  const kernel_cap_t *effective,
2124*4882a593Smuzhiyun 			  const kernel_cap_t *inheritable,
2125*4882a593Smuzhiyun 			  const kernel_cap_t *permitted)
2126*4882a593Smuzhiyun {
2127*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2128*4882a593Smuzhiyun 			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
2129*4882a593Smuzhiyun 			    PROCESS__SETCAP, NULL);
2130*4882a593Smuzhiyun }
2131*4882a593Smuzhiyun 
2132*4882a593Smuzhiyun /*
2133*4882a593Smuzhiyun  * (This comment used to live with the selinux_task_setuid hook,
2134*4882a593Smuzhiyun  * which was removed).
2135*4882a593Smuzhiyun  *
2136*4882a593Smuzhiyun  * Since setuid only affects the current process, and since the SELinux
2137*4882a593Smuzhiyun  * controls are not based on the Linux identity attributes, SELinux does not
2138*4882a593Smuzhiyun  * need to control this operation.  However, SELinux does control the use of
2139*4882a593Smuzhiyun  * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2140*4882a593Smuzhiyun  */
2141*4882a593Smuzhiyun 
selinux_capable(const struct cred * cred,struct user_namespace * ns,int cap,unsigned int opts)2142*4882a593Smuzhiyun static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2143*4882a593Smuzhiyun 			   int cap, unsigned int opts)
2144*4882a593Smuzhiyun {
2145*4882a593Smuzhiyun 	return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
2146*4882a593Smuzhiyun }
2147*4882a593Smuzhiyun 
selinux_quotactl(int cmds,int type,int id,struct super_block * sb)2148*4882a593Smuzhiyun static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2149*4882a593Smuzhiyun {
2150*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2151*4882a593Smuzhiyun 	int rc = 0;
2152*4882a593Smuzhiyun 
2153*4882a593Smuzhiyun 	if (!sb)
2154*4882a593Smuzhiyun 		return 0;
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun 	switch (cmds) {
2157*4882a593Smuzhiyun 	case Q_SYNC:
2158*4882a593Smuzhiyun 	case Q_QUOTAON:
2159*4882a593Smuzhiyun 	case Q_QUOTAOFF:
2160*4882a593Smuzhiyun 	case Q_SETINFO:
2161*4882a593Smuzhiyun 	case Q_SETQUOTA:
2162*4882a593Smuzhiyun 	case Q_XQUOTAOFF:
2163*4882a593Smuzhiyun 	case Q_XQUOTAON:
2164*4882a593Smuzhiyun 	case Q_XSETQLIM:
2165*4882a593Smuzhiyun 		rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
2166*4882a593Smuzhiyun 		break;
2167*4882a593Smuzhiyun 	case Q_GETFMT:
2168*4882a593Smuzhiyun 	case Q_GETINFO:
2169*4882a593Smuzhiyun 	case Q_GETQUOTA:
2170*4882a593Smuzhiyun 	case Q_XGETQUOTA:
2171*4882a593Smuzhiyun 	case Q_XGETQSTAT:
2172*4882a593Smuzhiyun 	case Q_XGETQSTATV:
2173*4882a593Smuzhiyun 	case Q_XGETNEXTQUOTA:
2174*4882a593Smuzhiyun 		rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
2175*4882a593Smuzhiyun 		break;
2176*4882a593Smuzhiyun 	default:
2177*4882a593Smuzhiyun 		rc = 0;  /* let the kernel handle invalid cmds */
2178*4882a593Smuzhiyun 		break;
2179*4882a593Smuzhiyun 	}
2180*4882a593Smuzhiyun 	return rc;
2181*4882a593Smuzhiyun }
2182*4882a593Smuzhiyun 
selinux_quota_on(struct dentry * dentry)2183*4882a593Smuzhiyun static int selinux_quota_on(struct dentry *dentry)
2184*4882a593Smuzhiyun {
2185*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2186*4882a593Smuzhiyun 
2187*4882a593Smuzhiyun 	return dentry_has_perm(cred, dentry, FILE__QUOTAON);
2188*4882a593Smuzhiyun }
2189*4882a593Smuzhiyun 
selinux_syslog(int type)2190*4882a593Smuzhiyun static int selinux_syslog(int type)
2191*4882a593Smuzhiyun {
2192*4882a593Smuzhiyun 	switch (type) {
2193*4882a593Smuzhiyun 	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
2194*4882a593Smuzhiyun 	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
2195*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
2196*4882a593Smuzhiyun 				    current_sid(), SECINITSID_KERNEL,
2197*4882a593Smuzhiyun 				    SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
2198*4882a593Smuzhiyun 	case SYSLOG_ACTION_CONSOLE_OFF:	/* Disable logging to console */
2199*4882a593Smuzhiyun 	case SYSLOG_ACTION_CONSOLE_ON:	/* Enable logging to console */
2200*4882a593Smuzhiyun 	/* Set level of messages printed to console */
2201*4882a593Smuzhiyun 	case SYSLOG_ACTION_CONSOLE_LEVEL:
2202*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
2203*4882a593Smuzhiyun 				    current_sid(), SECINITSID_KERNEL,
2204*4882a593Smuzhiyun 				    SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2205*4882a593Smuzhiyun 				    NULL);
2206*4882a593Smuzhiyun 	}
2207*4882a593Smuzhiyun 	/* All other syslog types */
2208*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2209*4882a593Smuzhiyun 			    current_sid(), SECINITSID_KERNEL,
2210*4882a593Smuzhiyun 			    SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
2211*4882a593Smuzhiyun }
2212*4882a593Smuzhiyun 
2213*4882a593Smuzhiyun /*
2214*4882a593Smuzhiyun  * Check that a process has enough memory to allocate a new virtual
2215*4882a593Smuzhiyun  * mapping. 0 means there is enough memory for the allocation to
2216*4882a593Smuzhiyun  * succeed and -ENOMEM implies there is not.
2217*4882a593Smuzhiyun  *
2218*4882a593Smuzhiyun  * Do not audit the selinux permission check, as this is applied to all
2219*4882a593Smuzhiyun  * processes that allocate mappings.
2220*4882a593Smuzhiyun  */
selinux_vm_enough_memory(struct mm_struct * mm,long pages)2221*4882a593Smuzhiyun static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
2222*4882a593Smuzhiyun {
2223*4882a593Smuzhiyun 	int rc, cap_sys_admin = 0;
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2226*4882a593Smuzhiyun 				 CAP_OPT_NOAUDIT, true);
2227*4882a593Smuzhiyun 	if (rc == 0)
2228*4882a593Smuzhiyun 		cap_sys_admin = 1;
2229*4882a593Smuzhiyun 
2230*4882a593Smuzhiyun 	return cap_sys_admin;
2231*4882a593Smuzhiyun }
2232*4882a593Smuzhiyun 
2233*4882a593Smuzhiyun /* binprm security operations */
2234*4882a593Smuzhiyun 
ptrace_parent_sid(void)2235*4882a593Smuzhiyun static u32 ptrace_parent_sid(void)
2236*4882a593Smuzhiyun {
2237*4882a593Smuzhiyun 	u32 sid = 0;
2238*4882a593Smuzhiyun 	struct task_struct *tracer;
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun 	rcu_read_lock();
2241*4882a593Smuzhiyun 	tracer = ptrace_parent(current);
2242*4882a593Smuzhiyun 	if (tracer)
2243*4882a593Smuzhiyun 		sid = task_sid(tracer);
2244*4882a593Smuzhiyun 	rcu_read_unlock();
2245*4882a593Smuzhiyun 
2246*4882a593Smuzhiyun 	return sid;
2247*4882a593Smuzhiyun }
2248*4882a593Smuzhiyun 
check_nnp_nosuid(const struct linux_binprm * bprm,const struct task_security_struct * old_tsec,const struct task_security_struct * new_tsec)2249*4882a593Smuzhiyun static int check_nnp_nosuid(const struct linux_binprm *bprm,
2250*4882a593Smuzhiyun 			    const struct task_security_struct *old_tsec,
2251*4882a593Smuzhiyun 			    const struct task_security_struct *new_tsec)
2252*4882a593Smuzhiyun {
2253*4882a593Smuzhiyun 	int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2254*4882a593Smuzhiyun 	int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
2255*4882a593Smuzhiyun 	int rc;
2256*4882a593Smuzhiyun 	u32 av;
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun 	if (!nnp && !nosuid)
2259*4882a593Smuzhiyun 		return 0; /* neither NNP nor nosuid */
2260*4882a593Smuzhiyun 
2261*4882a593Smuzhiyun 	if (new_tsec->sid == old_tsec->sid)
2262*4882a593Smuzhiyun 		return 0; /* No change in credentials */
2263*4882a593Smuzhiyun 
2264*4882a593Smuzhiyun 	/*
2265*4882a593Smuzhiyun 	 * If the policy enables the nnp_nosuid_transition policy capability,
2266*4882a593Smuzhiyun 	 * then we permit transitions under NNP or nosuid if the
2267*4882a593Smuzhiyun 	 * policy allows the corresponding permission between
2268*4882a593Smuzhiyun 	 * the old and new contexts.
2269*4882a593Smuzhiyun 	 */
2270*4882a593Smuzhiyun 	if (selinux_policycap_nnp_nosuid_transition()) {
2271*4882a593Smuzhiyun 		av = 0;
2272*4882a593Smuzhiyun 		if (nnp)
2273*4882a593Smuzhiyun 			av |= PROCESS2__NNP_TRANSITION;
2274*4882a593Smuzhiyun 		if (nosuid)
2275*4882a593Smuzhiyun 			av |= PROCESS2__NOSUID_TRANSITION;
2276*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2277*4882a593Smuzhiyun 				  old_tsec->sid, new_tsec->sid,
2278*4882a593Smuzhiyun 				  SECCLASS_PROCESS2, av, NULL);
2279*4882a593Smuzhiyun 		if (!rc)
2280*4882a593Smuzhiyun 			return 0;
2281*4882a593Smuzhiyun 	}
2282*4882a593Smuzhiyun 
2283*4882a593Smuzhiyun 	/*
2284*4882a593Smuzhiyun 	 * We also permit NNP or nosuid transitions to bounded SIDs,
2285*4882a593Smuzhiyun 	 * i.e. SIDs that are guaranteed to only be allowed a subset
2286*4882a593Smuzhiyun 	 * of the permissions of the current SID.
2287*4882a593Smuzhiyun 	 */
2288*4882a593Smuzhiyun 	rc = security_bounded_transition(&selinux_state, old_tsec->sid,
2289*4882a593Smuzhiyun 					 new_tsec->sid);
2290*4882a593Smuzhiyun 	if (!rc)
2291*4882a593Smuzhiyun 		return 0;
2292*4882a593Smuzhiyun 
2293*4882a593Smuzhiyun 	/*
2294*4882a593Smuzhiyun 	 * On failure, preserve the errno values for NNP vs nosuid.
2295*4882a593Smuzhiyun 	 * NNP:  Operation not permitted for caller.
2296*4882a593Smuzhiyun 	 * nosuid:  Permission denied to file.
2297*4882a593Smuzhiyun 	 */
2298*4882a593Smuzhiyun 	if (nnp)
2299*4882a593Smuzhiyun 		return -EPERM;
2300*4882a593Smuzhiyun 	return -EACCES;
2301*4882a593Smuzhiyun }
2302*4882a593Smuzhiyun 
selinux_bprm_creds_for_exec(struct linux_binprm * bprm)2303*4882a593Smuzhiyun static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
2304*4882a593Smuzhiyun {
2305*4882a593Smuzhiyun 	const struct task_security_struct *old_tsec;
2306*4882a593Smuzhiyun 	struct task_security_struct *new_tsec;
2307*4882a593Smuzhiyun 	struct inode_security_struct *isec;
2308*4882a593Smuzhiyun 	struct common_audit_data ad;
2309*4882a593Smuzhiyun 	struct inode *inode = file_inode(bprm->file);
2310*4882a593Smuzhiyun 	int rc;
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 	/* SELinux context only depends on initial program or script and not
2313*4882a593Smuzhiyun 	 * the script interpreter */
2314*4882a593Smuzhiyun 
2315*4882a593Smuzhiyun 	old_tsec = selinux_cred(current_cred());
2316*4882a593Smuzhiyun 	new_tsec = selinux_cred(bprm->cred);
2317*4882a593Smuzhiyun 	isec = inode_security(inode);
2318*4882a593Smuzhiyun 
2319*4882a593Smuzhiyun 	/* Default to the current task SID. */
2320*4882a593Smuzhiyun 	new_tsec->sid = old_tsec->sid;
2321*4882a593Smuzhiyun 	new_tsec->osid = old_tsec->sid;
2322*4882a593Smuzhiyun 
2323*4882a593Smuzhiyun 	/* Reset fs, key, and sock SIDs on execve. */
2324*4882a593Smuzhiyun 	new_tsec->create_sid = 0;
2325*4882a593Smuzhiyun 	new_tsec->keycreate_sid = 0;
2326*4882a593Smuzhiyun 	new_tsec->sockcreate_sid = 0;
2327*4882a593Smuzhiyun 
2328*4882a593Smuzhiyun 	if (old_tsec->exec_sid) {
2329*4882a593Smuzhiyun 		new_tsec->sid = old_tsec->exec_sid;
2330*4882a593Smuzhiyun 		/* Reset exec SID on execve. */
2331*4882a593Smuzhiyun 		new_tsec->exec_sid = 0;
2332*4882a593Smuzhiyun 
2333*4882a593Smuzhiyun 		/* Fail on NNP or nosuid if not an allowed transition. */
2334*4882a593Smuzhiyun 		rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2335*4882a593Smuzhiyun 		if (rc)
2336*4882a593Smuzhiyun 			return rc;
2337*4882a593Smuzhiyun 	} else {
2338*4882a593Smuzhiyun 		/* Check for a default transition on this program. */
2339*4882a593Smuzhiyun 		rc = security_transition_sid(&selinux_state, old_tsec->sid,
2340*4882a593Smuzhiyun 					     isec->sid, SECCLASS_PROCESS, NULL,
2341*4882a593Smuzhiyun 					     &new_tsec->sid);
2342*4882a593Smuzhiyun 		if (rc)
2343*4882a593Smuzhiyun 			return rc;
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun 		/*
2346*4882a593Smuzhiyun 		 * Fallback to old SID on NNP or nosuid if not an allowed
2347*4882a593Smuzhiyun 		 * transition.
2348*4882a593Smuzhiyun 		 */
2349*4882a593Smuzhiyun 		rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2350*4882a593Smuzhiyun 		if (rc)
2351*4882a593Smuzhiyun 			new_tsec->sid = old_tsec->sid;
2352*4882a593Smuzhiyun 	}
2353*4882a593Smuzhiyun 
2354*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_FILE;
2355*4882a593Smuzhiyun 	ad.u.file = bprm->file;
2356*4882a593Smuzhiyun 
2357*4882a593Smuzhiyun 	if (new_tsec->sid == old_tsec->sid) {
2358*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2359*4882a593Smuzhiyun 				  old_tsec->sid, isec->sid,
2360*4882a593Smuzhiyun 				  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2361*4882a593Smuzhiyun 		if (rc)
2362*4882a593Smuzhiyun 			return rc;
2363*4882a593Smuzhiyun 	} else {
2364*4882a593Smuzhiyun 		/* Check permissions for the transition. */
2365*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2366*4882a593Smuzhiyun 				  old_tsec->sid, new_tsec->sid,
2367*4882a593Smuzhiyun 				  SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2368*4882a593Smuzhiyun 		if (rc)
2369*4882a593Smuzhiyun 			return rc;
2370*4882a593Smuzhiyun 
2371*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2372*4882a593Smuzhiyun 				  new_tsec->sid, isec->sid,
2373*4882a593Smuzhiyun 				  SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2374*4882a593Smuzhiyun 		if (rc)
2375*4882a593Smuzhiyun 			return rc;
2376*4882a593Smuzhiyun 
2377*4882a593Smuzhiyun 		/* Check for shared state */
2378*4882a593Smuzhiyun 		if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2379*4882a593Smuzhiyun 			rc = avc_has_perm(&selinux_state,
2380*4882a593Smuzhiyun 					  old_tsec->sid, new_tsec->sid,
2381*4882a593Smuzhiyun 					  SECCLASS_PROCESS, PROCESS__SHARE,
2382*4882a593Smuzhiyun 					  NULL);
2383*4882a593Smuzhiyun 			if (rc)
2384*4882a593Smuzhiyun 				return -EPERM;
2385*4882a593Smuzhiyun 		}
2386*4882a593Smuzhiyun 
2387*4882a593Smuzhiyun 		/* Make sure that anyone attempting to ptrace over a task that
2388*4882a593Smuzhiyun 		 * changes its SID has the appropriate permit */
2389*4882a593Smuzhiyun 		if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
2390*4882a593Smuzhiyun 			u32 ptsid = ptrace_parent_sid();
2391*4882a593Smuzhiyun 			if (ptsid != 0) {
2392*4882a593Smuzhiyun 				rc = avc_has_perm(&selinux_state,
2393*4882a593Smuzhiyun 						  ptsid, new_tsec->sid,
2394*4882a593Smuzhiyun 						  SECCLASS_PROCESS,
2395*4882a593Smuzhiyun 						  PROCESS__PTRACE, NULL);
2396*4882a593Smuzhiyun 				if (rc)
2397*4882a593Smuzhiyun 					return -EPERM;
2398*4882a593Smuzhiyun 			}
2399*4882a593Smuzhiyun 		}
2400*4882a593Smuzhiyun 
2401*4882a593Smuzhiyun 		/* Clear any possibly unsafe personality bits on exec: */
2402*4882a593Smuzhiyun 		bprm->per_clear |= PER_CLEAR_ON_SETID;
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 		/* Enable secure mode for SIDs transitions unless
2405*4882a593Smuzhiyun 		   the noatsecure permission is granted between
2406*4882a593Smuzhiyun 		   the two SIDs, i.e. ahp returns 0. */
2407*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
2408*4882a593Smuzhiyun 				  old_tsec->sid, new_tsec->sid,
2409*4882a593Smuzhiyun 				  SECCLASS_PROCESS, PROCESS__NOATSECURE,
2410*4882a593Smuzhiyun 				  NULL);
2411*4882a593Smuzhiyun 		bprm->secureexec |= !!rc;
2412*4882a593Smuzhiyun 	}
2413*4882a593Smuzhiyun 
2414*4882a593Smuzhiyun 	return 0;
2415*4882a593Smuzhiyun }
2416*4882a593Smuzhiyun 
match_file(const void * p,struct file * file,unsigned fd)2417*4882a593Smuzhiyun static int match_file(const void *p, struct file *file, unsigned fd)
2418*4882a593Smuzhiyun {
2419*4882a593Smuzhiyun 	return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2420*4882a593Smuzhiyun }
2421*4882a593Smuzhiyun 
2422*4882a593Smuzhiyun /* Derived from fs/exec.c:flush_old_files. */
flush_unauthorized_files(const struct cred * cred,struct files_struct * files)2423*4882a593Smuzhiyun static inline void flush_unauthorized_files(const struct cred *cred,
2424*4882a593Smuzhiyun 					    struct files_struct *files)
2425*4882a593Smuzhiyun {
2426*4882a593Smuzhiyun 	struct file *file, *devnull = NULL;
2427*4882a593Smuzhiyun 	struct tty_struct *tty;
2428*4882a593Smuzhiyun 	int drop_tty = 0;
2429*4882a593Smuzhiyun 	unsigned n;
2430*4882a593Smuzhiyun 
2431*4882a593Smuzhiyun 	tty = get_current_tty();
2432*4882a593Smuzhiyun 	if (tty) {
2433*4882a593Smuzhiyun 		spin_lock(&tty->files_lock);
2434*4882a593Smuzhiyun 		if (!list_empty(&tty->tty_files)) {
2435*4882a593Smuzhiyun 			struct tty_file_private *file_priv;
2436*4882a593Smuzhiyun 
2437*4882a593Smuzhiyun 			/* Revalidate access to controlling tty.
2438*4882a593Smuzhiyun 			   Use file_path_has_perm on the tty path directly
2439*4882a593Smuzhiyun 			   rather than using file_has_perm, as this particular
2440*4882a593Smuzhiyun 			   open file may belong to another process and we are
2441*4882a593Smuzhiyun 			   only interested in the inode-based check here. */
2442*4882a593Smuzhiyun 			file_priv = list_first_entry(&tty->tty_files,
2443*4882a593Smuzhiyun 						struct tty_file_private, list);
2444*4882a593Smuzhiyun 			file = file_priv->file;
2445*4882a593Smuzhiyun 			if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
2446*4882a593Smuzhiyun 				drop_tty = 1;
2447*4882a593Smuzhiyun 		}
2448*4882a593Smuzhiyun 		spin_unlock(&tty->files_lock);
2449*4882a593Smuzhiyun 		tty_kref_put(tty);
2450*4882a593Smuzhiyun 	}
2451*4882a593Smuzhiyun 	/* Reset controlling tty. */
2452*4882a593Smuzhiyun 	if (drop_tty)
2453*4882a593Smuzhiyun 		no_tty();
2454*4882a593Smuzhiyun 
2455*4882a593Smuzhiyun 	/* Revalidate access to inherited open files. */
2456*4882a593Smuzhiyun 	n = iterate_fd(files, 0, match_file, cred);
2457*4882a593Smuzhiyun 	if (!n) /* none found? */
2458*4882a593Smuzhiyun 		return;
2459*4882a593Smuzhiyun 
2460*4882a593Smuzhiyun 	devnull = dentry_open(&selinux_null, O_RDWR, cred);
2461*4882a593Smuzhiyun 	if (IS_ERR(devnull))
2462*4882a593Smuzhiyun 		devnull = NULL;
2463*4882a593Smuzhiyun 	/* replace all the matching ones with this */
2464*4882a593Smuzhiyun 	do {
2465*4882a593Smuzhiyun 		replace_fd(n - 1, devnull, 0);
2466*4882a593Smuzhiyun 	} while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2467*4882a593Smuzhiyun 	if (devnull)
2468*4882a593Smuzhiyun 		fput(devnull);
2469*4882a593Smuzhiyun }
2470*4882a593Smuzhiyun 
2471*4882a593Smuzhiyun /*
2472*4882a593Smuzhiyun  * Prepare a process for imminent new credential changes due to exec
2473*4882a593Smuzhiyun  */
selinux_bprm_committing_creds(struct linux_binprm * bprm)2474*4882a593Smuzhiyun static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
2475*4882a593Smuzhiyun {
2476*4882a593Smuzhiyun 	struct task_security_struct *new_tsec;
2477*4882a593Smuzhiyun 	struct rlimit *rlim, *initrlim;
2478*4882a593Smuzhiyun 	int rc, i;
2479*4882a593Smuzhiyun 
2480*4882a593Smuzhiyun 	new_tsec = selinux_cred(bprm->cred);
2481*4882a593Smuzhiyun 	if (new_tsec->sid == new_tsec->osid)
2482*4882a593Smuzhiyun 		return;
2483*4882a593Smuzhiyun 
2484*4882a593Smuzhiyun 	/* Close files for which the new task SID is not authorized. */
2485*4882a593Smuzhiyun 	flush_unauthorized_files(bprm->cred, current->files);
2486*4882a593Smuzhiyun 
2487*4882a593Smuzhiyun 	/* Always clear parent death signal on SID transitions. */
2488*4882a593Smuzhiyun 	current->pdeath_signal = 0;
2489*4882a593Smuzhiyun 
2490*4882a593Smuzhiyun 	/* Check whether the new SID can inherit resource limits from the old
2491*4882a593Smuzhiyun 	 * SID.  If not, reset all soft limits to the lower of the current
2492*4882a593Smuzhiyun 	 * task's hard limit and the init task's soft limit.
2493*4882a593Smuzhiyun 	 *
2494*4882a593Smuzhiyun 	 * Note that the setting of hard limits (even to lower them) can be
2495*4882a593Smuzhiyun 	 * controlled by the setrlimit check.  The inclusion of the init task's
2496*4882a593Smuzhiyun 	 * soft limit into the computation is to avoid resetting soft limits
2497*4882a593Smuzhiyun 	 * higher than the default soft limit for cases where the default is
2498*4882a593Smuzhiyun 	 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2499*4882a593Smuzhiyun 	 */
2500*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
2501*4882a593Smuzhiyun 			  new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2502*4882a593Smuzhiyun 			  PROCESS__RLIMITINH, NULL);
2503*4882a593Smuzhiyun 	if (rc) {
2504*4882a593Smuzhiyun 		/* protect against do_prlimit() */
2505*4882a593Smuzhiyun 		task_lock(current);
2506*4882a593Smuzhiyun 		for (i = 0; i < RLIM_NLIMITS; i++) {
2507*4882a593Smuzhiyun 			rlim = current->signal->rlim + i;
2508*4882a593Smuzhiyun 			initrlim = init_task.signal->rlim + i;
2509*4882a593Smuzhiyun 			rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2510*4882a593Smuzhiyun 		}
2511*4882a593Smuzhiyun 		task_unlock(current);
2512*4882a593Smuzhiyun 		if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2513*4882a593Smuzhiyun 			update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
2514*4882a593Smuzhiyun 	}
2515*4882a593Smuzhiyun }
2516*4882a593Smuzhiyun 
2517*4882a593Smuzhiyun /*
2518*4882a593Smuzhiyun  * Clean up the process immediately after the installation of new credentials
2519*4882a593Smuzhiyun  * due to exec
2520*4882a593Smuzhiyun  */
selinux_bprm_committed_creds(struct linux_binprm * bprm)2521*4882a593Smuzhiyun static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2522*4882a593Smuzhiyun {
2523*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
2524*4882a593Smuzhiyun 	u32 osid, sid;
2525*4882a593Smuzhiyun 	int rc;
2526*4882a593Smuzhiyun 
2527*4882a593Smuzhiyun 	osid = tsec->osid;
2528*4882a593Smuzhiyun 	sid = tsec->sid;
2529*4882a593Smuzhiyun 
2530*4882a593Smuzhiyun 	if (sid == osid)
2531*4882a593Smuzhiyun 		return;
2532*4882a593Smuzhiyun 
2533*4882a593Smuzhiyun 	/* Check whether the new SID can inherit signal state from the old SID.
2534*4882a593Smuzhiyun 	 * If not, clear itimers to avoid subsequent signal generation and
2535*4882a593Smuzhiyun 	 * flush and unblock signals.
2536*4882a593Smuzhiyun 	 *
2537*4882a593Smuzhiyun 	 * This must occur _after_ the task SID has been updated so that any
2538*4882a593Smuzhiyun 	 * kill done after the flush will be checked against the new SID.
2539*4882a593Smuzhiyun 	 */
2540*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
2541*4882a593Smuzhiyun 			  osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
2542*4882a593Smuzhiyun 	if (rc) {
2543*4882a593Smuzhiyun 		clear_itimer();
2544*4882a593Smuzhiyun 
2545*4882a593Smuzhiyun 		spin_lock_irq(&current->sighand->siglock);
2546*4882a593Smuzhiyun 		if (!fatal_signal_pending(current)) {
2547*4882a593Smuzhiyun 			flush_sigqueue(&current->pending);
2548*4882a593Smuzhiyun 			flush_sigqueue(&current->signal->shared_pending);
2549*4882a593Smuzhiyun 			flush_signal_handlers(current, 1);
2550*4882a593Smuzhiyun 			sigemptyset(&current->blocked);
2551*4882a593Smuzhiyun 			recalc_sigpending();
2552*4882a593Smuzhiyun 		}
2553*4882a593Smuzhiyun 		spin_unlock_irq(&current->sighand->siglock);
2554*4882a593Smuzhiyun 	}
2555*4882a593Smuzhiyun 
2556*4882a593Smuzhiyun 	/* Wake up the parent if it is waiting so that it can recheck
2557*4882a593Smuzhiyun 	 * wait permission to the new task SID. */
2558*4882a593Smuzhiyun 	read_lock(&tasklist_lock);
2559*4882a593Smuzhiyun 	__wake_up_parent(current, current->real_parent);
2560*4882a593Smuzhiyun 	read_unlock(&tasklist_lock);
2561*4882a593Smuzhiyun }
2562*4882a593Smuzhiyun 
2563*4882a593Smuzhiyun /* superblock security operations */
2564*4882a593Smuzhiyun 
selinux_sb_alloc_security(struct super_block * sb)2565*4882a593Smuzhiyun static int selinux_sb_alloc_security(struct super_block *sb)
2566*4882a593Smuzhiyun {
2567*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
2568*4882a593Smuzhiyun 
2569*4882a593Smuzhiyun 	sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
2570*4882a593Smuzhiyun 	if (!sbsec)
2571*4882a593Smuzhiyun 		return -ENOMEM;
2572*4882a593Smuzhiyun 
2573*4882a593Smuzhiyun 	mutex_init(&sbsec->lock);
2574*4882a593Smuzhiyun 	INIT_LIST_HEAD(&sbsec->isec_head);
2575*4882a593Smuzhiyun 	spin_lock_init(&sbsec->isec_lock);
2576*4882a593Smuzhiyun 	sbsec->sb = sb;
2577*4882a593Smuzhiyun 	sbsec->sid = SECINITSID_UNLABELED;
2578*4882a593Smuzhiyun 	sbsec->def_sid = SECINITSID_FILE;
2579*4882a593Smuzhiyun 	sbsec->mntpoint_sid = SECINITSID_UNLABELED;
2580*4882a593Smuzhiyun 	sb->s_security = sbsec;
2581*4882a593Smuzhiyun 
2582*4882a593Smuzhiyun 	return 0;
2583*4882a593Smuzhiyun }
2584*4882a593Smuzhiyun 
selinux_sb_free_security(struct super_block * sb)2585*4882a593Smuzhiyun static void selinux_sb_free_security(struct super_block *sb)
2586*4882a593Smuzhiyun {
2587*4882a593Smuzhiyun 	superblock_free_security(sb);
2588*4882a593Smuzhiyun }
2589*4882a593Smuzhiyun 
opt_len(const char * s)2590*4882a593Smuzhiyun static inline int opt_len(const char *s)
2591*4882a593Smuzhiyun {
2592*4882a593Smuzhiyun 	bool open_quote = false;
2593*4882a593Smuzhiyun 	int len;
2594*4882a593Smuzhiyun 	char c;
2595*4882a593Smuzhiyun 
2596*4882a593Smuzhiyun 	for (len = 0; (c = s[len]) != '\0'; len++) {
2597*4882a593Smuzhiyun 		if (c == '"')
2598*4882a593Smuzhiyun 			open_quote = !open_quote;
2599*4882a593Smuzhiyun 		if (c == ',' && !open_quote)
2600*4882a593Smuzhiyun 			break;
2601*4882a593Smuzhiyun 	}
2602*4882a593Smuzhiyun 	return len;
2603*4882a593Smuzhiyun }
2604*4882a593Smuzhiyun 
selinux_sb_eat_lsm_opts(char * options,void ** mnt_opts)2605*4882a593Smuzhiyun static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
2606*4882a593Smuzhiyun {
2607*4882a593Smuzhiyun 	char *from = options;
2608*4882a593Smuzhiyun 	char *to = options;
2609*4882a593Smuzhiyun 	bool first = true;
2610*4882a593Smuzhiyun 	int rc;
2611*4882a593Smuzhiyun 
2612*4882a593Smuzhiyun 	while (1) {
2613*4882a593Smuzhiyun 		int len = opt_len(from);
2614*4882a593Smuzhiyun 		int token;
2615*4882a593Smuzhiyun 		char *arg = NULL;
2616*4882a593Smuzhiyun 
2617*4882a593Smuzhiyun 		token = match_opt_prefix(from, len, &arg);
2618*4882a593Smuzhiyun 
2619*4882a593Smuzhiyun 		if (token != Opt_error) {
2620*4882a593Smuzhiyun 			char *p, *q;
2621*4882a593Smuzhiyun 
2622*4882a593Smuzhiyun 			/* strip quotes */
2623*4882a593Smuzhiyun 			if (arg) {
2624*4882a593Smuzhiyun 				for (p = q = arg; p < from + len; p++) {
2625*4882a593Smuzhiyun 					char c = *p;
2626*4882a593Smuzhiyun 					if (c != '"')
2627*4882a593Smuzhiyun 						*q++ = c;
2628*4882a593Smuzhiyun 				}
2629*4882a593Smuzhiyun 				arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
2630*4882a593Smuzhiyun 				if (!arg) {
2631*4882a593Smuzhiyun 					rc = -ENOMEM;
2632*4882a593Smuzhiyun 					goto free_opt;
2633*4882a593Smuzhiyun 				}
2634*4882a593Smuzhiyun 			}
2635*4882a593Smuzhiyun 			rc = selinux_add_opt(token, arg, mnt_opts);
2636*4882a593Smuzhiyun 			if (unlikely(rc)) {
2637*4882a593Smuzhiyun 				kfree(arg);
2638*4882a593Smuzhiyun 				goto free_opt;
2639*4882a593Smuzhiyun 			}
2640*4882a593Smuzhiyun 		} else {
2641*4882a593Smuzhiyun 			if (!first) {	// copy with preceding comma
2642*4882a593Smuzhiyun 				from--;
2643*4882a593Smuzhiyun 				len++;
2644*4882a593Smuzhiyun 			}
2645*4882a593Smuzhiyun 			if (to != from)
2646*4882a593Smuzhiyun 				memmove(to, from, len);
2647*4882a593Smuzhiyun 			to += len;
2648*4882a593Smuzhiyun 			first = false;
2649*4882a593Smuzhiyun 		}
2650*4882a593Smuzhiyun 		if (!from[len])
2651*4882a593Smuzhiyun 			break;
2652*4882a593Smuzhiyun 		from += len + 1;
2653*4882a593Smuzhiyun 	}
2654*4882a593Smuzhiyun 	*to = '\0';
2655*4882a593Smuzhiyun 	return 0;
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun free_opt:
2658*4882a593Smuzhiyun 	if (*mnt_opts) {
2659*4882a593Smuzhiyun 		selinux_free_mnt_opts(*mnt_opts);
2660*4882a593Smuzhiyun 		*mnt_opts = NULL;
2661*4882a593Smuzhiyun 	}
2662*4882a593Smuzhiyun 	return rc;
2663*4882a593Smuzhiyun }
2664*4882a593Smuzhiyun 
selinux_sb_remount(struct super_block * sb,void * mnt_opts)2665*4882a593Smuzhiyun static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
2666*4882a593Smuzhiyun {
2667*4882a593Smuzhiyun 	struct selinux_mnt_opts *opts = mnt_opts;
2668*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = sb->s_security;
2669*4882a593Smuzhiyun 	u32 sid;
2670*4882a593Smuzhiyun 	int rc;
2671*4882a593Smuzhiyun 
2672*4882a593Smuzhiyun 	if (!(sbsec->flags & SE_SBINITIALIZED))
2673*4882a593Smuzhiyun 		return 0;
2674*4882a593Smuzhiyun 
2675*4882a593Smuzhiyun 	if (!opts)
2676*4882a593Smuzhiyun 		return 0;
2677*4882a593Smuzhiyun 
2678*4882a593Smuzhiyun 	if (opts->fscontext) {
2679*4882a593Smuzhiyun 		rc = parse_sid(sb, opts->fscontext, &sid);
2680*4882a593Smuzhiyun 		if (rc)
2681*4882a593Smuzhiyun 			return rc;
2682*4882a593Smuzhiyun 		if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2683*4882a593Smuzhiyun 			goto out_bad_option;
2684*4882a593Smuzhiyun 	}
2685*4882a593Smuzhiyun 	if (opts->context) {
2686*4882a593Smuzhiyun 		rc = parse_sid(sb, opts->context, &sid);
2687*4882a593Smuzhiyun 		if (rc)
2688*4882a593Smuzhiyun 			return rc;
2689*4882a593Smuzhiyun 		if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2690*4882a593Smuzhiyun 			goto out_bad_option;
2691*4882a593Smuzhiyun 	}
2692*4882a593Smuzhiyun 	if (opts->rootcontext) {
2693*4882a593Smuzhiyun 		struct inode_security_struct *root_isec;
2694*4882a593Smuzhiyun 		root_isec = backing_inode_security(sb->s_root);
2695*4882a593Smuzhiyun 		rc = parse_sid(sb, opts->rootcontext, &sid);
2696*4882a593Smuzhiyun 		if (rc)
2697*4882a593Smuzhiyun 			return rc;
2698*4882a593Smuzhiyun 		if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2699*4882a593Smuzhiyun 			goto out_bad_option;
2700*4882a593Smuzhiyun 	}
2701*4882a593Smuzhiyun 	if (opts->defcontext) {
2702*4882a593Smuzhiyun 		rc = parse_sid(sb, opts->defcontext, &sid);
2703*4882a593Smuzhiyun 		if (rc)
2704*4882a593Smuzhiyun 			return rc;
2705*4882a593Smuzhiyun 		if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2706*4882a593Smuzhiyun 			goto out_bad_option;
2707*4882a593Smuzhiyun 	}
2708*4882a593Smuzhiyun 	return 0;
2709*4882a593Smuzhiyun 
2710*4882a593Smuzhiyun out_bad_option:
2711*4882a593Smuzhiyun 	pr_warn("SELinux: unable to change security options "
2712*4882a593Smuzhiyun 	       "during remount (dev %s, type=%s)\n", sb->s_id,
2713*4882a593Smuzhiyun 	       sb->s_type->name);
2714*4882a593Smuzhiyun 	return -EINVAL;
2715*4882a593Smuzhiyun }
2716*4882a593Smuzhiyun 
selinux_sb_kern_mount(struct super_block * sb)2717*4882a593Smuzhiyun static int selinux_sb_kern_mount(struct super_block *sb)
2718*4882a593Smuzhiyun {
2719*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2720*4882a593Smuzhiyun 	struct common_audit_data ad;
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
2723*4882a593Smuzhiyun 	ad.u.dentry = sb->s_root;
2724*4882a593Smuzhiyun 	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
2725*4882a593Smuzhiyun }
2726*4882a593Smuzhiyun 
selinux_sb_statfs(struct dentry * dentry)2727*4882a593Smuzhiyun static int selinux_sb_statfs(struct dentry *dentry)
2728*4882a593Smuzhiyun {
2729*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2730*4882a593Smuzhiyun 	struct common_audit_data ad;
2731*4882a593Smuzhiyun 
2732*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
2733*4882a593Smuzhiyun 	ad.u.dentry = dentry->d_sb->s_root;
2734*4882a593Smuzhiyun 	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
2735*4882a593Smuzhiyun }
2736*4882a593Smuzhiyun 
selinux_mount(const char * dev_name,const struct path * path,const char * type,unsigned long flags,void * data)2737*4882a593Smuzhiyun static int selinux_mount(const char *dev_name,
2738*4882a593Smuzhiyun 			 const struct path *path,
2739*4882a593Smuzhiyun 			 const char *type,
2740*4882a593Smuzhiyun 			 unsigned long flags,
2741*4882a593Smuzhiyun 			 void *data)
2742*4882a593Smuzhiyun {
2743*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2744*4882a593Smuzhiyun 
2745*4882a593Smuzhiyun 	if (flags & MS_REMOUNT)
2746*4882a593Smuzhiyun 		return superblock_has_perm(cred, path->dentry->d_sb,
2747*4882a593Smuzhiyun 					   FILESYSTEM__REMOUNT, NULL);
2748*4882a593Smuzhiyun 	else
2749*4882a593Smuzhiyun 		return path_has_perm(cred, path, FILE__MOUNTON);
2750*4882a593Smuzhiyun }
2751*4882a593Smuzhiyun 
selinux_move_mount(const struct path * from_path,const struct path * to_path)2752*4882a593Smuzhiyun static int selinux_move_mount(const struct path *from_path,
2753*4882a593Smuzhiyun 			      const struct path *to_path)
2754*4882a593Smuzhiyun {
2755*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2756*4882a593Smuzhiyun 
2757*4882a593Smuzhiyun 	return path_has_perm(cred, to_path, FILE__MOUNTON);
2758*4882a593Smuzhiyun }
2759*4882a593Smuzhiyun 
selinux_umount(struct vfsmount * mnt,int flags)2760*4882a593Smuzhiyun static int selinux_umount(struct vfsmount *mnt, int flags)
2761*4882a593Smuzhiyun {
2762*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
2763*4882a593Smuzhiyun 
2764*4882a593Smuzhiyun 	return superblock_has_perm(cred, mnt->mnt_sb,
2765*4882a593Smuzhiyun 				   FILESYSTEM__UNMOUNT, NULL);
2766*4882a593Smuzhiyun }
2767*4882a593Smuzhiyun 
selinux_fs_context_dup(struct fs_context * fc,struct fs_context * src_fc)2768*4882a593Smuzhiyun static int selinux_fs_context_dup(struct fs_context *fc,
2769*4882a593Smuzhiyun 				  struct fs_context *src_fc)
2770*4882a593Smuzhiyun {
2771*4882a593Smuzhiyun 	const struct selinux_mnt_opts *src = src_fc->security;
2772*4882a593Smuzhiyun 	struct selinux_mnt_opts *opts;
2773*4882a593Smuzhiyun 
2774*4882a593Smuzhiyun 	if (!src)
2775*4882a593Smuzhiyun 		return 0;
2776*4882a593Smuzhiyun 
2777*4882a593Smuzhiyun 	fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
2778*4882a593Smuzhiyun 	if (!fc->security)
2779*4882a593Smuzhiyun 		return -ENOMEM;
2780*4882a593Smuzhiyun 
2781*4882a593Smuzhiyun 	opts = fc->security;
2782*4882a593Smuzhiyun 
2783*4882a593Smuzhiyun 	if (src->fscontext) {
2784*4882a593Smuzhiyun 		opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
2785*4882a593Smuzhiyun 		if (!opts->fscontext)
2786*4882a593Smuzhiyun 			return -ENOMEM;
2787*4882a593Smuzhiyun 	}
2788*4882a593Smuzhiyun 	if (src->context) {
2789*4882a593Smuzhiyun 		opts->context = kstrdup(src->context, GFP_KERNEL);
2790*4882a593Smuzhiyun 		if (!opts->context)
2791*4882a593Smuzhiyun 			return -ENOMEM;
2792*4882a593Smuzhiyun 	}
2793*4882a593Smuzhiyun 	if (src->rootcontext) {
2794*4882a593Smuzhiyun 		opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
2795*4882a593Smuzhiyun 		if (!opts->rootcontext)
2796*4882a593Smuzhiyun 			return -ENOMEM;
2797*4882a593Smuzhiyun 	}
2798*4882a593Smuzhiyun 	if (src->defcontext) {
2799*4882a593Smuzhiyun 		opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
2800*4882a593Smuzhiyun 		if (!opts->defcontext)
2801*4882a593Smuzhiyun 			return -ENOMEM;
2802*4882a593Smuzhiyun 	}
2803*4882a593Smuzhiyun 	return 0;
2804*4882a593Smuzhiyun }
2805*4882a593Smuzhiyun 
2806*4882a593Smuzhiyun static const struct fs_parameter_spec selinux_fs_parameters[] = {
2807*4882a593Smuzhiyun 	fsparam_string(CONTEXT_STR,	Opt_context),
2808*4882a593Smuzhiyun 	fsparam_string(DEFCONTEXT_STR,	Opt_defcontext),
2809*4882a593Smuzhiyun 	fsparam_string(FSCONTEXT_STR,	Opt_fscontext),
2810*4882a593Smuzhiyun 	fsparam_string(ROOTCONTEXT_STR,	Opt_rootcontext),
2811*4882a593Smuzhiyun 	fsparam_flag  (SECLABEL_STR,	Opt_seclabel),
2812*4882a593Smuzhiyun 	{}
2813*4882a593Smuzhiyun };
2814*4882a593Smuzhiyun 
selinux_fs_context_parse_param(struct fs_context * fc,struct fs_parameter * param)2815*4882a593Smuzhiyun static int selinux_fs_context_parse_param(struct fs_context *fc,
2816*4882a593Smuzhiyun 					  struct fs_parameter *param)
2817*4882a593Smuzhiyun {
2818*4882a593Smuzhiyun 	struct fs_parse_result result;
2819*4882a593Smuzhiyun 	int opt, rc;
2820*4882a593Smuzhiyun 
2821*4882a593Smuzhiyun 	opt = fs_parse(fc, selinux_fs_parameters, param, &result);
2822*4882a593Smuzhiyun 	if (opt < 0)
2823*4882a593Smuzhiyun 		return opt;
2824*4882a593Smuzhiyun 
2825*4882a593Smuzhiyun 	rc = selinux_add_opt(opt, param->string, &fc->security);
2826*4882a593Smuzhiyun 	if (!rc)
2827*4882a593Smuzhiyun 		param->string = NULL;
2828*4882a593Smuzhiyun 
2829*4882a593Smuzhiyun 	return rc;
2830*4882a593Smuzhiyun }
2831*4882a593Smuzhiyun 
2832*4882a593Smuzhiyun /* inode security operations */
2833*4882a593Smuzhiyun 
selinux_inode_alloc_security(struct inode * inode)2834*4882a593Smuzhiyun static int selinux_inode_alloc_security(struct inode *inode)
2835*4882a593Smuzhiyun {
2836*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
2837*4882a593Smuzhiyun 	u32 sid = current_sid();
2838*4882a593Smuzhiyun 
2839*4882a593Smuzhiyun 	spin_lock_init(&isec->lock);
2840*4882a593Smuzhiyun 	INIT_LIST_HEAD(&isec->list);
2841*4882a593Smuzhiyun 	isec->inode = inode;
2842*4882a593Smuzhiyun 	isec->sid = SECINITSID_UNLABELED;
2843*4882a593Smuzhiyun 	isec->sclass = SECCLASS_FILE;
2844*4882a593Smuzhiyun 	isec->task_sid = sid;
2845*4882a593Smuzhiyun 	isec->initialized = LABEL_INVALID;
2846*4882a593Smuzhiyun 
2847*4882a593Smuzhiyun 	return 0;
2848*4882a593Smuzhiyun }
2849*4882a593Smuzhiyun 
selinux_inode_free_security(struct inode * inode)2850*4882a593Smuzhiyun static void selinux_inode_free_security(struct inode *inode)
2851*4882a593Smuzhiyun {
2852*4882a593Smuzhiyun 	inode_free_security(inode);
2853*4882a593Smuzhiyun }
2854*4882a593Smuzhiyun 
selinux_dentry_init_security(struct dentry * dentry,int mode,const struct qstr * name,void ** ctx,u32 * ctxlen)2855*4882a593Smuzhiyun static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2856*4882a593Smuzhiyun 					const struct qstr *name, void **ctx,
2857*4882a593Smuzhiyun 					u32 *ctxlen)
2858*4882a593Smuzhiyun {
2859*4882a593Smuzhiyun 	u32 newsid;
2860*4882a593Smuzhiyun 	int rc;
2861*4882a593Smuzhiyun 
2862*4882a593Smuzhiyun 	rc = selinux_determine_inode_label(selinux_cred(current_cred()),
2863*4882a593Smuzhiyun 					   d_inode(dentry->d_parent), name,
2864*4882a593Smuzhiyun 					   inode_mode_to_security_class(mode),
2865*4882a593Smuzhiyun 					   &newsid);
2866*4882a593Smuzhiyun 	if (rc)
2867*4882a593Smuzhiyun 		return rc;
2868*4882a593Smuzhiyun 
2869*4882a593Smuzhiyun 	return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
2870*4882a593Smuzhiyun 				       ctxlen);
2871*4882a593Smuzhiyun }
2872*4882a593Smuzhiyun 
selinux_dentry_create_files_as(struct dentry * dentry,int mode,struct qstr * name,const struct cred * old,struct cred * new)2873*4882a593Smuzhiyun static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2874*4882a593Smuzhiyun 					  struct qstr *name,
2875*4882a593Smuzhiyun 					  const struct cred *old,
2876*4882a593Smuzhiyun 					  struct cred *new)
2877*4882a593Smuzhiyun {
2878*4882a593Smuzhiyun 	u32 newsid;
2879*4882a593Smuzhiyun 	int rc;
2880*4882a593Smuzhiyun 	struct task_security_struct *tsec;
2881*4882a593Smuzhiyun 
2882*4882a593Smuzhiyun 	rc = selinux_determine_inode_label(selinux_cred(old),
2883*4882a593Smuzhiyun 					   d_inode(dentry->d_parent), name,
2884*4882a593Smuzhiyun 					   inode_mode_to_security_class(mode),
2885*4882a593Smuzhiyun 					   &newsid);
2886*4882a593Smuzhiyun 	if (rc)
2887*4882a593Smuzhiyun 		return rc;
2888*4882a593Smuzhiyun 
2889*4882a593Smuzhiyun 	tsec = selinux_cred(new);
2890*4882a593Smuzhiyun 	tsec->create_sid = newsid;
2891*4882a593Smuzhiyun 	return 0;
2892*4882a593Smuzhiyun }
2893*4882a593Smuzhiyun 
selinux_inode_init_security(struct inode * inode,struct inode * dir,const struct qstr * qstr,const char ** name,void ** value,size_t * len)2894*4882a593Smuzhiyun static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2895*4882a593Smuzhiyun 				       const struct qstr *qstr,
2896*4882a593Smuzhiyun 				       const char **name,
2897*4882a593Smuzhiyun 				       void **value, size_t *len)
2898*4882a593Smuzhiyun {
2899*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
2900*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
2901*4882a593Smuzhiyun 	u32 newsid, clen;
2902*4882a593Smuzhiyun 	int rc;
2903*4882a593Smuzhiyun 	char *context;
2904*4882a593Smuzhiyun 
2905*4882a593Smuzhiyun 	sbsec = dir->i_sb->s_security;
2906*4882a593Smuzhiyun 
2907*4882a593Smuzhiyun 	newsid = tsec->create_sid;
2908*4882a593Smuzhiyun 
2909*4882a593Smuzhiyun 	rc = selinux_determine_inode_label(tsec, dir, qstr,
2910*4882a593Smuzhiyun 		inode_mode_to_security_class(inode->i_mode),
2911*4882a593Smuzhiyun 		&newsid);
2912*4882a593Smuzhiyun 	if (rc)
2913*4882a593Smuzhiyun 		return rc;
2914*4882a593Smuzhiyun 
2915*4882a593Smuzhiyun 	/* Possibly defer initialization to selinux_complete_init. */
2916*4882a593Smuzhiyun 	if (sbsec->flags & SE_SBINITIALIZED) {
2917*4882a593Smuzhiyun 		struct inode_security_struct *isec = selinux_inode(inode);
2918*4882a593Smuzhiyun 		isec->sclass = inode_mode_to_security_class(inode->i_mode);
2919*4882a593Smuzhiyun 		isec->sid = newsid;
2920*4882a593Smuzhiyun 		isec->initialized = LABEL_INITIALIZED;
2921*4882a593Smuzhiyun 	}
2922*4882a593Smuzhiyun 
2923*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state) ||
2924*4882a593Smuzhiyun 	    !(sbsec->flags & SBLABEL_MNT))
2925*4882a593Smuzhiyun 		return -EOPNOTSUPP;
2926*4882a593Smuzhiyun 
2927*4882a593Smuzhiyun 	if (name)
2928*4882a593Smuzhiyun 		*name = XATTR_SELINUX_SUFFIX;
2929*4882a593Smuzhiyun 
2930*4882a593Smuzhiyun 	if (value && len) {
2931*4882a593Smuzhiyun 		rc = security_sid_to_context_force(&selinux_state, newsid,
2932*4882a593Smuzhiyun 						   &context, &clen);
2933*4882a593Smuzhiyun 		if (rc)
2934*4882a593Smuzhiyun 			return rc;
2935*4882a593Smuzhiyun 		*value = context;
2936*4882a593Smuzhiyun 		*len = clen;
2937*4882a593Smuzhiyun 	}
2938*4882a593Smuzhiyun 
2939*4882a593Smuzhiyun 	return 0;
2940*4882a593Smuzhiyun }
2941*4882a593Smuzhiyun 
selinux_inode_init_security_anon(struct inode * inode,const struct qstr * name,const struct inode * context_inode)2942*4882a593Smuzhiyun static int selinux_inode_init_security_anon(struct inode *inode,
2943*4882a593Smuzhiyun 					    const struct qstr *name,
2944*4882a593Smuzhiyun 					    const struct inode *context_inode)
2945*4882a593Smuzhiyun {
2946*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
2947*4882a593Smuzhiyun 	struct common_audit_data ad;
2948*4882a593Smuzhiyun 	struct inode_security_struct *isec;
2949*4882a593Smuzhiyun 	int rc;
2950*4882a593Smuzhiyun 
2951*4882a593Smuzhiyun 	if (unlikely(!selinux_initialized(&selinux_state)))
2952*4882a593Smuzhiyun 		return 0;
2953*4882a593Smuzhiyun 
2954*4882a593Smuzhiyun 	isec = selinux_inode(inode);
2955*4882a593Smuzhiyun 
2956*4882a593Smuzhiyun 	/*
2957*4882a593Smuzhiyun 	 * We only get here once per ephemeral inode.  The inode has
2958*4882a593Smuzhiyun 	 * been initialized via inode_alloc_security but is otherwise
2959*4882a593Smuzhiyun 	 * untouched.
2960*4882a593Smuzhiyun 	 */
2961*4882a593Smuzhiyun 
2962*4882a593Smuzhiyun 	if (context_inode) {
2963*4882a593Smuzhiyun 		struct inode_security_struct *context_isec =
2964*4882a593Smuzhiyun 			selinux_inode(context_inode);
2965*4882a593Smuzhiyun 		if (context_isec->initialized != LABEL_INITIALIZED) {
2966*4882a593Smuzhiyun 			pr_err("SELinux:  context_inode is not initialized");
2967*4882a593Smuzhiyun 			return -EACCES;
2968*4882a593Smuzhiyun 		}
2969*4882a593Smuzhiyun 
2970*4882a593Smuzhiyun 		isec->sclass = context_isec->sclass;
2971*4882a593Smuzhiyun 		isec->sid = context_isec->sid;
2972*4882a593Smuzhiyun 	} else {
2973*4882a593Smuzhiyun 		isec->sclass = SECCLASS_ANON_INODE;
2974*4882a593Smuzhiyun 		rc = security_transition_sid(
2975*4882a593Smuzhiyun 			&selinux_state, tsec->sid, tsec->sid,
2976*4882a593Smuzhiyun 			isec->sclass, name, &isec->sid);
2977*4882a593Smuzhiyun 		if (rc)
2978*4882a593Smuzhiyun 			return rc;
2979*4882a593Smuzhiyun 	}
2980*4882a593Smuzhiyun 
2981*4882a593Smuzhiyun 	isec->initialized = LABEL_INITIALIZED;
2982*4882a593Smuzhiyun 	/*
2983*4882a593Smuzhiyun 	 * Now that we've initialized security, check whether we're
2984*4882a593Smuzhiyun 	 * allowed to actually create this type of anonymous inode.
2985*4882a593Smuzhiyun 	 */
2986*4882a593Smuzhiyun 
2987*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_INODE;
2988*4882a593Smuzhiyun 	ad.u.inode = inode;
2989*4882a593Smuzhiyun 
2990*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
2991*4882a593Smuzhiyun 			    tsec->sid,
2992*4882a593Smuzhiyun 			    isec->sid,
2993*4882a593Smuzhiyun 			    isec->sclass,
2994*4882a593Smuzhiyun 			    FILE__CREATE,
2995*4882a593Smuzhiyun 			    &ad);
2996*4882a593Smuzhiyun }
2997*4882a593Smuzhiyun 
selinux_inode_create(struct inode * dir,struct dentry * dentry,umode_t mode)2998*4882a593Smuzhiyun static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
2999*4882a593Smuzhiyun {
3000*4882a593Smuzhiyun 	return may_create(dir, dentry, SECCLASS_FILE);
3001*4882a593Smuzhiyun }
3002*4882a593Smuzhiyun 
selinux_inode_link(struct dentry * old_dentry,struct inode * dir,struct dentry * new_dentry)3003*4882a593Smuzhiyun static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
3004*4882a593Smuzhiyun {
3005*4882a593Smuzhiyun 	return may_link(dir, old_dentry, MAY_LINK);
3006*4882a593Smuzhiyun }
3007*4882a593Smuzhiyun 
selinux_inode_unlink(struct inode * dir,struct dentry * dentry)3008*4882a593Smuzhiyun static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
3009*4882a593Smuzhiyun {
3010*4882a593Smuzhiyun 	return may_link(dir, dentry, MAY_UNLINK);
3011*4882a593Smuzhiyun }
3012*4882a593Smuzhiyun 
selinux_inode_symlink(struct inode * dir,struct dentry * dentry,const char * name)3013*4882a593Smuzhiyun static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
3014*4882a593Smuzhiyun {
3015*4882a593Smuzhiyun 	return may_create(dir, dentry, SECCLASS_LNK_FILE);
3016*4882a593Smuzhiyun }
3017*4882a593Smuzhiyun 
selinux_inode_mkdir(struct inode * dir,struct dentry * dentry,umode_t mask)3018*4882a593Smuzhiyun static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
3019*4882a593Smuzhiyun {
3020*4882a593Smuzhiyun 	return may_create(dir, dentry, SECCLASS_DIR);
3021*4882a593Smuzhiyun }
3022*4882a593Smuzhiyun 
selinux_inode_rmdir(struct inode * dir,struct dentry * dentry)3023*4882a593Smuzhiyun static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
3024*4882a593Smuzhiyun {
3025*4882a593Smuzhiyun 	return may_link(dir, dentry, MAY_RMDIR);
3026*4882a593Smuzhiyun }
3027*4882a593Smuzhiyun 
selinux_inode_mknod(struct inode * dir,struct dentry * dentry,umode_t mode,dev_t dev)3028*4882a593Smuzhiyun static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
3029*4882a593Smuzhiyun {
3030*4882a593Smuzhiyun 	return may_create(dir, dentry, inode_mode_to_security_class(mode));
3031*4882a593Smuzhiyun }
3032*4882a593Smuzhiyun 
selinux_inode_rename(struct inode * old_inode,struct dentry * old_dentry,struct inode * new_inode,struct dentry * new_dentry)3033*4882a593Smuzhiyun static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
3034*4882a593Smuzhiyun 				struct inode *new_inode, struct dentry *new_dentry)
3035*4882a593Smuzhiyun {
3036*4882a593Smuzhiyun 	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
3037*4882a593Smuzhiyun }
3038*4882a593Smuzhiyun 
selinux_inode_readlink(struct dentry * dentry)3039*4882a593Smuzhiyun static int selinux_inode_readlink(struct dentry *dentry)
3040*4882a593Smuzhiyun {
3041*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3042*4882a593Smuzhiyun 
3043*4882a593Smuzhiyun 	return dentry_has_perm(cred, dentry, FILE__READ);
3044*4882a593Smuzhiyun }
3045*4882a593Smuzhiyun 
selinux_inode_follow_link(struct dentry * dentry,struct inode * inode,bool rcu)3046*4882a593Smuzhiyun static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
3047*4882a593Smuzhiyun 				     bool rcu)
3048*4882a593Smuzhiyun {
3049*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3050*4882a593Smuzhiyun 	struct common_audit_data ad;
3051*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3052*4882a593Smuzhiyun 	u32 sid;
3053*4882a593Smuzhiyun 
3054*4882a593Smuzhiyun 	validate_creds(cred);
3055*4882a593Smuzhiyun 
3056*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
3057*4882a593Smuzhiyun 	ad.u.dentry = dentry;
3058*4882a593Smuzhiyun 	sid = cred_sid(cred);
3059*4882a593Smuzhiyun 	isec = inode_security_rcu(inode, rcu);
3060*4882a593Smuzhiyun 	if (IS_ERR(isec))
3061*4882a593Smuzhiyun 		return PTR_ERR(isec);
3062*4882a593Smuzhiyun 
3063*4882a593Smuzhiyun 	return avc_has_perm_flags(&selinux_state,
3064*4882a593Smuzhiyun 				  sid, isec->sid, isec->sclass, FILE__READ, &ad,
3065*4882a593Smuzhiyun 				  rcu ? MAY_NOT_BLOCK : 0);
3066*4882a593Smuzhiyun }
3067*4882a593Smuzhiyun 
audit_inode_permission(struct inode * inode,u32 perms,u32 audited,u32 denied,int result)3068*4882a593Smuzhiyun static noinline int audit_inode_permission(struct inode *inode,
3069*4882a593Smuzhiyun 					   u32 perms, u32 audited, u32 denied,
3070*4882a593Smuzhiyun 					   int result)
3071*4882a593Smuzhiyun {
3072*4882a593Smuzhiyun 	struct common_audit_data ad;
3073*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
3074*4882a593Smuzhiyun 	int rc;
3075*4882a593Smuzhiyun 
3076*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_INODE;
3077*4882a593Smuzhiyun 	ad.u.inode = inode;
3078*4882a593Smuzhiyun 
3079*4882a593Smuzhiyun 	rc = slow_avc_audit(&selinux_state,
3080*4882a593Smuzhiyun 			    current_sid(), isec->sid, isec->sclass, perms,
3081*4882a593Smuzhiyun 			    audited, denied, result, &ad);
3082*4882a593Smuzhiyun 	if (rc)
3083*4882a593Smuzhiyun 		return rc;
3084*4882a593Smuzhiyun 	return 0;
3085*4882a593Smuzhiyun }
3086*4882a593Smuzhiyun 
selinux_inode_permission(struct inode * inode,int mask)3087*4882a593Smuzhiyun static int selinux_inode_permission(struct inode *inode, int mask)
3088*4882a593Smuzhiyun {
3089*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3090*4882a593Smuzhiyun 	u32 perms;
3091*4882a593Smuzhiyun 	bool from_access;
3092*4882a593Smuzhiyun 	bool no_block = mask & MAY_NOT_BLOCK;
3093*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3094*4882a593Smuzhiyun 	u32 sid;
3095*4882a593Smuzhiyun 	struct av_decision avd;
3096*4882a593Smuzhiyun 	int rc, rc2;
3097*4882a593Smuzhiyun 	u32 audited, denied;
3098*4882a593Smuzhiyun 
3099*4882a593Smuzhiyun 	from_access = mask & MAY_ACCESS;
3100*4882a593Smuzhiyun 	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3101*4882a593Smuzhiyun 
3102*4882a593Smuzhiyun 	/* No permission to check.  Existence test. */
3103*4882a593Smuzhiyun 	if (!mask)
3104*4882a593Smuzhiyun 		return 0;
3105*4882a593Smuzhiyun 
3106*4882a593Smuzhiyun 	validate_creds(cred);
3107*4882a593Smuzhiyun 
3108*4882a593Smuzhiyun 	if (unlikely(IS_PRIVATE(inode)))
3109*4882a593Smuzhiyun 		return 0;
3110*4882a593Smuzhiyun 
3111*4882a593Smuzhiyun 	perms = file_mask_to_av(inode->i_mode, mask);
3112*4882a593Smuzhiyun 
3113*4882a593Smuzhiyun 	sid = cred_sid(cred);
3114*4882a593Smuzhiyun 	isec = inode_security_rcu(inode, no_block);
3115*4882a593Smuzhiyun 	if (IS_ERR(isec))
3116*4882a593Smuzhiyun 		return PTR_ERR(isec);
3117*4882a593Smuzhiyun 
3118*4882a593Smuzhiyun 	rc = avc_has_perm_noaudit(&selinux_state,
3119*4882a593Smuzhiyun 				  sid, isec->sid, isec->sclass, perms,
3120*4882a593Smuzhiyun 				  no_block ? AVC_NONBLOCKING : 0,
3121*4882a593Smuzhiyun 				  &avd);
3122*4882a593Smuzhiyun 	audited = avc_audit_required(perms, &avd, rc,
3123*4882a593Smuzhiyun 				     from_access ? FILE__AUDIT_ACCESS : 0,
3124*4882a593Smuzhiyun 				     &denied);
3125*4882a593Smuzhiyun 	if (likely(!audited))
3126*4882a593Smuzhiyun 		return rc;
3127*4882a593Smuzhiyun 
3128*4882a593Smuzhiyun 	/* fall back to ref-walk if we have to generate audit */
3129*4882a593Smuzhiyun 	if (no_block)
3130*4882a593Smuzhiyun 		return -ECHILD;
3131*4882a593Smuzhiyun 
3132*4882a593Smuzhiyun 	rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
3133*4882a593Smuzhiyun 	if (rc2)
3134*4882a593Smuzhiyun 		return rc2;
3135*4882a593Smuzhiyun 	return rc;
3136*4882a593Smuzhiyun }
3137*4882a593Smuzhiyun 
selinux_inode_setattr(struct dentry * dentry,struct iattr * iattr)3138*4882a593Smuzhiyun static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3139*4882a593Smuzhiyun {
3140*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3141*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
3142*4882a593Smuzhiyun 	unsigned int ia_valid = iattr->ia_valid;
3143*4882a593Smuzhiyun 	__u32 av = FILE__WRITE;
3144*4882a593Smuzhiyun 
3145*4882a593Smuzhiyun 	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3146*4882a593Smuzhiyun 	if (ia_valid & ATTR_FORCE) {
3147*4882a593Smuzhiyun 		ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3148*4882a593Smuzhiyun 			      ATTR_FORCE);
3149*4882a593Smuzhiyun 		if (!ia_valid)
3150*4882a593Smuzhiyun 			return 0;
3151*4882a593Smuzhiyun 	}
3152*4882a593Smuzhiyun 
3153*4882a593Smuzhiyun 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3154*4882a593Smuzhiyun 			ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
3155*4882a593Smuzhiyun 		return dentry_has_perm(cred, dentry, FILE__SETATTR);
3156*4882a593Smuzhiyun 
3157*4882a593Smuzhiyun 	if (selinux_policycap_openperm() &&
3158*4882a593Smuzhiyun 	    inode->i_sb->s_magic != SOCKFS_MAGIC &&
3159*4882a593Smuzhiyun 	    (ia_valid & ATTR_SIZE) &&
3160*4882a593Smuzhiyun 	    !(ia_valid & ATTR_FILE))
3161*4882a593Smuzhiyun 		av |= FILE__OPEN;
3162*4882a593Smuzhiyun 
3163*4882a593Smuzhiyun 	return dentry_has_perm(cred, dentry, av);
3164*4882a593Smuzhiyun }
3165*4882a593Smuzhiyun 
selinux_inode_getattr(const struct path * path)3166*4882a593Smuzhiyun static int selinux_inode_getattr(const struct path *path)
3167*4882a593Smuzhiyun {
3168*4882a593Smuzhiyun 	return path_has_perm(current_cred(), path, FILE__GETATTR);
3169*4882a593Smuzhiyun }
3170*4882a593Smuzhiyun 
has_cap_mac_admin(bool audit)3171*4882a593Smuzhiyun static bool has_cap_mac_admin(bool audit)
3172*4882a593Smuzhiyun {
3173*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3174*4882a593Smuzhiyun 	unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
3175*4882a593Smuzhiyun 
3176*4882a593Smuzhiyun 	if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
3177*4882a593Smuzhiyun 		return false;
3178*4882a593Smuzhiyun 	if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
3179*4882a593Smuzhiyun 		return false;
3180*4882a593Smuzhiyun 	return true;
3181*4882a593Smuzhiyun }
3182*4882a593Smuzhiyun 
selinux_inode_setxattr(struct dentry * dentry,const char * name,const void * value,size_t size,int flags)3183*4882a593Smuzhiyun static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3184*4882a593Smuzhiyun 				  const void *value, size_t size, int flags)
3185*4882a593Smuzhiyun {
3186*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
3187*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3188*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec;
3189*4882a593Smuzhiyun 	struct common_audit_data ad;
3190*4882a593Smuzhiyun 	u32 newsid, sid = current_sid();
3191*4882a593Smuzhiyun 	int rc = 0;
3192*4882a593Smuzhiyun 
3193*4882a593Smuzhiyun 	if (strcmp(name, XATTR_NAME_SELINUX)) {
3194*4882a593Smuzhiyun 		rc = cap_inode_setxattr(dentry, name, value, size, flags);
3195*4882a593Smuzhiyun 		if (rc)
3196*4882a593Smuzhiyun 			return rc;
3197*4882a593Smuzhiyun 
3198*4882a593Smuzhiyun 		/* Not an attribute we recognize, so just check the
3199*4882a593Smuzhiyun 		   ordinary setattr permission. */
3200*4882a593Smuzhiyun 		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3201*4882a593Smuzhiyun 	}
3202*4882a593Smuzhiyun 
3203*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state))
3204*4882a593Smuzhiyun 		return (inode_owner_or_capable(inode) ? 0 : -EPERM);
3205*4882a593Smuzhiyun 
3206*4882a593Smuzhiyun 	sbsec = inode->i_sb->s_security;
3207*4882a593Smuzhiyun 	if (!(sbsec->flags & SBLABEL_MNT))
3208*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3209*4882a593Smuzhiyun 
3210*4882a593Smuzhiyun 	if (!inode_owner_or_capable(inode))
3211*4882a593Smuzhiyun 		return -EPERM;
3212*4882a593Smuzhiyun 
3213*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_DENTRY;
3214*4882a593Smuzhiyun 	ad.u.dentry = dentry;
3215*4882a593Smuzhiyun 
3216*4882a593Smuzhiyun 	isec = backing_inode_security(dentry);
3217*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
3218*4882a593Smuzhiyun 			  sid, isec->sid, isec->sclass,
3219*4882a593Smuzhiyun 			  FILE__RELABELFROM, &ad);
3220*4882a593Smuzhiyun 	if (rc)
3221*4882a593Smuzhiyun 		return rc;
3222*4882a593Smuzhiyun 
3223*4882a593Smuzhiyun 	rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3224*4882a593Smuzhiyun 				     GFP_KERNEL);
3225*4882a593Smuzhiyun 	if (rc == -EINVAL) {
3226*4882a593Smuzhiyun 		if (!has_cap_mac_admin(true)) {
3227*4882a593Smuzhiyun 			struct audit_buffer *ab;
3228*4882a593Smuzhiyun 			size_t audit_size;
3229*4882a593Smuzhiyun 
3230*4882a593Smuzhiyun 			/* We strip a nul only if it is at the end, otherwise the
3231*4882a593Smuzhiyun 			 * context contains a nul and we should audit that */
3232*4882a593Smuzhiyun 			if (value) {
3233*4882a593Smuzhiyun 				const char *str = value;
3234*4882a593Smuzhiyun 
3235*4882a593Smuzhiyun 				if (str[size - 1] == '\0')
3236*4882a593Smuzhiyun 					audit_size = size - 1;
3237*4882a593Smuzhiyun 				else
3238*4882a593Smuzhiyun 					audit_size = size;
3239*4882a593Smuzhiyun 			} else {
3240*4882a593Smuzhiyun 				audit_size = 0;
3241*4882a593Smuzhiyun 			}
3242*4882a593Smuzhiyun 			ab = audit_log_start(audit_context(),
3243*4882a593Smuzhiyun 					     GFP_ATOMIC, AUDIT_SELINUX_ERR);
3244*4882a593Smuzhiyun 			audit_log_format(ab, "op=setxattr invalid_context=");
3245*4882a593Smuzhiyun 			audit_log_n_untrustedstring(ab, value, audit_size);
3246*4882a593Smuzhiyun 			audit_log_end(ab);
3247*4882a593Smuzhiyun 
3248*4882a593Smuzhiyun 			return rc;
3249*4882a593Smuzhiyun 		}
3250*4882a593Smuzhiyun 		rc = security_context_to_sid_force(&selinux_state, value,
3251*4882a593Smuzhiyun 						   size, &newsid);
3252*4882a593Smuzhiyun 	}
3253*4882a593Smuzhiyun 	if (rc)
3254*4882a593Smuzhiyun 		return rc;
3255*4882a593Smuzhiyun 
3256*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
3257*4882a593Smuzhiyun 			  sid, newsid, isec->sclass,
3258*4882a593Smuzhiyun 			  FILE__RELABELTO, &ad);
3259*4882a593Smuzhiyun 	if (rc)
3260*4882a593Smuzhiyun 		return rc;
3261*4882a593Smuzhiyun 
3262*4882a593Smuzhiyun 	rc = security_validate_transition(&selinux_state, isec->sid, newsid,
3263*4882a593Smuzhiyun 					  sid, isec->sclass);
3264*4882a593Smuzhiyun 	if (rc)
3265*4882a593Smuzhiyun 		return rc;
3266*4882a593Smuzhiyun 
3267*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
3268*4882a593Smuzhiyun 			    newsid,
3269*4882a593Smuzhiyun 			    sbsec->sid,
3270*4882a593Smuzhiyun 			    SECCLASS_FILESYSTEM,
3271*4882a593Smuzhiyun 			    FILESYSTEM__ASSOCIATE,
3272*4882a593Smuzhiyun 			    &ad);
3273*4882a593Smuzhiyun }
3274*4882a593Smuzhiyun 
selinux_inode_post_setxattr(struct dentry * dentry,const char * name,const void * value,size_t size,int flags)3275*4882a593Smuzhiyun static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
3276*4882a593Smuzhiyun 					const void *value, size_t size,
3277*4882a593Smuzhiyun 					int flags)
3278*4882a593Smuzhiyun {
3279*4882a593Smuzhiyun 	struct inode *inode = d_backing_inode(dentry);
3280*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3281*4882a593Smuzhiyun 	u32 newsid;
3282*4882a593Smuzhiyun 	int rc;
3283*4882a593Smuzhiyun 
3284*4882a593Smuzhiyun 	if (strcmp(name, XATTR_NAME_SELINUX)) {
3285*4882a593Smuzhiyun 		/* Not an attribute we recognize, so nothing to do. */
3286*4882a593Smuzhiyun 		return;
3287*4882a593Smuzhiyun 	}
3288*4882a593Smuzhiyun 
3289*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state)) {
3290*4882a593Smuzhiyun 		/* If we haven't even been initialized, then we can't validate
3291*4882a593Smuzhiyun 		 * against a policy, so leave the label as invalid. It may
3292*4882a593Smuzhiyun 		 * resolve to a valid label on the next revalidation try if
3293*4882a593Smuzhiyun 		 * we've since initialized.
3294*4882a593Smuzhiyun 		 */
3295*4882a593Smuzhiyun 		return;
3296*4882a593Smuzhiyun 	}
3297*4882a593Smuzhiyun 
3298*4882a593Smuzhiyun 	rc = security_context_to_sid_force(&selinux_state, value, size,
3299*4882a593Smuzhiyun 					   &newsid);
3300*4882a593Smuzhiyun 	if (rc) {
3301*4882a593Smuzhiyun 		pr_err("SELinux:  unable to map context to SID"
3302*4882a593Smuzhiyun 		       "for (%s, %lu), rc=%d\n",
3303*4882a593Smuzhiyun 		       inode->i_sb->s_id, inode->i_ino, -rc);
3304*4882a593Smuzhiyun 		return;
3305*4882a593Smuzhiyun 	}
3306*4882a593Smuzhiyun 
3307*4882a593Smuzhiyun 	isec = backing_inode_security(dentry);
3308*4882a593Smuzhiyun 	spin_lock(&isec->lock);
3309*4882a593Smuzhiyun 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
3310*4882a593Smuzhiyun 	isec->sid = newsid;
3311*4882a593Smuzhiyun 	isec->initialized = LABEL_INITIALIZED;
3312*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
3313*4882a593Smuzhiyun 
3314*4882a593Smuzhiyun 	return;
3315*4882a593Smuzhiyun }
3316*4882a593Smuzhiyun 
selinux_inode_getxattr(struct dentry * dentry,const char * name)3317*4882a593Smuzhiyun static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
3318*4882a593Smuzhiyun {
3319*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3320*4882a593Smuzhiyun 
3321*4882a593Smuzhiyun 	return dentry_has_perm(cred, dentry, FILE__GETATTR);
3322*4882a593Smuzhiyun }
3323*4882a593Smuzhiyun 
selinux_inode_listxattr(struct dentry * dentry)3324*4882a593Smuzhiyun static int selinux_inode_listxattr(struct dentry *dentry)
3325*4882a593Smuzhiyun {
3326*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3327*4882a593Smuzhiyun 
3328*4882a593Smuzhiyun 	return dentry_has_perm(cred, dentry, FILE__GETATTR);
3329*4882a593Smuzhiyun }
3330*4882a593Smuzhiyun 
selinux_inode_removexattr(struct dentry * dentry,const char * name)3331*4882a593Smuzhiyun static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
3332*4882a593Smuzhiyun {
3333*4882a593Smuzhiyun 	if (strcmp(name, XATTR_NAME_SELINUX)) {
3334*4882a593Smuzhiyun 		int rc = cap_inode_removexattr(dentry, name);
3335*4882a593Smuzhiyun 		if (rc)
3336*4882a593Smuzhiyun 			return rc;
3337*4882a593Smuzhiyun 
3338*4882a593Smuzhiyun 		/* Not an attribute we recognize, so just check the
3339*4882a593Smuzhiyun 		   ordinary setattr permission. */
3340*4882a593Smuzhiyun 		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3341*4882a593Smuzhiyun 	}
3342*4882a593Smuzhiyun 
3343*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state))
3344*4882a593Smuzhiyun 		return 0;
3345*4882a593Smuzhiyun 
3346*4882a593Smuzhiyun 	/* No one is allowed to remove a SELinux security label.
3347*4882a593Smuzhiyun 	   You can change the label, but all data must be labeled. */
3348*4882a593Smuzhiyun 	return -EACCES;
3349*4882a593Smuzhiyun }
3350*4882a593Smuzhiyun 
selinux_path_notify(const struct path * path,u64 mask,unsigned int obj_type)3351*4882a593Smuzhiyun static int selinux_path_notify(const struct path *path, u64 mask,
3352*4882a593Smuzhiyun 						unsigned int obj_type)
3353*4882a593Smuzhiyun {
3354*4882a593Smuzhiyun 	int ret;
3355*4882a593Smuzhiyun 	u32 perm;
3356*4882a593Smuzhiyun 
3357*4882a593Smuzhiyun 	struct common_audit_data ad;
3358*4882a593Smuzhiyun 
3359*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_PATH;
3360*4882a593Smuzhiyun 	ad.u.path = *path;
3361*4882a593Smuzhiyun 
3362*4882a593Smuzhiyun 	/*
3363*4882a593Smuzhiyun 	 * Set permission needed based on the type of mark being set.
3364*4882a593Smuzhiyun 	 * Performs an additional check for sb watches.
3365*4882a593Smuzhiyun 	 */
3366*4882a593Smuzhiyun 	switch (obj_type) {
3367*4882a593Smuzhiyun 	case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
3368*4882a593Smuzhiyun 		perm = FILE__WATCH_MOUNT;
3369*4882a593Smuzhiyun 		break;
3370*4882a593Smuzhiyun 	case FSNOTIFY_OBJ_TYPE_SB:
3371*4882a593Smuzhiyun 		perm = FILE__WATCH_SB;
3372*4882a593Smuzhiyun 		ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
3373*4882a593Smuzhiyun 						FILESYSTEM__WATCH, &ad);
3374*4882a593Smuzhiyun 		if (ret)
3375*4882a593Smuzhiyun 			return ret;
3376*4882a593Smuzhiyun 		break;
3377*4882a593Smuzhiyun 	case FSNOTIFY_OBJ_TYPE_INODE:
3378*4882a593Smuzhiyun 		perm = FILE__WATCH;
3379*4882a593Smuzhiyun 		break;
3380*4882a593Smuzhiyun 	default:
3381*4882a593Smuzhiyun 		return -EINVAL;
3382*4882a593Smuzhiyun 	}
3383*4882a593Smuzhiyun 
3384*4882a593Smuzhiyun 	/* blocking watches require the file:watch_with_perm permission */
3385*4882a593Smuzhiyun 	if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
3386*4882a593Smuzhiyun 		perm |= FILE__WATCH_WITH_PERM;
3387*4882a593Smuzhiyun 
3388*4882a593Smuzhiyun 	/* watches on read-like events need the file:watch_reads permission */
3389*4882a593Smuzhiyun 	if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3390*4882a593Smuzhiyun 		perm |= FILE__WATCH_READS;
3391*4882a593Smuzhiyun 
3392*4882a593Smuzhiyun 	return path_has_perm(current_cred(), path, perm);
3393*4882a593Smuzhiyun }
3394*4882a593Smuzhiyun 
3395*4882a593Smuzhiyun /*
3396*4882a593Smuzhiyun  * Copy the inode security context value to the user.
3397*4882a593Smuzhiyun  *
3398*4882a593Smuzhiyun  * Permission check is handled by selinux_inode_getxattr hook.
3399*4882a593Smuzhiyun  */
selinux_inode_getsecurity(struct inode * inode,const char * name,void ** buffer,bool alloc)3400*4882a593Smuzhiyun static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
3401*4882a593Smuzhiyun {
3402*4882a593Smuzhiyun 	u32 size;
3403*4882a593Smuzhiyun 	int error;
3404*4882a593Smuzhiyun 	char *context = NULL;
3405*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3406*4882a593Smuzhiyun 
3407*4882a593Smuzhiyun 	/*
3408*4882a593Smuzhiyun 	 * If we're not initialized yet, then we can't validate contexts, so
3409*4882a593Smuzhiyun 	 * just let vfs_getxattr fall back to using the on-disk xattr.
3410*4882a593Smuzhiyun 	 */
3411*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state) ||
3412*4882a593Smuzhiyun 	    strcmp(name, XATTR_SELINUX_SUFFIX))
3413*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3414*4882a593Smuzhiyun 
3415*4882a593Smuzhiyun 	/*
3416*4882a593Smuzhiyun 	 * If the caller has CAP_MAC_ADMIN, then get the raw context
3417*4882a593Smuzhiyun 	 * value even if it is not defined by current policy; otherwise,
3418*4882a593Smuzhiyun 	 * use the in-core value under current policy.
3419*4882a593Smuzhiyun 	 * Use the non-auditing forms of the permission checks since
3420*4882a593Smuzhiyun 	 * getxattr may be called by unprivileged processes commonly
3421*4882a593Smuzhiyun 	 * and lack of permission just means that we fall back to the
3422*4882a593Smuzhiyun 	 * in-core context value, not a denial.
3423*4882a593Smuzhiyun 	 */
3424*4882a593Smuzhiyun 	isec = inode_security(inode);
3425*4882a593Smuzhiyun 	if (has_cap_mac_admin(false))
3426*4882a593Smuzhiyun 		error = security_sid_to_context_force(&selinux_state,
3427*4882a593Smuzhiyun 						      isec->sid, &context,
3428*4882a593Smuzhiyun 						      &size);
3429*4882a593Smuzhiyun 	else
3430*4882a593Smuzhiyun 		error = security_sid_to_context(&selinux_state, isec->sid,
3431*4882a593Smuzhiyun 						&context, &size);
3432*4882a593Smuzhiyun 	if (error)
3433*4882a593Smuzhiyun 		return error;
3434*4882a593Smuzhiyun 	error = size;
3435*4882a593Smuzhiyun 	if (alloc) {
3436*4882a593Smuzhiyun 		*buffer = context;
3437*4882a593Smuzhiyun 		goto out_nofree;
3438*4882a593Smuzhiyun 	}
3439*4882a593Smuzhiyun 	kfree(context);
3440*4882a593Smuzhiyun out_nofree:
3441*4882a593Smuzhiyun 	return error;
3442*4882a593Smuzhiyun }
3443*4882a593Smuzhiyun 
selinux_inode_setsecurity(struct inode * inode,const char * name,const void * value,size_t size,int flags)3444*4882a593Smuzhiyun static int selinux_inode_setsecurity(struct inode *inode, const char *name,
3445*4882a593Smuzhiyun 				     const void *value, size_t size, int flags)
3446*4882a593Smuzhiyun {
3447*4882a593Smuzhiyun 	struct inode_security_struct *isec = inode_security_novalidate(inode);
3448*4882a593Smuzhiyun 	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
3449*4882a593Smuzhiyun 	u32 newsid;
3450*4882a593Smuzhiyun 	int rc;
3451*4882a593Smuzhiyun 
3452*4882a593Smuzhiyun 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
3453*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3454*4882a593Smuzhiyun 
3455*4882a593Smuzhiyun 	if (!(sbsec->flags & SBLABEL_MNT))
3456*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3457*4882a593Smuzhiyun 
3458*4882a593Smuzhiyun 	if (!value || !size)
3459*4882a593Smuzhiyun 		return -EACCES;
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun 	rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3462*4882a593Smuzhiyun 				     GFP_KERNEL);
3463*4882a593Smuzhiyun 	if (rc)
3464*4882a593Smuzhiyun 		return rc;
3465*4882a593Smuzhiyun 
3466*4882a593Smuzhiyun 	spin_lock(&isec->lock);
3467*4882a593Smuzhiyun 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
3468*4882a593Smuzhiyun 	isec->sid = newsid;
3469*4882a593Smuzhiyun 	isec->initialized = LABEL_INITIALIZED;
3470*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
3471*4882a593Smuzhiyun 	return 0;
3472*4882a593Smuzhiyun }
3473*4882a593Smuzhiyun 
selinux_inode_listsecurity(struct inode * inode,char * buffer,size_t buffer_size)3474*4882a593Smuzhiyun static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3475*4882a593Smuzhiyun {
3476*4882a593Smuzhiyun 	const int len = sizeof(XATTR_NAME_SELINUX);
3477*4882a593Smuzhiyun 
3478*4882a593Smuzhiyun 	if (!selinux_initialized(&selinux_state))
3479*4882a593Smuzhiyun 		return 0;
3480*4882a593Smuzhiyun 
3481*4882a593Smuzhiyun 	if (buffer && len <= buffer_size)
3482*4882a593Smuzhiyun 		memcpy(buffer, XATTR_NAME_SELINUX, len);
3483*4882a593Smuzhiyun 	return len;
3484*4882a593Smuzhiyun }
3485*4882a593Smuzhiyun 
selinux_inode_getsecid(struct inode * inode,u32 * secid)3486*4882a593Smuzhiyun static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
3487*4882a593Smuzhiyun {
3488*4882a593Smuzhiyun 	struct inode_security_struct *isec = inode_security_novalidate(inode);
3489*4882a593Smuzhiyun 	*secid = isec->sid;
3490*4882a593Smuzhiyun }
3491*4882a593Smuzhiyun 
selinux_inode_copy_up(struct dentry * src,struct cred ** new)3492*4882a593Smuzhiyun static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3493*4882a593Smuzhiyun {
3494*4882a593Smuzhiyun 	u32 sid;
3495*4882a593Smuzhiyun 	struct task_security_struct *tsec;
3496*4882a593Smuzhiyun 	struct cred *new_creds = *new;
3497*4882a593Smuzhiyun 
3498*4882a593Smuzhiyun 	if (new_creds == NULL) {
3499*4882a593Smuzhiyun 		new_creds = prepare_creds();
3500*4882a593Smuzhiyun 		if (!new_creds)
3501*4882a593Smuzhiyun 			return -ENOMEM;
3502*4882a593Smuzhiyun 	}
3503*4882a593Smuzhiyun 
3504*4882a593Smuzhiyun 	tsec = selinux_cred(new_creds);
3505*4882a593Smuzhiyun 	/* Get label from overlay inode and set it in create_sid */
3506*4882a593Smuzhiyun 	selinux_inode_getsecid(d_inode(src), &sid);
3507*4882a593Smuzhiyun 	tsec->create_sid = sid;
3508*4882a593Smuzhiyun 	*new = new_creds;
3509*4882a593Smuzhiyun 	return 0;
3510*4882a593Smuzhiyun }
3511*4882a593Smuzhiyun 
selinux_inode_copy_up_xattr(const char * name)3512*4882a593Smuzhiyun static int selinux_inode_copy_up_xattr(const char *name)
3513*4882a593Smuzhiyun {
3514*4882a593Smuzhiyun 	/* The copy_up hook above sets the initial context on an inode, but we
3515*4882a593Smuzhiyun 	 * don't then want to overwrite it by blindly copying all the lower
3516*4882a593Smuzhiyun 	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
3517*4882a593Smuzhiyun 	 */
3518*4882a593Smuzhiyun 	if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3519*4882a593Smuzhiyun 		return 1; /* Discard */
3520*4882a593Smuzhiyun 	/*
3521*4882a593Smuzhiyun 	 * Any other attribute apart from SELINUX is not claimed, supported
3522*4882a593Smuzhiyun 	 * by selinux.
3523*4882a593Smuzhiyun 	 */
3524*4882a593Smuzhiyun 	return -EOPNOTSUPP;
3525*4882a593Smuzhiyun }
3526*4882a593Smuzhiyun 
3527*4882a593Smuzhiyun /* kernfs node operations */
3528*4882a593Smuzhiyun 
selinux_kernfs_init_security(struct kernfs_node * kn_dir,struct kernfs_node * kn)3529*4882a593Smuzhiyun static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
3530*4882a593Smuzhiyun 					struct kernfs_node *kn)
3531*4882a593Smuzhiyun {
3532*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
3533*4882a593Smuzhiyun 	u32 parent_sid, newsid, clen;
3534*4882a593Smuzhiyun 	int rc;
3535*4882a593Smuzhiyun 	char *context;
3536*4882a593Smuzhiyun 
3537*4882a593Smuzhiyun 	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
3538*4882a593Smuzhiyun 	if (rc == -ENODATA)
3539*4882a593Smuzhiyun 		return 0;
3540*4882a593Smuzhiyun 	else if (rc < 0)
3541*4882a593Smuzhiyun 		return rc;
3542*4882a593Smuzhiyun 
3543*4882a593Smuzhiyun 	clen = (u32)rc;
3544*4882a593Smuzhiyun 	context = kmalloc(clen, GFP_KERNEL);
3545*4882a593Smuzhiyun 	if (!context)
3546*4882a593Smuzhiyun 		return -ENOMEM;
3547*4882a593Smuzhiyun 
3548*4882a593Smuzhiyun 	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, context, clen);
3549*4882a593Smuzhiyun 	if (rc < 0) {
3550*4882a593Smuzhiyun 		kfree(context);
3551*4882a593Smuzhiyun 		return rc;
3552*4882a593Smuzhiyun 	}
3553*4882a593Smuzhiyun 
3554*4882a593Smuzhiyun 	rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid,
3555*4882a593Smuzhiyun 				     GFP_KERNEL);
3556*4882a593Smuzhiyun 	kfree(context);
3557*4882a593Smuzhiyun 	if (rc)
3558*4882a593Smuzhiyun 		return rc;
3559*4882a593Smuzhiyun 
3560*4882a593Smuzhiyun 	if (tsec->create_sid) {
3561*4882a593Smuzhiyun 		newsid = tsec->create_sid;
3562*4882a593Smuzhiyun 	} else {
3563*4882a593Smuzhiyun 		u16 secclass = inode_mode_to_security_class(kn->mode);
3564*4882a593Smuzhiyun 		struct qstr q;
3565*4882a593Smuzhiyun 
3566*4882a593Smuzhiyun 		q.name = kn->name;
3567*4882a593Smuzhiyun 		q.hash_len = hashlen_string(kn_dir, kn->name);
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 		rc = security_transition_sid(&selinux_state, tsec->sid,
3570*4882a593Smuzhiyun 					     parent_sid, secclass, &q,
3571*4882a593Smuzhiyun 					     &newsid);
3572*4882a593Smuzhiyun 		if (rc)
3573*4882a593Smuzhiyun 			return rc;
3574*4882a593Smuzhiyun 	}
3575*4882a593Smuzhiyun 
3576*4882a593Smuzhiyun 	rc = security_sid_to_context_force(&selinux_state, newsid,
3577*4882a593Smuzhiyun 					   &context, &clen);
3578*4882a593Smuzhiyun 	if (rc)
3579*4882a593Smuzhiyun 		return rc;
3580*4882a593Smuzhiyun 
3581*4882a593Smuzhiyun 	rc = kernfs_xattr_set(kn, XATTR_NAME_SELINUX, context, clen,
3582*4882a593Smuzhiyun 			      XATTR_CREATE);
3583*4882a593Smuzhiyun 	kfree(context);
3584*4882a593Smuzhiyun 	return rc;
3585*4882a593Smuzhiyun }
3586*4882a593Smuzhiyun 
3587*4882a593Smuzhiyun 
3588*4882a593Smuzhiyun /* file security operations */
3589*4882a593Smuzhiyun 
selinux_revalidate_file_permission(struct file * file,int mask)3590*4882a593Smuzhiyun static int selinux_revalidate_file_permission(struct file *file, int mask)
3591*4882a593Smuzhiyun {
3592*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3593*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
3594*4882a593Smuzhiyun 
3595*4882a593Smuzhiyun 	/* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3596*4882a593Smuzhiyun 	if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3597*4882a593Smuzhiyun 		mask |= MAY_APPEND;
3598*4882a593Smuzhiyun 
3599*4882a593Smuzhiyun 	return file_has_perm(cred, file,
3600*4882a593Smuzhiyun 			     file_mask_to_av(inode->i_mode, mask));
3601*4882a593Smuzhiyun }
3602*4882a593Smuzhiyun 
selinux_file_permission(struct file * file,int mask)3603*4882a593Smuzhiyun static int selinux_file_permission(struct file *file, int mask)
3604*4882a593Smuzhiyun {
3605*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
3606*4882a593Smuzhiyun 	struct file_security_struct *fsec = selinux_file(file);
3607*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3608*4882a593Smuzhiyun 	u32 sid = current_sid();
3609*4882a593Smuzhiyun 
3610*4882a593Smuzhiyun 	if (!mask)
3611*4882a593Smuzhiyun 		/* No permission to check.  Existence test. */
3612*4882a593Smuzhiyun 		return 0;
3613*4882a593Smuzhiyun 
3614*4882a593Smuzhiyun 	isec = inode_security(inode);
3615*4882a593Smuzhiyun 	if (sid == fsec->sid && fsec->isid == isec->sid &&
3616*4882a593Smuzhiyun 	    fsec->pseqno == avc_policy_seqno(&selinux_state))
3617*4882a593Smuzhiyun 		/* No change since file_open check. */
3618*4882a593Smuzhiyun 		return 0;
3619*4882a593Smuzhiyun 
3620*4882a593Smuzhiyun 	return selinux_revalidate_file_permission(file, mask);
3621*4882a593Smuzhiyun }
3622*4882a593Smuzhiyun 
selinux_file_alloc_security(struct file * file)3623*4882a593Smuzhiyun static int selinux_file_alloc_security(struct file *file)
3624*4882a593Smuzhiyun {
3625*4882a593Smuzhiyun 	struct file_security_struct *fsec = selinux_file(file);
3626*4882a593Smuzhiyun 	u32 sid = current_sid();
3627*4882a593Smuzhiyun 
3628*4882a593Smuzhiyun 	fsec->sid = sid;
3629*4882a593Smuzhiyun 	fsec->fown_sid = sid;
3630*4882a593Smuzhiyun 
3631*4882a593Smuzhiyun 	return 0;
3632*4882a593Smuzhiyun }
3633*4882a593Smuzhiyun 
3634*4882a593Smuzhiyun /*
3635*4882a593Smuzhiyun  * Check whether a task has the ioctl permission and cmd
3636*4882a593Smuzhiyun  * operation to an inode.
3637*4882a593Smuzhiyun  */
ioctl_has_perm(const struct cred * cred,struct file * file,u32 requested,u16 cmd)3638*4882a593Smuzhiyun static int ioctl_has_perm(const struct cred *cred, struct file *file,
3639*4882a593Smuzhiyun 		u32 requested, u16 cmd)
3640*4882a593Smuzhiyun {
3641*4882a593Smuzhiyun 	struct common_audit_data ad;
3642*4882a593Smuzhiyun 	struct file_security_struct *fsec = selinux_file(file);
3643*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
3644*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3645*4882a593Smuzhiyun 	struct lsm_ioctlop_audit ioctl;
3646*4882a593Smuzhiyun 	u32 ssid = cred_sid(cred);
3647*4882a593Smuzhiyun 	int rc;
3648*4882a593Smuzhiyun 	u8 driver = cmd >> 8;
3649*4882a593Smuzhiyun 	u8 xperm = cmd & 0xff;
3650*4882a593Smuzhiyun 
3651*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3652*4882a593Smuzhiyun 	ad.u.op = &ioctl;
3653*4882a593Smuzhiyun 	ad.u.op->cmd = cmd;
3654*4882a593Smuzhiyun 	ad.u.op->path = file->f_path;
3655*4882a593Smuzhiyun 
3656*4882a593Smuzhiyun 	if (ssid != fsec->sid) {
3657*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
3658*4882a593Smuzhiyun 				  ssid, fsec->sid,
3659*4882a593Smuzhiyun 				SECCLASS_FD,
3660*4882a593Smuzhiyun 				FD__USE,
3661*4882a593Smuzhiyun 				&ad);
3662*4882a593Smuzhiyun 		if (rc)
3663*4882a593Smuzhiyun 			goto out;
3664*4882a593Smuzhiyun 	}
3665*4882a593Smuzhiyun 
3666*4882a593Smuzhiyun 	if (unlikely(IS_PRIVATE(inode)))
3667*4882a593Smuzhiyun 		return 0;
3668*4882a593Smuzhiyun 
3669*4882a593Smuzhiyun 	isec = inode_security(inode);
3670*4882a593Smuzhiyun 	rc = avc_has_extended_perms(&selinux_state,
3671*4882a593Smuzhiyun 				    ssid, isec->sid, isec->sclass,
3672*4882a593Smuzhiyun 				    requested, driver, xperm, &ad);
3673*4882a593Smuzhiyun out:
3674*4882a593Smuzhiyun 	return rc;
3675*4882a593Smuzhiyun }
3676*4882a593Smuzhiyun 
selinux_file_ioctl(struct file * file,unsigned int cmd,unsigned long arg)3677*4882a593Smuzhiyun static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3678*4882a593Smuzhiyun 			      unsigned long arg)
3679*4882a593Smuzhiyun {
3680*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3681*4882a593Smuzhiyun 	int error = 0;
3682*4882a593Smuzhiyun 
3683*4882a593Smuzhiyun 	switch (cmd) {
3684*4882a593Smuzhiyun 	case FIONREAD:
3685*4882a593Smuzhiyun 	case FIBMAP:
3686*4882a593Smuzhiyun 	case FIGETBSZ:
3687*4882a593Smuzhiyun 	case FS_IOC_GETFLAGS:
3688*4882a593Smuzhiyun 	case FS_IOC_GETVERSION:
3689*4882a593Smuzhiyun 		error = file_has_perm(cred, file, FILE__GETATTR);
3690*4882a593Smuzhiyun 		break;
3691*4882a593Smuzhiyun 
3692*4882a593Smuzhiyun 	case FS_IOC_SETFLAGS:
3693*4882a593Smuzhiyun 	case FS_IOC_SETVERSION:
3694*4882a593Smuzhiyun 		error = file_has_perm(cred, file, FILE__SETATTR);
3695*4882a593Smuzhiyun 		break;
3696*4882a593Smuzhiyun 
3697*4882a593Smuzhiyun 	/* sys_ioctl() checks */
3698*4882a593Smuzhiyun 	case FIONBIO:
3699*4882a593Smuzhiyun 	case FIOASYNC:
3700*4882a593Smuzhiyun 		error = file_has_perm(cred, file, 0);
3701*4882a593Smuzhiyun 		break;
3702*4882a593Smuzhiyun 
3703*4882a593Smuzhiyun 	case KDSKBENT:
3704*4882a593Smuzhiyun 	case KDSKBSENT:
3705*4882a593Smuzhiyun 		error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3706*4882a593Smuzhiyun 					    CAP_OPT_NONE, true);
3707*4882a593Smuzhiyun 		break;
3708*4882a593Smuzhiyun 
3709*4882a593Smuzhiyun 	case FIOCLEX:
3710*4882a593Smuzhiyun 	case FIONCLEX:
3711*4882a593Smuzhiyun 		if (!selinux_policycap_ioctl_skip_cloexec())
3712*4882a593Smuzhiyun 			error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
3713*4882a593Smuzhiyun 		break;
3714*4882a593Smuzhiyun 
3715*4882a593Smuzhiyun 	/* default case assumes that the command will go
3716*4882a593Smuzhiyun 	 * to the file's ioctl() function.
3717*4882a593Smuzhiyun 	 */
3718*4882a593Smuzhiyun 	default:
3719*4882a593Smuzhiyun 		error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
3720*4882a593Smuzhiyun 	}
3721*4882a593Smuzhiyun 	return error;
3722*4882a593Smuzhiyun }
3723*4882a593Smuzhiyun 
3724*4882a593Smuzhiyun static int default_noexec __ro_after_init;
3725*4882a593Smuzhiyun 
file_map_prot_check(struct file * file,unsigned long prot,int shared)3726*4882a593Smuzhiyun static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3727*4882a593Smuzhiyun {
3728*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3729*4882a593Smuzhiyun 	u32 sid = cred_sid(cred);
3730*4882a593Smuzhiyun 	int rc = 0;
3731*4882a593Smuzhiyun 
3732*4882a593Smuzhiyun 	if (default_noexec &&
3733*4882a593Smuzhiyun 	    (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3734*4882a593Smuzhiyun 				   (!shared && (prot & PROT_WRITE)))) {
3735*4882a593Smuzhiyun 		/*
3736*4882a593Smuzhiyun 		 * We are making executable an anonymous mapping or a
3737*4882a593Smuzhiyun 		 * private file mapping that will also be writable.
3738*4882a593Smuzhiyun 		 * This has an additional check.
3739*4882a593Smuzhiyun 		 */
3740*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
3741*4882a593Smuzhiyun 				  sid, sid, SECCLASS_PROCESS,
3742*4882a593Smuzhiyun 				  PROCESS__EXECMEM, NULL);
3743*4882a593Smuzhiyun 		if (rc)
3744*4882a593Smuzhiyun 			goto error;
3745*4882a593Smuzhiyun 	}
3746*4882a593Smuzhiyun 
3747*4882a593Smuzhiyun 	if (file) {
3748*4882a593Smuzhiyun 		/* read access is always possible with a mapping */
3749*4882a593Smuzhiyun 		u32 av = FILE__READ;
3750*4882a593Smuzhiyun 
3751*4882a593Smuzhiyun 		/* write access only matters if the mapping is shared */
3752*4882a593Smuzhiyun 		if (shared && (prot & PROT_WRITE))
3753*4882a593Smuzhiyun 			av |= FILE__WRITE;
3754*4882a593Smuzhiyun 
3755*4882a593Smuzhiyun 		if (prot & PROT_EXEC)
3756*4882a593Smuzhiyun 			av |= FILE__EXECUTE;
3757*4882a593Smuzhiyun 
3758*4882a593Smuzhiyun 		return file_has_perm(cred, file, av);
3759*4882a593Smuzhiyun 	}
3760*4882a593Smuzhiyun 
3761*4882a593Smuzhiyun error:
3762*4882a593Smuzhiyun 	return rc;
3763*4882a593Smuzhiyun }
3764*4882a593Smuzhiyun 
selinux_mmap_addr(unsigned long addr)3765*4882a593Smuzhiyun static int selinux_mmap_addr(unsigned long addr)
3766*4882a593Smuzhiyun {
3767*4882a593Smuzhiyun 	int rc = 0;
3768*4882a593Smuzhiyun 
3769*4882a593Smuzhiyun 	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3770*4882a593Smuzhiyun 		u32 sid = current_sid();
3771*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
3772*4882a593Smuzhiyun 				  sid, sid, SECCLASS_MEMPROTECT,
3773*4882a593Smuzhiyun 				  MEMPROTECT__MMAP_ZERO, NULL);
3774*4882a593Smuzhiyun 	}
3775*4882a593Smuzhiyun 
3776*4882a593Smuzhiyun 	return rc;
3777*4882a593Smuzhiyun }
3778*4882a593Smuzhiyun 
selinux_mmap_file(struct file * file,unsigned long reqprot,unsigned long prot,unsigned long flags)3779*4882a593Smuzhiyun static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3780*4882a593Smuzhiyun 			     unsigned long prot, unsigned long flags)
3781*4882a593Smuzhiyun {
3782*4882a593Smuzhiyun 	struct common_audit_data ad;
3783*4882a593Smuzhiyun 	int rc;
3784*4882a593Smuzhiyun 
3785*4882a593Smuzhiyun 	if (file) {
3786*4882a593Smuzhiyun 		ad.type = LSM_AUDIT_DATA_FILE;
3787*4882a593Smuzhiyun 		ad.u.file = file;
3788*4882a593Smuzhiyun 		rc = inode_has_perm(current_cred(), file_inode(file),
3789*4882a593Smuzhiyun 				    FILE__MAP, &ad);
3790*4882a593Smuzhiyun 		if (rc)
3791*4882a593Smuzhiyun 			return rc;
3792*4882a593Smuzhiyun 	}
3793*4882a593Smuzhiyun 
3794*4882a593Smuzhiyun 	if (checkreqprot_get(&selinux_state))
3795*4882a593Smuzhiyun 		prot = reqprot;
3796*4882a593Smuzhiyun 
3797*4882a593Smuzhiyun 	return file_map_prot_check(file, prot,
3798*4882a593Smuzhiyun 				   (flags & MAP_TYPE) == MAP_SHARED);
3799*4882a593Smuzhiyun }
3800*4882a593Smuzhiyun 
selinux_file_mprotect(struct vm_area_struct * vma,unsigned long reqprot,unsigned long prot)3801*4882a593Smuzhiyun static int selinux_file_mprotect(struct vm_area_struct *vma,
3802*4882a593Smuzhiyun 				 unsigned long reqprot,
3803*4882a593Smuzhiyun 				 unsigned long prot)
3804*4882a593Smuzhiyun {
3805*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3806*4882a593Smuzhiyun 	u32 sid = cred_sid(cred);
3807*4882a593Smuzhiyun 
3808*4882a593Smuzhiyun 	if (checkreqprot_get(&selinux_state))
3809*4882a593Smuzhiyun 		prot = reqprot;
3810*4882a593Smuzhiyun 
3811*4882a593Smuzhiyun 	if (default_noexec &&
3812*4882a593Smuzhiyun 	    (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
3813*4882a593Smuzhiyun 		int rc = 0;
3814*4882a593Smuzhiyun 		if (vma->vm_start >= vma->vm_mm->start_brk &&
3815*4882a593Smuzhiyun 		    vma->vm_end <= vma->vm_mm->brk) {
3816*4882a593Smuzhiyun 			rc = avc_has_perm(&selinux_state,
3817*4882a593Smuzhiyun 					  sid, sid, SECCLASS_PROCESS,
3818*4882a593Smuzhiyun 					  PROCESS__EXECHEAP, NULL);
3819*4882a593Smuzhiyun 		} else if (!vma->vm_file &&
3820*4882a593Smuzhiyun 			   ((vma->vm_start <= vma->vm_mm->start_stack &&
3821*4882a593Smuzhiyun 			     vma->vm_end >= vma->vm_mm->start_stack) ||
3822*4882a593Smuzhiyun 			    vma_is_stack_for_current(vma))) {
3823*4882a593Smuzhiyun 			rc = avc_has_perm(&selinux_state,
3824*4882a593Smuzhiyun 					  sid, sid, SECCLASS_PROCESS,
3825*4882a593Smuzhiyun 					  PROCESS__EXECSTACK, NULL);
3826*4882a593Smuzhiyun 		} else if (vma->vm_file && vma->anon_vma) {
3827*4882a593Smuzhiyun 			/*
3828*4882a593Smuzhiyun 			 * We are making executable a file mapping that has
3829*4882a593Smuzhiyun 			 * had some COW done. Since pages might have been
3830*4882a593Smuzhiyun 			 * written, check ability to execute the possibly
3831*4882a593Smuzhiyun 			 * modified content.  This typically should only
3832*4882a593Smuzhiyun 			 * occur for text relocations.
3833*4882a593Smuzhiyun 			 */
3834*4882a593Smuzhiyun 			rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
3835*4882a593Smuzhiyun 		}
3836*4882a593Smuzhiyun 		if (rc)
3837*4882a593Smuzhiyun 			return rc;
3838*4882a593Smuzhiyun 	}
3839*4882a593Smuzhiyun 
3840*4882a593Smuzhiyun 	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3841*4882a593Smuzhiyun }
3842*4882a593Smuzhiyun 
selinux_file_lock(struct file * file,unsigned int cmd)3843*4882a593Smuzhiyun static int selinux_file_lock(struct file *file, unsigned int cmd)
3844*4882a593Smuzhiyun {
3845*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3846*4882a593Smuzhiyun 
3847*4882a593Smuzhiyun 	return file_has_perm(cred, file, FILE__LOCK);
3848*4882a593Smuzhiyun }
3849*4882a593Smuzhiyun 
selinux_file_fcntl(struct file * file,unsigned int cmd,unsigned long arg)3850*4882a593Smuzhiyun static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3851*4882a593Smuzhiyun 			      unsigned long arg)
3852*4882a593Smuzhiyun {
3853*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3854*4882a593Smuzhiyun 	int err = 0;
3855*4882a593Smuzhiyun 
3856*4882a593Smuzhiyun 	switch (cmd) {
3857*4882a593Smuzhiyun 	case F_SETFL:
3858*4882a593Smuzhiyun 		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
3859*4882a593Smuzhiyun 			err = file_has_perm(cred, file, FILE__WRITE);
3860*4882a593Smuzhiyun 			break;
3861*4882a593Smuzhiyun 		}
3862*4882a593Smuzhiyun 		fallthrough;
3863*4882a593Smuzhiyun 	case F_SETOWN:
3864*4882a593Smuzhiyun 	case F_SETSIG:
3865*4882a593Smuzhiyun 	case F_GETFL:
3866*4882a593Smuzhiyun 	case F_GETOWN:
3867*4882a593Smuzhiyun 	case F_GETSIG:
3868*4882a593Smuzhiyun 	case F_GETOWNER_UIDS:
3869*4882a593Smuzhiyun 		/* Just check FD__USE permission */
3870*4882a593Smuzhiyun 		err = file_has_perm(cred, file, 0);
3871*4882a593Smuzhiyun 		break;
3872*4882a593Smuzhiyun 	case F_GETLK:
3873*4882a593Smuzhiyun 	case F_SETLK:
3874*4882a593Smuzhiyun 	case F_SETLKW:
3875*4882a593Smuzhiyun 	case F_OFD_GETLK:
3876*4882a593Smuzhiyun 	case F_OFD_SETLK:
3877*4882a593Smuzhiyun 	case F_OFD_SETLKW:
3878*4882a593Smuzhiyun #if BITS_PER_LONG == 32
3879*4882a593Smuzhiyun 	case F_GETLK64:
3880*4882a593Smuzhiyun 	case F_SETLK64:
3881*4882a593Smuzhiyun 	case F_SETLKW64:
3882*4882a593Smuzhiyun #endif
3883*4882a593Smuzhiyun 		err = file_has_perm(cred, file, FILE__LOCK);
3884*4882a593Smuzhiyun 		break;
3885*4882a593Smuzhiyun 	}
3886*4882a593Smuzhiyun 
3887*4882a593Smuzhiyun 	return err;
3888*4882a593Smuzhiyun }
3889*4882a593Smuzhiyun 
selinux_file_set_fowner(struct file * file)3890*4882a593Smuzhiyun static void selinux_file_set_fowner(struct file *file)
3891*4882a593Smuzhiyun {
3892*4882a593Smuzhiyun 	struct file_security_struct *fsec;
3893*4882a593Smuzhiyun 
3894*4882a593Smuzhiyun 	fsec = selinux_file(file);
3895*4882a593Smuzhiyun 	fsec->fown_sid = current_sid();
3896*4882a593Smuzhiyun }
3897*4882a593Smuzhiyun 
selinux_file_send_sigiotask(struct task_struct * tsk,struct fown_struct * fown,int signum)3898*4882a593Smuzhiyun static int selinux_file_send_sigiotask(struct task_struct *tsk,
3899*4882a593Smuzhiyun 				       struct fown_struct *fown, int signum)
3900*4882a593Smuzhiyun {
3901*4882a593Smuzhiyun 	struct file *file;
3902*4882a593Smuzhiyun 	u32 sid = task_sid(tsk);
3903*4882a593Smuzhiyun 	u32 perm;
3904*4882a593Smuzhiyun 	struct file_security_struct *fsec;
3905*4882a593Smuzhiyun 
3906*4882a593Smuzhiyun 	/* struct fown_struct is never outside the context of a struct file */
3907*4882a593Smuzhiyun 	file = container_of(fown, struct file, f_owner);
3908*4882a593Smuzhiyun 
3909*4882a593Smuzhiyun 	fsec = selinux_file(file);
3910*4882a593Smuzhiyun 
3911*4882a593Smuzhiyun 	if (!signum)
3912*4882a593Smuzhiyun 		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3913*4882a593Smuzhiyun 	else
3914*4882a593Smuzhiyun 		perm = signal_to_av(signum);
3915*4882a593Smuzhiyun 
3916*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
3917*4882a593Smuzhiyun 			    fsec->fown_sid, sid,
3918*4882a593Smuzhiyun 			    SECCLASS_PROCESS, perm, NULL);
3919*4882a593Smuzhiyun }
3920*4882a593Smuzhiyun 
selinux_file_receive(struct file * file)3921*4882a593Smuzhiyun static int selinux_file_receive(struct file *file)
3922*4882a593Smuzhiyun {
3923*4882a593Smuzhiyun 	const struct cred *cred = current_cred();
3924*4882a593Smuzhiyun 
3925*4882a593Smuzhiyun 	return file_has_perm(cred, file, file_to_av(file));
3926*4882a593Smuzhiyun }
3927*4882a593Smuzhiyun 
selinux_file_open(struct file * file)3928*4882a593Smuzhiyun static int selinux_file_open(struct file *file)
3929*4882a593Smuzhiyun {
3930*4882a593Smuzhiyun 	struct file_security_struct *fsec;
3931*4882a593Smuzhiyun 	struct inode_security_struct *isec;
3932*4882a593Smuzhiyun 
3933*4882a593Smuzhiyun 	fsec = selinux_file(file);
3934*4882a593Smuzhiyun 	isec = inode_security(file_inode(file));
3935*4882a593Smuzhiyun 	/*
3936*4882a593Smuzhiyun 	 * Save inode label and policy sequence number
3937*4882a593Smuzhiyun 	 * at open-time so that selinux_file_permission
3938*4882a593Smuzhiyun 	 * can determine whether revalidation is necessary.
3939*4882a593Smuzhiyun 	 * Task label is already saved in the file security
3940*4882a593Smuzhiyun 	 * struct as its SID.
3941*4882a593Smuzhiyun 	 */
3942*4882a593Smuzhiyun 	fsec->isid = isec->sid;
3943*4882a593Smuzhiyun 	fsec->pseqno = avc_policy_seqno(&selinux_state);
3944*4882a593Smuzhiyun 	/*
3945*4882a593Smuzhiyun 	 * Since the inode label or policy seqno may have changed
3946*4882a593Smuzhiyun 	 * between the selinux_inode_permission check and the saving
3947*4882a593Smuzhiyun 	 * of state above, recheck that access is still permitted.
3948*4882a593Smuzhiyun 	 * Otherwise, access might never be revalidated against the
3949*4882a593Smuzhiyun 	 * new inode label or new policy.
3950*4882a593Smuzhiyun 	 * This check is not redundant - do not remove.
3951*4882a593Smuzhiyun 	 */
3952*4882a593Smuzhiyun 	return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
3953*4882a593Smuzhiyun }
3954*4882a593Smuzhiyun 
3955*4882a593Smuzhiyun /* task security operations */
3956*4882a593Smuzhiyun 
selinux_task_alloc(struct task_struct * task,unsigned long clone_flags)3957*4882a593Smuzhiyun static int selinux_task_alloc(struct task_struct *task,
3958*4882a593Smuzhiyun 			      unsigned long clone_flags)
3959*4882a593Smuzhiyun {
3960*4882a593Smuzhiyun 	u32 sid = current_sid();
3961*4882a593Smuzhiyun 
3962*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
3963*4882a593Smuzhiyun 			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
3964*4882a593Smuzhiyun }
3965*4882a593Smuzhiyun 
3966*4882a593Smuzhiyun /*
3967*4882a593Smuzhiyun  * prepare a new set of credentials for modification
3968*4882a593Smuzhiyun  */
selinux_cred_prepare(struct cred * new,const struct cred * old,gfp_t gfp)3969*4882a593Smuzhiyun static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3970*4882a593Smuzhiyun 				gfp_t gfp)
3971*4882a593Smuzhiyun {
3972*4882a593Smuzhiyun 	const struct task_security_struct *old_tsec = selinux_cred(old);
3973*4882a593Smuzhiyun 	struct task_security_struct *tsec = selinux_cred(new);
3974*4882a593Smuzhiyun 
3975*4882a593Smuzhiyun 	*tsec = *old_tsec;
3976*4882a593Smuzhiyun 	return 0;
3977*4882a593Smuzhiyun }
3978*4882a593Smuzhiyun 
3979*4882a593Smuzhiyun /*
3980*4882a593Smuzhiyun  * transfer the SELinux data to a blank set of creds
3981*4882a593Smuzhiyun  */
selinux_cred_transfer(struct cred * new,const struct cred * old)3982*4882a593Smuzhiyun static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3983*4882a593Smuzhiyun {
3984*4882a593Smuzhiyun 	const struct task_security_struct *old_tsec = selinux_cred(old);
3985*4882a593Smuzhiyun 	struct task_security_struct *tsec = selinux_cred(new);
3986*4882a593Smuzhiyun 
3987*4882a593Smuzhiyun 	*tsec = *old_tsec;
3988*4882a593Smuzhiyun }
3989*4882a593Smuzhiyun 
selinux_cred_getsecid(const struct cred * c,u32 * secid)3990*4882a593Smuzhiyun static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3991*4882a593Smuzhiyun {
3992*4882a593Smuzhiyun 	*secid = cred_sid(c);
3993*4882a593Smuzhiyun }
3994*4882a593Smuzhiyun 
3995*4882a593Smuzhiyun /*
3996*4882a593Smuzhiyun  * set the security data for a kernel service
3997*4882a593Smuzhiyun  * - all the creation contexts are set to unlabelled
3998*4882a593Smuzhiyun  */
selinux_kernel_act_as(struct cred * new,u32 secid)3999*4882a593Smuzhiyun static int selinux_kernel_act_as(struct cred *new, u32 secid)
4000*4882a593Smuzhiyun {
4001*4882a593Smuzhiyun 	struct task_security_struct *tsec = selinux_cred(new);
4002*4882a593Smuzhiyun 	u32 sid = current_sid();
4003*4882a593Smuzhiyun 	int ret;
4004*4882a593Smuzhiyun 
4005*4882a593Smuzhiyun 	ret = avc_has_perm(&selinux_state,
4006*4882a593Smuzhiyun 			   sid, secid,
4007*4882a593Smuzhiyun 			   SECCLASS_KERNEL_SERVICE,
4008*4882a593Smuzhiyun 			   KERNEL_SERVICE__USE_AS_OVERRIDE,
4009*4882a593Smuzhiyun 			   NULL);
4010*4882a593Smuzhiyun 	if (ret == 0) {
4011*4882a593Smuzhiyun 		tsec->sid = secid;
4012*4882a593Smuzhiyun 		tsec->create_sid = 0;
4013*4882a593Smuzhiyun 		tsec->keycreate_sid = 0;
4014*4882a593Smuzhiyun 		tsec->sockcreate_sid = 0;
4015*4882a593Smuzhiyun 	}
4016*4882a593Smuzhiyun 	return ret;
4017*4882a593Smuzhiyun }
4018*4882a593Smuzhiyun 
4019*4882a593Smuzhiyun /*
4020*4882a593Smuzhiyun  * set the file creation context in a security record to the same as the
4021*4882a593Smuzhiyun  * objective context of the specified inode
4022*4882a593Smuzhiyun  */
selinux_kernel_create_files_as(struct cred * new,struct inode * inode)4023*4882a593Smuzhiyun static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
4024*4882a593Smuzhiyun {
4025*4882a593Smuzhiyun 	struct inode_security_struct *isec = inode_security(inode);
4026*4882a593Smuzhiyun 	struct task_security_struct *tsec = selinux_cred(new);
4027*4882a593Smuzhiyun 	u32 sid = current_sid();
4028*4882a593Smuzhiyun 	int ret;
4029*4882a593Smuzhiyun 
4030*4882a593Smuzhiyun 	ret = avc_has_perm(&selinux_state,
4031*4882a593Smuzhiyun 			   sid, isec->sid,
4032*4882a593Smuzhiyun 			   SECCLASS_KERNEL_SERVICE,
4033*4882a593Smuzhiyun 			   KERNEL_SERVICE__CREATE_FILES_AS,
4034*4882a593Smuzhiyun 			   NULL);
4035*4882a593Smuzhiyun 
4036*4882a593Smuzhiyun 	if (ret == 0)
4037*4882a593Smuzhiyun 		tsec->create_sid = isec->sid;
4038*4882a593Smuzhiyun 	return ret;
4039*4882a593Smuzhiyun }
4040*4882a593Smuzhiyun 
selinux_kernel_module_request(char * kmod_name)4041*4882a593Smuzhiyun static int selinux_kernel_module_request(char *kmod_name)
4042*4882a593Smuzhiyun {
4043*4882a593Smuzhiyun 	struct common_audit_data ad;
4044*4882a593Smuzhiyun 
4045*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_KMOD;
4046*4882a593Smuzhiyun 	ad.u.kmod_name = kmod_name;
4047*4882a593Smuzhiyun 
4048*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4049*4882a593Smuzhiyun 			    current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
4050*4882a593Smuzhiyun 			    SYSTEM__MODULE_REQUEST, &ad);
4051*4882a593Smuzhiyun }
4052*4882a593Smuzhiyun 
selinux_kernel_module_from_file(struct file * file)4053*4882a593Smuzhiyun static int selinux_kernel_module_from_file(struct file *file)
4054*4882a593Smuzhiyun {
4055*4882a593Smuzhiyun 	struct common_audit_data ad;
4056*4882a593Smuzhiyun 	struct inode_security_struct *isec;
4057*4882a593Smuzhiyun 	struct file_security_struct *fsec;
4058*4882a593Smuzhiyun 	u32 sid = current_sid();
4059*4882a593Smuzhiyun 	int rc;
4060*4882a593Smuzhiyun 
4061*4882a593Smuzhiyun 	/* init_module */
4062*4882a593Smuzhiyun 	if (file == NULL)
4063*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
4064*4882a593Smuzhiyun 				    sid, sid, SECCLASS_SYSTEM,
4065*4882a593Smuzhiyun 					SYSTEM__MODULE_LOAD, NULL);
4066*4882a593Smuzhiyun 
4067*4882a593Smuzhiyun 	/* finit_module */
4068*4882a593Smuzhiyun 
4069*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_FILE;
4070*4882a593Smuzhiyun 	ad.u.file = file;
4071*4882a593Smuzhiyun 
4072*4882a593Smuzhiyun 	fsec = selinux_file(file);
4073*4882a593Smuzhiyun 	if (sid != fsec->sid) {
4074*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
4075*4882a593Smuzhiyun 				  sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
4076*4882a593Smuzhiyun 		if (rc)
4077*4882a593Smuzhiyun 			return rc;
4078*4882a593Smuzhiyun 	}
4079*4882a593Smuzhiyun 
4080*4882a593Smuzhiyun 	isec = inode_security(file_inode(file));
4081*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4082*4882a593Smuzhiyun 			    sid, isec->sid, SECCLASS_SYSTEM,
4083*4882a593Smuzhiyun 				SYSTEM__MODULE_LOAD, &ad);
4084*4882a593Smuzhiyun }
4085*4882a593Smuzhiyun 
selinux_kernel_read_file(struct file * file,enum kernel_read_file_id id,bool contents)4086*4882a593Smuzhiyun static int selinux_kernel_read_file(struct file *file,
4087*4882a593Smuzhiyun 				    enum kernel_read_file_id id,
4088*4882a593Smuzhiyun 				    bool contents)
4089*4882a593Smuzhiyun {
4090*4882a593Smuzhiyun 	int rc = 0;
4091*4882a593Smuzhiyun 
4092*4882a593Smuzhiyun 	switch (id) {
4093*4882a593Smuzhiyun 	case READING_MODULE:
4094*4882a593Smuzhiyun 		rc = selinux_kernel_module_from_file(contents ? file : NULL);
4095*4882a593Smuzhiyun 		break;
4096*4882a593Smuzhiyun 	default:
4097*4882a593Smuzhiyun 		break;
4098*4882a593Smuzhiyun 	}
4099*4882a593Smuzhiyun 
4100*4882a593Smuzhiyun 	return rc;
4101*4882a593Smuzhiyun }
4102*4882a593Smuzhiyun 
selinux_kernel_load_data(enum kernel_load_data_id id,bool contents)4103*4882a593Smuzhiyun static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
4104*4882a593Smuzhiyun {
4105*4882a593Smuzhiyun 	int rc = 0;
4106*4882a593Smuzhiyun 
4107*4882a593Smuzhiyun 	switch (id) {
4108*4882a593Smuzhiyun 	case LOADING_MODULE:
4109*4882a593Smuzhiyun 		rc = selinux_kernel_module_from_file(NULL);
4110*4882a593Smuzhiyun 	default:
4111*4882a593Smuzhiyun 		break;
4112*4882a593Smuzhiyun 	}
4113*4882a593Smuzhiyun 
4114*4882a593Smuzhiyun 	return rc;
4115*4882a593Smuzhiyun }
4116*4882a593Smuzhiyun 
selinux_task_setpgid(struct task_struct * p,pid_t pgid)4117*4882a593Smuzhiyun static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
4118*4882a593Smuzhiyun {
4119*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4120*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4121*4882a593Smuzhiyun 			    PROCESS__SETPGID, NULL);
4122*4882a593Smuzhiyun }
4123*4882a593Smuzhiyun 
selinux_task_getpgid(struct task_struct * p)4124*4882a593Smuzhiyun static int selinux_task_getpgid(struct task_struct *p)
4125*4882a593Smuzhiyun {
4126*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4127*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4128*4882a593Smuzhiyun 			    PROCESS__GETPGID, NULL);
4129*4882a593Smuzhiyun }
4130*4882a593Smuzhiyun 
selinux_task_getsid(struct task_struct * p)4131*4882a593Smuzhiyun static int selinux_task_getsid(struct task_struct *p)
4132*4882a593Smuzhiyun {
4133*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4134*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4135*4882a593Smuzhiyun 			    PROCESS__GETSESSION, NULL);
4136*4882a593Smuzhiyun }
4137*4882a593Smuzhiyun 
selinux_task_getsecid(struct task_struct * p,u32 * secid)4138*4882a593Smuzhiyun static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
4139*4882a593Smuzhiyun {
4140*4882a593Smuzhiyun 	*secid = task_sid(p);
4141*4882a593Smuzhiyun }
4142*4882a593Smuzhiyun 
selinux_task_setnice(struct task_struct * p,int nice)4143*4882a593Smuzhiyun static int selinux_task_setnice(struct task_struct *p, int nice)
4144*4882a593Smuzhiyun {
4145*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4146*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4147*4882a593Smuzhiyun 			    PROCESS__SETSCHED, NULL);
4148*4882a593Smuzhiyun }
4149*4882a593Smuzhiyun 
selinux_task_setioprio(struct task_struct * p,int ioprio)4150*4882a593Smuzhiyun static int selinux_task_setioprio(struct task_struct *p, int ioprio)
4151*4882a593Smuzhiyun {
4152*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4153*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4154*4882a593Smuzhiyun 			    PROCESS__SETSCHED, NULL);
4155*4882a593Smuzhiyun }
4156*4882a593Smuzhiyun 
selinux_task_getioprio(struct task_struct * p)4157*4882a593Smuzhiyun static int selinux_task_getioprio(struct task_struct *p)
4158*4882a593Smuzhiyun {
4159*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4160*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4161*4882a593Smuzhiyun 			    PROCESS__GETSCHED, NULL);
4162*4882a593Smuzhiyun }
4163*4882a593Smuzhiyun 
selinux_task_prlimit(const struct cred * cred,const struct cred * tcred,unsigned int flags)4164*4882a593Smuzhiyun static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
4165*4882a593Smuzhiyun 				unsigned int flags)
4166*4882a593Smuzhiyun {
4167*4882a593Smuzhiyun 	u32 av = 0;
4168*4882a593Smuzhiyun 
4169*4882a593Smuzhiyun 	if (!flags)
4170*4882a593Smuzhiyun 		return 0;
4171*4882a593Smuzhiyun 	if (flags & LSM_PRLIMIT_WRITE)
4172*4882a593Smuzhiyun 		av |= PROCESS__SETRLIMIT;
4173*4882a593Smuzhiyun 	if (flags & LSM_PRLIMIT_READ)
4174*4882a593Smuzhiyun 		av |= PROCESS__GETRLIMIT;
4175*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4176*4882a593Smuzhiyun 			    cred_sid(cred), cred_sid(tcred),
4177*4882a593Smuzhiyun 			    SECCLASS_PROCESS, av, NULL);
4178*4882a593Smuzhiyun }
4179*4882a593Smuzhiyun 
selinux_task_setrlimit(struct task_struct * p,unsigned int resource,struct rlimit * new_rlim)4180*4882a593Smuzhiyun static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
4181*4882a593Smuzhiyun 		struct rlimit *new_rlim)
4182*4882a593Smuzhiyun {
4183*4882a593Smuzhiyun 	struct rlimit *old_rlim = p->signal->rlim + resource;
4184*4882a593Smuzhiyun 
4185*4882a593Smuzhiyun 	/* Control the ability to change the hard limit (whether
4186*4882a593Smuzhiyun 	   lowering or raising it), so that the hard limit can
4187*4882a593Smuzhiyun 	   later be used as a safe reset point for the soft limit
4188*4882a593Smuzhiyun 	   upon context transitions.  See selinux_bprm_committing_creds. */
4189*4882a593Smuzhiyun 	if (old_rlim->rlim_max != new_rlim->rlim_max)
4190*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
4191*4882a593Smuzhiyun 				    current_sid(), task_sid(p),
4192*4882a593Smuzhiyun 				    SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
4193*4882a593Smuzhiyun 
4194*4882a593Smuzhiyun 	return 0;
4195*4882a593Smuzhiyun }
4196*4882a593Smuzhiyun 
selinux_task_setscheduler(struct task_struct * p)4197*4882a593Smuzhiyun static int selinux_task_setscheduler(struct task_struct *p)
4198*4882a593Smuzhiyun {
4199*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4200*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4201*4882a593Smuzhiyun 			    PROCESS__SETSCHED, NULL);
4202*4882a593Smuzhiyun }
4203*4882a593Smuzhiyun 
selinux_task_getscheduler(struct task_struct * p)4204*4882a593Smuzhiyun static int selinux_task_getscheduler(struct task_struct *p)
4205*4882a593Smuzhiyun {
4206*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4207*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4208*4882a593Smuzhiyun 			    PROCESS__GETSCHED, NULL);
4209*4882a593Smuzhiyun }
4210*4882a593Smuzhiyun 
selinux_task_movememory(struct task_struct * p)4211*4882a593Smuzhiyun static int selinux_task_movememory(struct task_struct *p)
4212*4882a593Smuzhiyun {
4213*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4214*4882a593Smuzhiyun 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
4215*4882a593Smuzhiyun 			    PROCESS__SETSCHED, NULL);
4216*4882a593Smuzhiyun }
4217*4882a593Smuzhiyun 
selinux_task_kill(struct task_struct * p,struct kernel_siginfo * info,int sig,const struct cred * cred)4218*4882a593Smuzhiyun static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
4219*4882a593Smuzhiyun 				int sig, const struct cred *cred)
4220*4882a593Smuzhiyun {
4221*4882a593Smuzhiyun 	u32 secid;
4222*4882a593Smuzhiyun 	u32 perm;
4223*4882a593Smuzhiyun 
4224*4882a593Smuzhiyun 	if (!sig)
4225*4882a593Smuzhiyun 		perm = PROCESS__SIGNULL; /* null signal; existence test */
4226*4882a593Smuzhiyun 	else
4227*4882a593Smuzhiyun 		perm = signal_to_av(sig);
4228*4882a593Smuzhiyun 	if (!cred)
4229*4882a593Smuzhiyun 		secid = current_sid();
4230*4882a593Smuzhiyun 	else
4231*4882a593Smuzhiyun 		secid = cred_sid(cred);
4232*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4233*4882a593Smuzhiyun 			    secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
4234*4882a593Smuzhiyun }
4235*4882a593Smuzhiyun 
selinux_task_to_inode(struct task_struct * p,struct inode * inode)4236*4882a593Smuzhiyun static void selinux_task_to_inode(struct task_struct *p,
4237*4882a593Smuzhiyun 				  struct inode *inode)
4238*4882a593Smuzhiyun {
4239*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
4240*4882a593Smuzhiyun 	u32 sid = task_sid(p);
4241*4882a593Smuzhiyun 
4242*4882a593Smuzhiyun 	spin_lock(&isec->lock);
4243*4882a593Smuzhiyun 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
4244*4882a593Smuzhiyun 	isec->sid = sid;
4245*4882a593Smuzhiyun 	isec->initialized = LABEL_INITIALIZED;
4246*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
4247*4882a593Smuzhiyun }
4248*4882a593Smuzhiyun 
4249*4882a593Smuzhiyun /* Returns error only if unable to parse addresses */
selinux_parse_skb_ipv4(struct sk_buff * skb,struct common_audit_data * ad,u8 * proto)4250*4882a593Smuzhiyun static int selinux_parse_skb_ipv4(struct sk_buff *skb,
4251*4882a593Smuzhiyun 			struct common_audit_data *ad, u8 *proto)
4252*4882a593Smuzhiyun {
4253*4882a593Smuzhiyun 	int offset, ihlen, ret = -EINVAL;
4254*4882a593Smuzhiyun 	struct iphdr _iph, *ih;
4255*4882a593Smuzhiyun 
4256*4882a593Smuzhiyun 	offset = skb_network_offset(skb);
4257*4882a593Smuzhiyun 	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4258*4882a593Smuzhiyun 	if (ih == NULL)
4259*4882a593Smuzhiyun 		goto out;
4260*4882a593Smuzhiyun 
4261*4882a593Smuzhiyun 	ihlen = ih->ihl * 4;
4262*4882a593Smuzhiyun 	if (ihlen < sizeof(_iph))
4263*4882a593Smuzhiyun 		goto out;
4264*4882a593Smuzhiyun 
4265*4882a593Smuzhiyun 	ad->u.net->v4info.saddr = ih->saddr;
4266*4882a593Smuzhiyun 	ad->u.net->v4info.daddr = ih->daddr;
4267*4882a593Smuzhiyun 	ret = 0;
4268*4882a593Smuzhiyun 
4269*4882a593Smuzhiyun 	if (proto)
4270*4882a593Smuzhiyun 		*proto = ih->protocol;
4271*4882a593Smuzhiyun 
4272*4882a593Smuzhiyun 	switch (ih->protocol) {
4273*4882a593Smuzhiyun 	case IPPROTO_TCP: {
4274*4882a593Smuzhiyun 		struct tcphdr _tcph, *th;
4275*4882a593Smuzhiyun 
4276*4882a593Smuzhiyun 		if (ntohs(ih->frag_off) & IP_OFFSET)
4277*4882a593Smuzhiyun 			break;
4278*4882a593Smuzhiyun 
4279*4882a593Smuzhiyun 		offset += ihlen;
4280*4882a593Smuzhiyun 		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4281*4882a593Smuzhiyun 		if (th == NULL)
4282*4882a593Smuzhiyun 			break;
4283*4882a593Smuzhiyun 
4284*4882a593Smuzhiyun 		ad->u.net->sport = th->source;
4285*4882a593Smuzhiyun 		ad->u.net->dport = th->dest;
4286*4882a593Smuzhiyun 		break;
4287*4882a593Smuzhiyun 	}
4288*4882a593Smuzhiyun 
4289*4882a593Smuzhiyun 	case IPPROTO_UDP: {
4290*4882a593Smuzhiyun 		struct udphdr _udph, *uh;
4291*4882a593Smuzhiyun 
4292*4882a593Smuzhiyun 		if (ntohs(ih->frag_off) & IP_OFFSET)
4293*4882a593Smuzhiyun 			break;
4294*4882a593Smuzhiyun 
4295*4882a593Smuzhiyun 		offset += ihlen;
4296*4882a593Smuzhiyun 		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4297*4882a593Smuzhiyun 		if (uh == NULL)
4298*4882a593Smuzhiyun 			break;
4299*4882a593Smuzhiyun 
4300*4882a593Smuzhiyun 		ad->u.net->sport = uh->source;
4301*4882a593Smuzhiyun 		ad->u.net->dport = uh->dest;
4302*4882a593Smuzhiyun 		break;
4303*4882a593Smuzhiyun 	}
4304*4882a593Smuzhiyun 
4305*4882a593Smuzhiyun 	case IPPROTO_DCCP: {
4306*4882a593Smuzhiyun 		struct dccp_hdr _dccph, *dh;
4307*4882a593Smuzhiyun 
4308*4882a593Smuzhiyun 		if (ntohs(ih->frag_off) & IP_OFFSET)
4309*4882a593Smuzhiyun 			break;
4310*4882a593Smuzhiyun 
4311*4882a593Smuzhiyun 		offset += ihlen;
4312*4882a593Smuzhiyun 		dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4313*4882a593Smuzhiyun 		if (dh == NULL)
4314*4882a593Smuzhiyun 			break;
4315*4882a593Smuzhiyun 
4316*4882a593Smuzhiyun 		ad->u.net->sport = dh->dccph_sport;
4317*4882a593Smuzhiyun 		ad->u.net->dport = dh->dccph_dport;
4318*4882a593Smuzhiyun 		break;
4319*4882a593Smuzhiyun 	}
4320*4882a593Smuzhiyun 
4321*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IP_SCTP)
4322*4882a593Smuzhiyun 	case IPPROTO_SCTP: {
4323*4882a593Smuzhiyun 		struct sctphdr _sctph, *sh;
4324*4882a593Smuzhiyun 
4325*4882a593Smuzhiyun 		if (ntohs(ih->frag_off) & IP_OFFSET)
4326*4882a593Smuzhiyun 			break;
4327*4882a593Smuzhiyun 
4328*4882a593Smuzhiyun 		offset += ihlen;
4329*4882a593Smuzhiyun 		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4330*4882a593Smuzhiyun 		if (sh == NULL)
4331*4882a593Smuzhiyun 			break;
4332*4882a593Smuzhiyun 
4333*4882a593Smuzhiyun 		ad->u.net->sport = sh->source;
4334*4882a593Smuzhiyun 		ad->u.net->dport = sh->dest;
4335*4882a593Smuzhiyun 		break;
4336*4882a593Smuzhiyun 	}
4337*4882a593Smuzhiyun #endif
4338*4882a593Smuzhiyun 	default:
4339*4882a593Smuzhiyun 		break;
4340*4882a593Smuzhiyun 	}
4341*4882a593Smuzhiyun out:
4342*4882a593Smuzhiyun 	return ret;
4343*4882a593Smuzhiyun }
4344*4882a593Smuzhiyun 
4345*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
4346*4882a593Smuzhiyun 
4347*4882a593Smuzhiyun /* Returns error only if unable to parse addresses */
selinux_parse_skb_ipv6(struct sk_buff * skb,struct common_audit_data * ad,u8 * proto)4348*4882a593Smuzhiyun static int selinux_parse_skb_ipv6(struct sk_buff *skb,
4349*4882a593Smuzhiyun 			struct common_audit_data *ad, u8 *proto)
4350*4882a593Smuzhiyun {
4351*4882a593Smuzhiyun 	u8 nexthdr;
4352*4882a593Smuzhiyun 	int ret = -EINVAL, offset;
4353*4882a593Smuzhiyun 	struct ipv6hdr _ipv6h, *ip6;
4354*4882a593Smuzhiyun 	__be16 frag_off;
4355*4882a593Smuzhiyun 
4356*4882a593Smuzhiyun 	offset = skb_network_offset(skb);
4357*4882a593Smuzhiyun 	ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4358*4882a593Smuzhiyun 	if (ip6 == NULL)
4359*4882a593Smuzhiyun 		goto out;
4360*4882a593Smuzhiyun 
4361*4882a593Smuzhiyun 	ad->u.net->v6info.saddr = ip6->saddr;
4362*4882a593Smuzhiyun 	ad->u.net->v6info.daddr = ip6->daddr;
4363*4882a593Smuzhiyun 	ret = 0;
4364*4882a593Smuzhiyun 
4365*4882a593Smuzhiyun 	nexthdr = ip6->nexthdr;
4366*4882a593Smuzhiyun 	offset += sizeof(_ipv6h);
4367*4882a593Smuzhiyun 	offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
4368*4882a593Smuzhiyun 	if (offset < 0)
4369*4882a593Smuzhiyun 		goto out;
4370*4882a593Smuzhiyun 
4371*4882a593Smuzhiyun 	if (proto)
4372*4882a593Smuzhiyun 		*proto = nexthdr;
4373*4882a593Smuzhiyun 
4374*4882a593Smuzhiyun 	switch (nexthdr) {
4375*4882a593Smuzhiyun 	case IPPROTO_TCP: {
4376*4882a593Smuzhiyun 		struct tcphdr _tcph, *th;
4377*4882a593Smuzhiyun 
4378*4882a593Smuzhiyun 		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4379*4882a593Smuzhiyun 		if (th == NULL)
4380*4882a593Smuzhiyun 			break;
4381*4882a593Smuzhiyun 
4382*4882a593Smuzhiyun 		ad->u.net->sport = th->source;
4383*4882a593Smuzhiyun 		ad->u.net->dport = th->dest;
4384*4882a593Smuzhiyun 		break;
4385*4882a593Smuzhiyun 	}
4386*4882a593Smuzhiyun 
4387*4882a593Smuzhiyun 	case IPPROTO_UDP: {
4388*4882a593Smuzhiyun 		struct udphdr _udph, *uh;
4389*4882a593Smuzhiyun 
4390*4882a593Smuzhiyun 		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4391*4882a593Smuzhiyun 		if (uh == NULL)
4392*4882a593Smuzhiyun 			break;
4393*4882a593Smuzhiyun 
4394*4882a593Smuzhiyun 		ad->u.net->sport = uh->source;
4395*4882a593Smuzhiyun 		ad->u.net->dport = uh->dest;
4396*4882a593Smuzhiyun 		break;
4397*4882a593Smuzhiyun 	}
4398*4882a593Smuzhiyun 
4399*4882a593Smuzhiyun 	case IPPROTO_DCCP: {
4400*4882a593Smuzhiyun 		struct dccp_hdr _dccph, *dh;
4401*4882a593Smuzhiyun 
4402*4882a593Smuzhiyun 		dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4403*4882a593Smuzhiyun 		if (dh == NULL)
4404*4882a593Smuzhiyun 			break;
4405*4882a593Smuzhiyun 
4406*4882a593Smuzhiyun 		ad->u.net->sport = dh->dccph_sport;
4407*4882a593Smuzhiyun 		ad->u.net->dport = dh->dccph_dport;
4408*4882a593Smuzhiyun 		break;
4409*4882a593Smuzhiyun 	}
4410*4882a593Smuzhiyun 
4411*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IP_SCTP)
4412*4882a593Smuzhiyun 	case IPPROTO_SCTP: {
4413*4882a593Smuzhiyun 		struct sctphdr _sctph, *sh;
4414*4882a593Smuzhiyun 
4415*4882a593Smuzhiyun 		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4416*4882a593Smuzhiyun 		if (sh == NULL)
4417*4882a593Smuzhiyun 			break;
4418*4882a593Smuzhiyun 
4419*4882a593Smuzhiyun 		ad->u.net->sport = sh->source;
4420*4882a593Smuzhiyun 		ad->u.net->dport = sh->dest;
4421*4882a593Smuzhiyun 		break;
4422*4882a593Smuzhiyun 	}
4423*4882a593Smuzhiyun #endif
4424*4882a593Smuzhiyun 	/* includes fragments */
4425*4882a593Smuzhiyun 	default:
4426*4882a593Smuzhiyun 		break;
4427*4882a593Smuzhiyun 	}
4428*4882a593Smuzhiyun out:
4429*4882a593Smuzhiyun 	return ret;
4430*4882a593Smuzhiyun }
4431*4882a593Smuzhiyun 
4432*4882a593Smuzhiyun #endif /* IPV6 */
4433*4882a593Smuzhiyun 
selinux_parse_skb(struct sk_buff * skb,struct common_audit_data * ad,char ** _addrp,int src,u8 * proto)4434*4882a593Smuzhiyun static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
4435*4882a593Smuzhiyun 			     char **_addrp, int src, u8 *proto)
4436*4882a593Smuzhiyun {
4437*4882a593Smuzhiyun 	char *addrp;
4438*4882a593Smuzhiyun 	int ret;
4439*4882a593Smuzhiyun 
4440*4882a593Smuzhiyun 	switch (ad->u.net->family) {
4441*4882a593Smuzhiyun 	case PF_INET:
4442*4882a593Smuzhiyun 		ret = selinux_parse_skb_ipv4(skb, ad, proto);
4443*4882a593Smuzhiyun 		if (ret)
4444*4882a593Smuzhiyun 			goto parse_error;
4445*4882a593Smuzhiyun 		addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4446*4882a593Smuzhiyun 				       &ad->u.net->v4info.daddr);
4447*4882a593Smuzhiyun 		goto okay;
4448*4882a593Smuzhiyun 
4449*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
4450*4882a593Smuzhiyun 	case PF_INET6:
4451*4882a593Smuzhiyun 		ret = selinux_parse_skb_ipv6(skb, ad, proto);
4452*4882a593Smuzhiyun 		if (ret)
4453*4882a593Smuzhiyun 			goto parse_error;
4454*4882a593Smuzhiyun 		addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4455*4882a593Smuzhiyun 				       &ad->u.net->v6info.daddr);
4456*4882a593Smuzhiyun 		goto okay;
4457*4882a593Smuzhiyun #endif	/* IPV6 */
4458*4882a593Smuzhiyun 	default:
4459*4882a593Smuzhiyun 		addrp = NULL;
4460*4882a593Smuzhiyun 		goto okay;
4461*4882a593Smuzhiyun 	}
4462*4882a593Smuzhiyun 
4463*4882a593Smuzhiyun parse_error:
4464*4882a593Smuzhiyun 	pr_warn(
4465*4882a593Smuzhiyun 	       "SELinux: failure in selinux_parse_skb(),"
4466*4882a593Smuzhiyun 	       " unable to parse packet\n");
4467*4882a593Smuzhiyun 	return ret;
4468*4882a593Smuzhiyun 
4469*4882a593Smuzhiyun okay:
4470*4882a593Smuzhiyun 	if (_addrp)
4471*4882a593Smuzhiyun 		*_addrp = addrp;
4472*4882a593Smuzhiyun 	return 0;
4473*4882a593Smuzhiyun }
4474*4882a593Smuzhiyun 
4475*4882a593Smuzhiyun /**
4476*4882a593Smuzhiyun  * selinux_skb_peerlbl_sid - Determine the peer label of a packet
4477*4882a593Smuzhiyun  * @skb: the packet
4478*4882a593Smuzhiyun  * @family: protocol family
4479*4882a593Smuzhiyun  * @sid: the packet's peer label SID
4480*4882a593Smuzhiyun  *
4481*4882a593Smuzhiyun  * Description:
4482*4882a593Smuzhiyun  * Check the various different forms of network peer labeling and determine
4483*4882a593Smuzhiyun  * the peer label/SID for the packet; most of the magic actually occurs in
4484*4882a593Smuzhiyun  * the security server function security_net_peersid_cmp().  The function
4485*4882a593Smuzhiyun  * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4486*4882a593Smuzhiyun  * or -EACCES if @sid is invalid due to inconsistencies with the different
4487*4882a593Smuzhiyun  * peer labels.
4488*4882a593Smuzhiyun  *
4489*4882a593Smuzhiyun  */
selinux_skb_peerlbl_sid(struct sk_buff * skb,u16 family,u32 * sid)4490*4882a593Smuzhiyun static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
4491*4882a593Smuzhiyun {
4492*4882a593Smuzhiyun 	int err;
4493*4882a593Smuzhiyun 	u32 xfrm_sid;
4494*4882a593Smuzhiyun 	u32 nlbl_sid;
4495*4882a593Smuzhiyun 	u32 nlbl_type;
4496*4882a593Smuzhiyun 
4497*4882a593Smuzhiyun 	err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
4498*4882a593Smuzhiyun 	if (unlikely(err))
4499*4882a593Smuzhiyun 		return -EACCES;
4500*4882a593Smuzhiyun 	err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4501*4882a593Smuzhiyun 	if (unlikely(err))
4502*4882a593Smuzhiyun 		return -EACCES;
4503*4882a593Smuzhiyun 
4504*4882a593Smuzhiyun 	err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
4505*4882a593Smuzhiyun 					   nlbl_type, xfrm_sid, sid);
4506*4882a593Smuzhiyun 	if (unlikely(err)) {
4507*4882a593Smuzhiyun 		pr_warn(
4508*4882a593Smuzhiyun 		       "SELinux: failure in selinux_skb_peerlbl_sid(),"
4509*4882a593Smuzhiyun 		       " unable to determine packet's peer label\n");
4510*4882a593Smuzhiyun 		return -EACCES;
4511*4882a593Smuzhiyun 	}
4512*4882a593Smuzhiyun 
4513*4882a593Smuzhiyun 	return 0;
4514*4882a593Smuzhiyun }
4515*4882a593Smuzhiyun 
4516*4882a593Smuzhiyun /**
4517*4882a593Smuzhiyun  * selinux_conn_sid - Determine the child socket label for a connection
4518*4882a593Smuzhiyun  * @sk_sid: the parent socket's SID
4519*4882a593Smuzhiyun  * @skb_sid: the packet's SID
4520*4882a593Smuzhiyun  * @conn_sid: the resulting connection SID
4521*4882a593Smuzhiyun  *
4522*4882a593Smuzhiyun  * If @skb_sid is valid then the user:role:type information from @sk_sid is
4523*4882a593Smuzhiyun  * combined with the MLS information from @skb_sid in order to create
4524*4882a593Smuzhiyun  * @conn_sid.  If @skb_sid is not valid then @conn_sid is simply a copy
4525*4882a593Smuzhiyun  * of @sk_sid.  Returns zero on success, negative values on failure.
4526*4882a593Smuzhiyun  *
4527*4882a593Smuzhiyun  */
selinux_conn_sid(u32 sk_sid,u32 skb_sid,u32 * conn_sid)4528*4882a593Smuzhiyun static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4529*4882a593Smuzhiyun {
4530*4882a593Smuzhiyun 	int err = 0;
4531*4882a593Smuzhiyun 
4532*4882a593Smuzhiyun 	if (skb_sid != SECSID_NULL)
4533*4882a593Smuzhiyun 		err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
4534*4882a593Smuzhiyun 					    conn_sid);
4535*4882a593Smuzhiyun 	else
4536*4882a593Smuzhiyun 		*conn_sid = sk_sid;
4537*4882a593Smuzhiyun 
4538*4882a593Smuzhiyun 	return err;
4539*4882a593Smuzhiyun }
4540*4882a593Smuzhiyun 
4541*4882a593Smuzhiyun /* socket security operations */
4542*4882a593Smuzhiyun 
socket_sockcreate_sid(const struct task_security_struct * tsec,u16 secclass,u32 * socksid)4543*4882a593Smuzhiyun static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4544*4882a593Smuzhiyun 				 u16 secclass, u32 *socksid)
4545*4882a593Smuzhiyun {
4546*4882a593Smuzhiyun 	if (tsec->sockcreate_sid > SECSID_NULL) {
4547*4882a593Smuzhiyun 		*socksid = tsec->sockcreate_sid;
4548*4882a593Smuzhiyun 		return 0;
4549*4882a593Smuzhiyun 	}
4550*4882a593Smuzhiyun 
4551*4882a593Smuzhiyun 	return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
4552*4882a593Smuzhiyun 				       secclass, NULL, socksid);
4553*4882a593Smuzhiyun }
4554*4882a593Smuzhiyun 
sock_has_perm(struct sock * sk,u32 perms)4555*4882a593Smuzhiyun static int sock_has_perm(struct sock *sk, u32 perms)
4556*4882a593Smuzhiyun {
4557*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
4558*4882a593Smuzhiyun 	struct common_audit_data ad;
4559*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
4560*4882a593Smuzhiyun 
4561*4882a593Smuzhiyun 	if (sksec->sid == SECINITSID_KERNEL)
4562*4882a593Smuzhiyun 		return 0;
4563*4882a593Smuzhiyun 
4564*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
4565*4882a593Smuzhiyun 	ad.u.net = &net;
4566*4882a593Smuzhiyun 	ad.u.net->sk = sk;
4567*4882a593Smuzhiyun 
4568*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4569*4882a593Smuzhiyun 			    current_sid(), sksec->sid, sksec->sclass, perms,
4570*4882a593Smuzhiyun 			    &ad);
4571*4882a593Smuzhiyun }
4572*4882a593Smuzhiyun 
selinux_socket_create(int family,int type,int protocol,int kern)4573*4882a593Smuzhiyun static int selinux_socket_create(int family, int type,
4574*4882a593Smuzhiyun 				 int protocol, int kern)
4575*4882a593Smuzhiyun {
4576*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
4577*4882a593Smuzhiyun 	u32 newsid;
4578*4882a593Smuzhiyun 	u16 secclass;
4579*4882a593Smuzhiyun 	int rc;
4580*4882a593Smuzhiyun 
4581*4882a593Smuzhiyun 	if (kern)
4582*4882a593Smuzhiyun 		return 0;
4583*4882a593Smuzhiyun 
4584*4882a593Smuzhiyun 	secclass = socket_type_to_security_class(family, type, protocol);
4585*4882a593Smuzhiyun 	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4586*4882a593Smuzhiyun 	if (rc)
4587*4882a593Smuzhiyun 		return rc;
4588*4882a593Smuzhiyun 
4589*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
4590*4882a593Smuzhiyun 			    tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
4591*4882a593Smuzhiyun }
4592*4882a593Smuzhiyun 
selinux_socket_post_create(struct socket * sock,int family,int type,int protocol,int kern)4593*4882a593Smuzhiyun static int selinux_socket_post_create(struct socket *sock, int family,
4594*4882a593Smuzhiyun 				      int type, int protocol, int kern)
4595*4882a593Smuzhiyun {
4596*4882a593Smuzhiyun 	const struct task_security_struct *tsec = selinux_cred(current_cred());
4597*4882a593Smuzhiyun 	struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
4598*4882a593Smuzhiyun 	struct sk_security_struct *sksec;
4599*4882a593Smuzhiyun 	u16 sclass = socket_type_to_security_class(family, type, protocol);
4600*4882a593Smuzhiyun 	u32 sid = SECINITSID_KERNEL;
4601*4882a593Smuzhiyun 	int err = 0;
4602*4882a593Smuzhiyun 
4603*4882a593Smuzhiyun 	if (!kern) {
4604*4882a593Smuzhiyun 		err = socket_sockcreate_sid(tsec, sclass, &sid);
4605*4882a593Smuzhiyun 		if (err)
4606*4882a593Smuzhiyun 			return err;
4607*4882a593Smuzhiyun 	}
4608*4882a593Smuzhiyun 
4609*4882a593Smuzhiyun 	isec->sclass = sclass;
4610*4882a593Smuzhiyun 	isec->sid = sid;
4611*4882a593Smuzhiyun 	isec->initialized = LABEL_INITIALIZED;
4612*4882a593Smuzhiyun 
4613*4882a593Smuzhiyun 	if (sock->sk) {
4614*4882a593Smuzhiyun 		sksec = sock->sk->sk_security;
4615*4882a593Smuzhiyun 		sksec->sclass = sclass;
4616*4882a593Smuzhiyun 		sksec->sid = sid;
4617*4882a593Smuzhiyun 		/* Allows detection of the first association on this socket */
4618*4882a593Smuzhiyun 		if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4619*4882a593Smuzhiyun 			sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4620*4882a593Smuzhiyun 
4621*4882a593Smuzhiyun 		err = selinux_netlbl_socket_post_create(sock->sk, family);
4622*4882a593Smuzhiyun 	}
4623*4882a593Smuzhiyun 
4624*4882a593Smuzhiyun 	return err;
4625*4882a593Smuzhiyun }
4626*4882a593Smuzhiyun 
selinux_socket_socketpair(struct socket * socka,struct socket * sockb)4627*4882a593Smuzhiyun static int selinux_socket_socketpair(struct socket *socka,
4628*4882a593Smuzhiyun 				     struct socket *sockb)
4629*4882a593Smuzhiyun {
4630*4882a593Smuzhiyun 	struct sk_security_struct *sksec_a = socka->sk->sk_security;
4631*4882a593Smuzhiyun 	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4632*4882a593Smuzhiyun 
4633*4882a593Smuzhiyun 	sksec_a->peer_sid = sksec_b->sid;
4634*4882a593Smuzhiyun 	sksec_b->peer_sid = sksec_a->sid;
4635*4882a593Smuzhiyun 
4636*4882a593Smuzhiyun 	return 0;
4637*4882a593Smuzhiyun }
4638*4882a593Smuzhiyun 
4639*4882a593Smuzhiyun /* Range of port numbers used to automatically bind.
4640*4882a593Smuzhiyun    Need to determine whether we should perform a name_bind
4641*4882a593Smuzhiyun    permission check between the socket and the port number. */
4642*4882a593Smuzhiyun 
selinux_socket_bind(struct socket * sock,struct sockaddr * address,int addrlen)4643*4882a593Smuzhiyun static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4644*4882a593Smuzhiyun {
4645*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
4646*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
4647*4882a593Smuzhiyun 	u16 family;
4648*4882a593Smuzhiyun 	int err;
4649*4882a593Smuzhiyun 
4650*4882a593Smuzhiyun 	err = sock_has_perm(sk, SOCKET__BIND);
4651*4882a593Smuzhiyun 	if (err)
4652*4882a593Smuzhiyun 		goto out;
4653*4882a593Smuzhiyun 
4654*4882a593Smuzhiyun 	/* If PF_INET or PF_INET6, check name_bind permission for the port. */
4655*4882a593Smuzhiyun 	family = sk->sk_family;
4656*4882a593Smuzhiyun 	if (family == PF_INET || family == PF_INET6) {
4657*4882a593Smuzhiyun 		char *addrp;
4658*4882a593Smuzhiyun 		struct common_audit_data ad;
4659*4882a593Smuzhiyun 		struct lsm_network_audit net = {0,};
4660*4882a593Smuzhiyun 		struct sockaddr_in *addr4 = NULL;
4661*4882a593Smuzhiyun 		struct sockaddr_in6 *addr6 = NULL;
4662*4882a593Smuzhiyun 		u16 family_sa;
4663*4882a593Smuzhiyun 		unsigned short snum;
4664*4882a593Smuzhiyun 		u32 sid, node_perm;
4665*4882a593Smuzhiyun 
4666*4882a593Smuzhiyun 		/*
4667*4882a593Smuzhiyun 		 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4668*4882a593Smuzhiyun 		 * that validates multiple binding addresses. Because of this
4669*4882a593Smuzhiyun 		 * need to check address->sa_family as it is possible to have
4670*4882a593Smuzhiyun 		 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4671*4882a593Smuzhiyun 		 */
4672*4882a593Smuzhiyun 		if (addrlen < offsetofend(struct sockaddr, sa_family))
4673*4882a593Smuzhiyun 			return -EINVAL;
4674*4882a593Smuzhiyun 		family_sa = address->sa_family;
4675*4882a593Smuzhiyun 		switch (family_sa) {
4676*4882a593Smuzhiyun 		case AF_UNSPEC:
4677*4882a593Smuzhiyun 		case AF_INET:
4678*4882a593Smuzhiyun 			if (addrlen < sizeof(struct sockaddr_in))
4679*4882a593Smuzhiyun 				return -EINVAL;
4680*4882a593Smuzhiyun 			addr4 = (struct sockaddr_in *)address;
4681*4882a593Smuzhiyun 			if (family_sa == AF_UNSPEC) {
4682*4882a593Smuzhiyun 				/* see __inet_bind(), we only want to allow
4683*4882a593Smuzhiyun 				 * AF_UNSPEC if the address is INADDR_ANY
4684*4882a593Smuzhiyun 				 */
4685*4882a593Smuzhiyun 				if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4686*4882a593Smuzhiyun 					goto err_af;
4687*4882a593Smuzhiyun 				family_sa = AF_INET;
4688*4882a593Smuzhiyun 			}
4689*4882a593Smuzhiyun 			snum = ntohs(addr4->sin_port);
4690*4882a593Smuzhiyun 			addrp = (char *)&addr4->sin_addr.s_addr;
4691*4882a593Smuzhiyun 			break;
4692*4882a593Smuzhiyun 		case AF_INET6:
4693*4882a593Smuzhiyun 			if (addrlen < SIN6_LEN_RFC2133)
4694*4882a593Smuzhiyun 				return -EINVAL;
4695*4882a593Smuzhiyun 			addr6 = (struct sockaddr_in6 *)address;
4696*4882a593Smuzhiyun 			snum = ntohs(addr6->sin6_port);
4697*4882a593Smuzhiyun 			addrp = (char *)&addr6->sin6_addr.s6_addr;
4698*4882a593Smuzhiyun 			break;
4699*4882a593Smuzhiyun 		default:
4700*4882a593Smuzhiyun 			goto err_af;
4701*4882a593Smuzhiyun 		}
4702*4882a593Smuzhiyun 
4703*4882a593Smuzhiyun 		ad.type = LSM_AUDIT_DATA_NET;
4704*4882a593Smuzhiyun 		ad.u.net = &net;
4705*4882a593Smuzhiyun 		ad.u.net->sport = htons(snum);
4706*4882a593Smuzhiyun 		ad.u.net->family = family_sa;
4707*4882a593Smuzhiyun 
4708*4882a593Smuzhiyun 		if (snum) {
4709*4882a593Smuzhiyun 			int low, high;
4710*4882a593Smuzhiyun 
4711*4882a593Smuzhiyun 			inet_get_local_port_range(sock_net(sk), &low, &high);
4712*4882a593Smuzhiyun 
4713*4882a593Smuzhiyun 			if (inet_port_requires_bind_service(sock_net(sk), snum) ||
4714*4882a593Smuzhiyun 			    snum < low || snum > high) {
4715*4882a593Smuzhiyun 				err = sel_netport_sid(sk->sk_protocol,
4716*4882a593Smuzhiyun 						      snum, &sid);
4717*4882a593Smuzhiyun 				if (err)
4718*4882a593Smuzhiyun 					goto out;
4719*4882a593Smuzhiyun 				err = avc_has_perm(&selinux_state,
4720*4882a593Smuzhiyun 						   sksec->sid, sid,
4721*4882a593Smuzhiyun 						   sksec->sclass,
4722*4882a593Smuzhiyun 						   SOCKET__NAME_BIND, &ad);
4723*4882a593Smuzhiyun 				if (err)
4724*4882a593Smuzhiyun 					goto out;
4725*4882a593Smuzhiyun 			}
4726*4882a593Smuzhiyun 		}
4727*4882a593Smuzhiyun 
4728*4882a593Smuzhiyun 		switch (sksec->sclass) {
4729*4882a593Smuzhiyun 		case SECCLASS_TCP_SOCKET:
4730*4882a593Smuzhiyun 			node_perm = TCP_SOCKET__NODE_BIND;
4731*4882a593Smuzhiyun 			break;
4732*4882a593Smuzhiyun 
4733*4882a593Smuzhiyun 		case SECCLASS_UDP_SOCKET:
4734*4882a593Smuzhiyun 			node_perm = UDP_SOCKET__NODE_BIND;
4735*4882a593Smuzhiyun 			break;
4736*4882a593Smuzhiyun 
4737*4882a593Smuzhiyun 		case SECCLASS_DCCP_SOCKET:
4738*4882a593Smuzhiyun 			node_perm = DCCP_SOCKET__NODE_BIND;
4739*4882a593Smuzhiyun 			break;
4740*4882a593Smuzhiyun 
4741*4882a593Smuzhiyun 		case SECCLASS_SCTP_SOCKET:
4742*4882a593Smuzhiyun 			node_perm = SCTP_SOCKET__NODE_BIND;
4743*4882a593Smuzhiyun 			break;
4744*4882a593Smuzhiyun 
4745*4882a593Smuzhiyun 		default:
4746*4882a593Smuzhiyun 			node_perm = RAWIP_SOCKET__NODE_BIND;
4747*4882a593Smuzhiyun 			break;
4748*4882a593Smuzhiyun 		}
4749*4882a593Smuzhiyun 
4750*4882a593Smuzhiyun 		err = sel_netnode_sid(addrp, family_sa, &sid);
4751*4882a593Smuzhiyun 		if (err)
4752*4882a593Smuzhiyun 			goto out;
4753*4882a593Smuzhiyun 
4754*4882a593Smuzhiyun 		if (family_sa == AF_INET)
4755*4882a593Smuzhiyun 			ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
4756*4882a593Smuzhiyun 		else
4757*4882a593Smuzhiyun 			ad.u.net->v6info.saddr = addr6->sin6_addr;
4758*4882a593Smuzhiyun 
4759*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
4760*4882a593Smuzhiyun 				   sksec->sid, sid,
4761*4882a593Smuzhiyun 				   sksec->sclass, node_perm, &ad);
4762*4882a593Smuzhiyun 		if (err)
4763*4882a593Smuzhiyun 			goto out;
4764*4882a593Smuzhiyun 	}
4765*4882a593Smuzhiyun out:
4766*4882a593Smuzhiyun 	return err;
4767*4882a593Smuzhiyun err_af:
4768*4882a593Smuzhiyun 	/* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4769*4882a593Smuzhiyun 	if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4770*4882a593Smuzhiyun 		return -EINVAL;
4771*4882a593Smuzhiyun 	return -EAFNOSUPPORT;
4772*4882a593Smuzhiyun }
4773*4882a593Smuzhiyun 
4774*4882a593Smuzhiyun /* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
4775*4882a593Smuzhiyun  * and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
4776*4882a593Smuzhiyun  */
selinux_socket_connect_helper(struct socket * sock,struct sockaddr * address,int addrlen)4777*4882a593Smuzhiyun static int selinux_socket_connect_helper(struct socket *sock,
4778*4882a593Smuzhiyun 					 struct sockaddr *address, int addrlen)
4779*4882a593Smuzhiyun {
4780*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
4781*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
4782*4882a593Smuzhiyun 	int err;
4783*4882a593Smuzhiyun 
4784*4882a593Smuzhiyun 	err = sock_has_perm(sk, SOCKET__CONNECT);
4785*4882a593Smuzhiyun 	if (err)
4786*4882a593Smuzhiyun 		return err;
4787*4882a593Smuzhiyun 	if (addrlen < offsetofend(struct sockaddr, sa_family))
4788*4882a593Smuzhiyun 		return -EINVAL;
4789*4882a593Smuzhiyun 
4790*4882a593Smuzhiyun 	/* connect(AF_UNSPEC) has special handling, as it is a documented
4791*4882a593Smuzhiyun 	 * way to disconnect the socket
4792*4882a593Smuzhiyun 	 */
4793*4882a593Smuzhiyun 	if (address->sa_family == AF_UNSPEC)
4794*4882a593Smuzhiyun 		return 0;
4795*4882a593Smuzhiyun 
4796*4882a593Smuzhiyun 	/*
4797*4882a593Smuzhiyun 	 * If a TCP, DCCP or SCTP socket, check name_connect permission
4798*4882a593Smuzhiyun 	 * for the port.
4799*4882a593Smuzhiyun 	 */
4800*4882a593Smuzhiyun 	if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4801*4882a593Smuzhiyun 	    sksec->sclass == SECCLASS_DCCP_SOCKET ||
4802*4882a593Smuzhiyun 	    sksec->sclass == SECCLASS_SCTP_SOCKET) {
4803*4882a593Smuzhiyun 		struct common_audit_data ad;
4804*4882a593Smuzhiyun 		struct lsm_network_audit net = {0,};
4805*4882a593Smuzhiyun 		struct sockaddr_in *addr4 = NULL;
4806*4882a593Smuzhiyun 		struct sockaddr_in6 *addr6 = NULL;
4807*4882a593Smuzhiyun 		unsigned short snum;
4808*4882a593Smuzhiyun 		u32 sid, perm;
4809*4882a593Smuzhiyun 
4810*4882a593Smuzhiyun 		/* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4811*4882a593Smuzhiyun 		 * that validates multiple connect addresses. Because of this
4812*4882a593Smuzhiyun 		 * need to check address->sa_family as it is possible to have
4813*4882a593Smuzhiyun 		 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4814*4882a593Smuzhiyun 		 */
4815*4882a593Smuzhiyun 		switch (address->sa_family) {
4816*4882a593Smuzhiyun 		case AF_INET:
4817*4882a593Smuzhiyun 			addr4 = (struct sockaddr_in *)address;
4818*4882a593Smuzhiyun 			if (addrlen < sizeof(struct sockaddr_in))
4819*4882a593Smuzhiyun 				return -EINVAL;
4820*4882a593Smuzhiyun 			snum = ntohs(addr4->sin_port);
4821*4882a593Smuzhiyun 			break;
4822*4882a593Smuzhiyun 		case AF_INET6:
4823*4882a593Smuzhiyun 			addr6 = (struct sockaddr_in6 *)address;
4824*4882a593Smuzhiyun 			if (addrlen < SIN6_LEN_RFC2133)
4825*4882a593Smuzhiyun 				return -EINVAL;
4826*4882a593Smuzhiyun 			snum = ntohs(addr6->sin6_port);
4827*4882a593Smuzhiyun 			break;
4828*4882a593Smuzhiyun 		default:
4829*4882a593Smuzhiyun 			/* Note that SCTP services expect -EINVAL, whereas
4830*4882a593Smuzhiyun 			 * others expect -EAFNOSUPPORT.
4831*4882a593Smuzhiyun 			 */
4832*4882a593Smuzhiyun 			if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4833*4882a593Smuzhiyun 				return -EINVAL;
4834*4882a593Smuzhiyun 			else
4835*4882a593Smuzhiyun 				return -EAFNOSUPPORT;
4836*4882a593Smuzhiyun 		}
4837*4882a593Smuzhiyun 
4838*4882a593Smuzhiyun 		err = sel_netport_sid(sk->sk_protocol, snum, &sid);
4839*4882a593Smuzhiyun 		if (err)
4840*4882a593Smuzhiyun 			return err;
4841*4882a593Smuzhiyun 
4842*4882a593Smuzhiyun 		switch (sksec->sclass) {
4843*4882a593Smuzhiyun 		case SECCLASS_TCP_SOCKET:
4844*4882a593Smuzhiyun 			perm = TCP_SOCKET__NAME_CONNECT;
4845*4882a593Smuzhiyun 			break;
4846*4882a593Smuzhiyun 		case SECCLASS_DCCP_SOCKET:
4847*4882a593Smuzhiyun 			perm = DCCP_SOCKET__NAME_CONNECT;
4848*4882a593Smuzhiyun 			break;
4849*4882a593Smuzhiyun 		case SECCLASS_SCTP_SOCKET:
4850*4882a593Smuzhiyun 			perm = SCTP_SOCKET__NAME_CONNECT;
4851*4882a593Smuzhiyun 			break;
4852*4882a593Smuzhiyun 		}
4853*4882a593Smuzhiyun 
4854*4882a593Smuzhiyun 		ad.type = LSM_AUDIT_DATA_NET;
4855*4882a593Smuzhiyun 		ad.u.net = &net;
4856*4882a593Smuzhiyun 		ad.u.net->dport = htons(snum);
4857*4882a593Smuzhiyun 		ad.u.net->family = address->sa_family;
4858*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
4859*4882a593Smuzhiyun 				   sksec->sid, sid, sksec->sclass, perm, &ad);
4860*4882a593Smuzhiyun 		if (err)
4861*4882a593Smuzhiyun 			return err;
4862*4882a593Smuzhiyun 	}
4863*4882a593Smuzhiyun 
4864*4882a593Smuzhiyun 	return 0;
4865*4882a593Smuzhiyun }
4866*4882a593Smuzhiyun 
4867*4882a593Smuzhiyun /* Supports connect(2), see comments in selinux_socket_connect_helper() */
selinux_socket_connect(struct socket * sock,struct sockaddr * address,int addrlen)4868*4882a593Smuzhiyun static int selinux_socket_connect(struct socket *sock,
4869*4882a593Smuzhiyun 				  struct sockaddr *address, int addrlen)
4870*4882a593Smuzhiyun {
4871*4882a593Smuzhiyun 	int err;
4872*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
4873*4882a593Smuzhiyun 
4874*4882a593Smuzhiyun 	err = selinux_socket_connect_helper(sock, address, addrlen);
4875*4882a593Smuzhiyun 	if (err)
4876*4882a593Smuzhiyun 		return err;
4877*4882a593Smuzhiyun 
4878*4882a593Smuzhiyun 	return selinux_netlbl_socket_connect(sk, address);
4879*4882a593Smuzhiyun }
4880*4882a593Smuzhiyun 
selinux_socket_listen(struct socket * sock,int backlog)4881*4882a593Smuzhiyun static int selinux_socket_listen(struct socket *sock, int backlog)
4882*4882a593Smuzhiyun {
4883*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__LISTEN);
4884*4882a593Smuzhiyun }
4885*4882a593Smuzhiyun 
selinux_socket_accept(struct socket * sock,struct socket * newsock)4886*4882a593Smuzhiyun static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4887*4882a593Smuzhiyun {
4888*4882a593Smuzhiyun 	int err;
4889*4882a593Smuzhiyun 	struct inode_security_struct *isec;
4890*4882a593Smuzhiyun 	struct inode_security_struct *newisec;
4891*4882a593Smuzhiyun 	u16 sclass;
4892*4882a593Smuzhiyun 	u32 sid;
4893*4882a593Smuzhiyun 
4894*4882a593Smuzhiyun 	err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
4895*4882a593Smuzhiyun 	if (err)
4896*4882a593Smuzhiyun 		return err;
4897*4882a593Smuzhiyun 
4898*4882a593Smuzhiyun 	isec = inode_security_novalidate(SOCK_INODE(sock));
4899*4882a593Smuzhiyun 	spin_lock(&isec->lock);
4900*4882a593Smuzhiyun 	sclass = isec->sclass;
4901*4882a593Smuzhiyun 	sid = isec->sid;
4902*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
4903*4882a593Smuzhiyun 
4904*4882a593Smuzhiyun 	newisec = inode_security_novalidate(SOCK_INODE(newsock));
4905*4882a593Smuzhiyun 	newisec->sclass = sclass;
4906*4882a593Smuzhiyun 	newisec->sid = sid;
4907*4882a593Smuzhiyun 	newisec->initialized = LABEL_INITIALIZED;
4908*4882a593Smuzhiyun 
4909*4882a593Smuzhiyun 	return 0;
4910*4882a593Smuzhiyun }
4911*4882a593Smuzhiyun 
selinux_socket_sendmsg(struct socket * sock,struct msghdr * msg,int size)4912*4882a593Smuzhiyun static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
4913*4882a593Smuzhiyun 				  int size)
4914*4882a593Smuzhiyun {
4915*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__WRITE);
4916*4882a593Smuzhiyun }
4917*4882a593Smuzhiyun 
selinux_socket_recvmsg(struct socket * sock,struct msghdr * msg,int size,int flags)4918*4882a593Smuzhiyun static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4919*4882a593Smuzhiyun 				  int size, int flags)
4920*4882a593Smuzhiyun {
4921*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__READ);
4922*4882a593Smuzhiyun }
4923*4882a593Smuzhiyun 
selinux_socket_getsockname(struct socket * sock)4924*4882a593Smuzhiyun static int selinux_socket_getsockname(struct socket *sock)
4925*4882a593Smuzhiyun {
4926*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__GETATTR);
4927*4882a593Smuzhiyun }
4928*4882a593Smuzhiyun 
selinux_socket_getpeername(struct socket * sock)4929*4882a593Smuzhiyun static int selinux_socket_getpeername(struct socket *sock)
4930*4882a593Smuzhiyun {
4931*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__GETATTR);
4932*4882a593Smuzhiyun }
4933*4882a593Smuzhiyun 
selinux_socket_setsockopt(struct socket * sock,int level,int optname)4934*4882a593Smuzhiyun static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
4935*4882a593Smuzhiyun {
4936*4882a593Smuzhiyun 	int err;
4937*4882a593Smuzhiyun 
4938*4882a593Smuzhiyun 	err = sock_has_perm(sock->sk, SOCKET__SETOPT);
4939*4882a593Smuzhiyun 	if (err)
4940*4882a593Smuzhiyun 		return err;
4941*4882a593Smuzhiyun 
4942*4882a593Smuzhiyun 	return selinux_netlbl_socket_setsockopt(sock, level, optname);
4943*4882a593Smuzhiyun }
4944*4882a593Smuzhiyun 
selinux_socket_getsockopt(struct socket * sock,int level,int optname)4945*4882a593Smuzhiyun static int selinux_socket_getsockopt(struct socket *sock, int level,
4946*4882a593Smuzhiyun 				     int optname)
4947*4882a593Smuzhiyun {
4948*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__GETOPT);
4949*4882a593Smuzhiyun }
4950*4882a593Smuzhiyun 
selinux_socket_shutdown(struct socket * sock,int how)4951*4882a593Smuzhiyun static int selinux_socket_shutdown(struct socket *sock, int how)
4952*4882a593Smuzhiyun {
4953*4882a593Smuzhiyun 	return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
4954*4882a593Smuzhiyun }
4955*4882a593Smuzhiyun 
selinux_socket_unix_stream_connect(struct sock * sock,struct sock * other,struct sock * newsk)4956*4882a593Smuzhiyun static int selinux_socket_unix_stream_connect(struct sock *sock,
4957*4882a593Smuzhiyun 					      struct sock *other,
4958*4882a593Smuzhiyun 					      struct sock *newsk)
4959*4882a593Smuzhiyun {
4960*4882a593Smuzhiyun 	struct sk_security_struct *sksec_sock = sock->sk_security;
4961*4882a593Smuzhiyun 	struct sk_security_struct *sksec_other = other->sk_security;
4962*4882a593Smuzhiyun 	struct sk_security_struct *sksec_new = newsk->sk_security;
4963*4882a593Smuzhiyun 	struct common_audit_data ad;
4964*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
4965*4882a593Smuzhiyun 	int err;
4966*4882a593Smuzhiyun 
4967*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
4968*4882a593Smuzhiyun 	ad.u.net = &net;
4969*4882a593Smuzhiyun 	ad.u.net->sk = other;
4970*4882a593Smuzhiyun 
4971*4882a593Smuzhiyun 	err = avc_has_perm(&selinux_state,
4972*4882a593Smuzhiyun 			   sksec_sock->sid, sksec_other->sid,
4973*4882a593Smuzhiyun 			   sksec_other->sclass,
4974*4882a593Smuzhiyun 			   UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4975*4882a593Smuzhiyun 	if (err)
4976*4882a593Smuzhiyun 		return err;
4977*4882a593Smuzhiyun 
4978*4882a593Smuzhiyun 	/* server child socket */
4979*4882a593Smuzhiyun 	sksec_new->peer_sid = sksec_sock->sid;
4980*4882a593Smuzhiyun 	err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
4981*4882a593Smuzhiyun 				    sksec_sock->sid, &sksec_new->sid);
4982*4882a593Smuzhiyun 	if (err)
4983*4882a593Smuzhiyun 		return err;
4984*4882a593Smuzhiyun 
4985*4882a593Smuzhiyun 	/* connecting socket */
4986*4882a593Smuzhiyun 	sksec_sock->peer_sid = sksec_new->sid;
4987*4882a593Smuzhiyun 
4988*4882a593Smuzhiyun 	return 0;
4989*4882a593Smuzhiyun }
4990*4882a593Smuzhiyun 
selinux_socket_unix_may_send(struct socket * sock,struct socket * other)4991*4882a593Smuzhiyun static int selinux_socket_unix_may_send(struct socket *sock,
4992*4882a593Smuzhiyun 					struct socket *other)
4993*4882a593Smuzhiyun {
4994*4882a593Smuzhiyun 	struct sk_security_struct *ssec = sock->sk->sk_security;
4995*4882a593Smuzhiyun 	struct sk_security_struct *osec = other->sk->sk_security;
4996*4882a593Smuzhiyun 	struct common_audit_data ad;
4997*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
4998*4882a593Smuzhiyun 
4999*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5000*4882a593Smuzhiyun 	ad.u.net = &net;
5001*4882a593Smuzhiyun 	ad.u.net->sk = other->sk;
5002*4882a593Smuzhiyun 
5003*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
5004*4882a593Smuzhiyun 			    ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
5005*4882a593Smuzhiyun 			    &ad);
5006*4882a593Smuzhiyun }
5007*4882a593Smuzhiyun 
selinux_inet_sys_rcv_skb(struct net * ns,int ifindex,char * addrp,u16 family,u32 peer_sid,struct common_audit_data * ad)5008*4882a593Smuzhiyun static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
5009*4882a593Smuzhiyun 				    char *addrp, u16 family, u32 peer_sid,
5010*4882a593Smuzhiyun 				    struct common_audit_data *ad)
5011*4882a593Smuzhiyun {
5012*4882a593Smuzhiyun 	int err;
5013*4882a593Smuzhiyun 	u32 if_sid;
5014*4882a593Smuzhiyun 	u32 node_sid;
5015*4882a593Smuzhiyun 
5016*4882a593Smuzhiyun 	err = sel_netif_sid(ns, ifindex, &if_sid);
5017*4882a593Smuzhiyun 	if (err)
5018*4882a593Smuzhiyun 		return err;
5019*4882a593Smuzhiyun 	err = avc_has_perm(&selinux_state,
5020*4882a593Smuzhiyun 			   peer_sid, if_sid,
5021*4882a593Smuzhiyun 			   SECCLASS_NETIF, NETIF__INGRESS, ad);
5022*4882a593Smuzhiyun 	if (err)
5023*4882a593Smuzhiyun 		return err;
5024*4882a593Smuzhiyun 
5025*4882a593Smuzhiyun 	err = sel_netnode_sid(addrp, family, &node_sid);
5026*4882a593Smuzhiyun 	if (err)
5027*4882a593Smuzhiyun 		return err;
5028*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
5029*4882a593Smuzhiyun 			    peer_sid, node_sid,
5030*4882a593Smuzhiyun 			    SECCLASS_NODE, NODE__RECVFROM, ad);
5031*4882a593Smuzhiyun }
5032*4882a593Smuzhiyun 
selinux_sock_rcv_skb_compat(struct sock * sk,struct sk_buff * skb,u16 family)5033*4882a593Smuzhiyun static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
5034*4882a593Smuzhiyun 				       u16 family)
5035*4882a593Smuzhiyun {
5036*4882a593Smuzhiyun 	int err = 0;
5037*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5038*4882a593Smuzhiyun 	u32 sk_sid = sksec->sid;
5039*4882a593Smuzhiyun 	struct common_audit_data ad;
5040*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5041*4882a593Smuzhiyun 	char *addrp;
5042*4882a593Smuzhiyun 
5043*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5044*4882a593Smuzhiyun 	ad.u.net = &net;
5045*4882a593Smuzhiyun 	ad.u.net->netif = skb->skb_iif;
5046*4882a593Smuzhiyun 	ad.u.net->family = family;
5047*4882a593Smuzhiyun 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
5048*4882a593Smuzhiyun 	if (err)
5049*4882a593Smuzhiyun 		return err;
5050*4882a593Smuzhiyun 
5051*4882a593Smuzhiyun 	if (selinux_secmark_enabled()) {
5052*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
5053*4882a593Smuzhiyun 				   sk_sid, skb->secmark, SECCLASS_PACKET,
5054*4882a593Smuzhiyun 				   PACKET__RECV, &ad);
5055*4882a593Smuzhiyun 		if (err)
5056*4882a593Smuzhiyun 			return err;
5057*4882a593Smuzhiyun 	}
5058*4882a593Smuzhiyun 
5059*4882a593Smuzhiyun 	err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
5060*4882a593Smuzhiyun 	if (err)
5061*4882a593Smuzhiyun 		return err;
5062*4882a593Smuzhiyun 	err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
5063*4882a593Smuzhiyun 
5064*4882a593Smuzhiyun 	return err;
5065*4882a593Smuzhiyun }
5066*4882a593Smuzhiyun 
selinux_socket_sock_rcv_skb(struct sock * sk,struct sk_buff * skb)5067*4882a593Smuzhiyun static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
5068*4882a593Smuzhiyun {
5069*4882a593Smuzhiyun 	int err;
5070*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5071*4882a593Smuzhiyun 	u16 family = sk->sk_family;
5072*4882a593Smuzhiyun 	u32 sk_sid = sksec->sid;
5073*4882a593Smuzhiyun 	struct common_audit_data ad;
5074*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5075*4882a593Smuzhiyun 	char *addrp;
5076*4882a593Smuzhiyun 	u8 secmark_active;
5077*4882a593Smuzhiyun 	u8 peerlbl_active;
5078*4882a593Smuzhiyun 
5079*4882a593Smuzhiyun 	if (family != PF_INET && family != PF_INET6)
5080*4882a593Smuzhiyun 		return 0;
5081*4882a593Smuzhiyun 
5082*4882a593Smuzhiyun 	/* Handle mapped IPv4 packets arriving via IPv6 sockets */
5083*4882a593Smuzhiyun 	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5084*4882a593Smuzhiyun 		family = PF_INET;
5085*4882a593Smuzhiyun 
5086*4882a593Smuzhiyun 	/* If any sort of compatibility mode is enabled then handoff processing
5087*4882a593Smuzhiyun 	 * to the selinux_sock_rcv_skb_compat() function to deal with the
5088*4882a593Smuzhiyun 	 * special handling.  We do this in an attempt to keep this function
5089*4882a593Smuzhiyun 	 * as fast and as clean as possible. */
5090*4882a593Smuzhiyun 	if (!selinux_policycap_netpeer())
5091*4882a593Smuzhiyun 		return selinux_sock_rcv_skb_compat(sk, skb, family);
5092*4882a593Smuzhiyun 
5093*4882a593Smuzhiyun 	secmark_active = selinux_secmark_enabled();
5094*4882a593Smuzhiyun 	peerlbl_active = selinux_peerlbl_enabled();
5095*4882a593Smuzhiyun 	if (!secmark_active && !peerlbl_active)
5096*4882a593Smuzhiyun 		return 0;
5097*4882a593Smuzhiyun 
5098*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5099*4882a593Smuzhiyun 	ad.u.net = &net;
5100*4882a593Smuzhiyun 	ad.u.net->netif = skb->skb_iif;
5101*4882a593Smuzhiyun 	ad.u.net->family = family;
5102*4882a593Smuzhiyun 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
5103*4882a593Smuzhiyun 	if (err)
5104*4882a593Smuzhiyun 		return err;
5105*4882a593Smuzhiyun 
5106*4882a593Smuzhiyun 	if (peerlbl_active) {
5107*4882a593Smuzhiyun 		u32 peer_sid;
5108*4882a593Smuzhiyun 
5109*4882a593Smuzhiyun 		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
5110*4882a593Smuzhiyun 		if (err)
5111*4882a593Smuzhiyun 			return err;
5112*4882a593Smuzhiyun 		err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
5113*4882a593Smuzhiyun 					       addrp, family, peer_sid, &ad);
5114*4882a593Smuzhiyun 		if (err) {
5115*4882a593Smuzhiyun 			selinux_netlbl_err(skb, family, err, 0);
5116*4882a593Smuzhiyun 			return err;
5117*4882a593Smuzhiyun 		}
5118*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
5119*4882a593Smuzhiyun 				   sk_sid, peer_sid, SECCLASS_PEER,
5120*4882a593Smuzhiyun 				   PEER__RECV, &ad);
5121*4882a593Smuzhiyun 		if (err) {
5122*4882a593Smuzhiyun 			selinux_netlbl_err(skb, family, err, 0);
5123*4882a593Smuzhiyun 			return err;
5124*4882a593Smuzhiyun 		}
5125*4882a593Smuzhiyun 	}
5126*4882a593Smuzhiyun 
5127*4882a593Smuzhiyun 	if (secmark_active) {
5128*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
5129*4882a593Smuzhiyun 				   sk_sid, skb->secmark, SECCLASS_PACKET,
5130*4882a593Smuzhiyun 				   PACKET__RECV, &ad);
5131*4882a593Smuzhiyun 		if (err)
5132*4882a593Smuzhiyun 			return err;
5133*4882a593Smuzhiyun 	}
5134*4882a593Smuzhiyun 
5135*4882a593Smuzhiyun 	return err;
5136*4882a593Smuzhiyun }
5137*4882a593Smuzhiyun 
selinux_socket_getpeersec_stream(struct socket * sock,char __user * optval,int __user * optlen,unsigned len)5138*4882a593Smuzhiyun static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
5139*4882a593Smuzhiyun 					    int __user *optlen, unsigned len)
5140*4882a593Smuzhiyun {
5141*4882a593Smuzhiyun 	int err = 0;
5142*4882a593Smuzhiyun 	char *scontext;
5143*4882a593Smuzhiyun 	u32 scontext_len;
5144*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sock->sk->sk_security;
5145*4882a593Smuzhiyun 	u32 peer_sid = SECSID_NULL;
5146*4882a593Smuzhiyun 
5147*4882a593Smuzhiyun 	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
5148*4882a593Smuzhiyun 	    sksec->sclass == SECCLASS_TCP_SOCKET ||
5149*4882a593Smuzhiyun 	    sksec->sclass == SECCLASS_SCTP_SOCKET)
5150*4882a593Smuzhiyun 		peer_sid = sksec->peer_sid;
5151*4882a593Smuzhiyun 	if (peer_sid == SECSID_NULL)
5152*4882a593Smuzhiyun 		return -ENOPROTOOPT;
5153*4882a593Smuzhiyun 
5154*4882a593Smuzhiyun 	err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
5155*4882a593Smuzhiyun 				      &scontext_len);
5156*4882a593Smuzhiyun 	if (err)
5157*4882a593Smuzhiyun 		return err;
5158*4882a593Smuzhiyun 
5159*4882a593Smuzhiyun 	if (scontext_len > len) {
5160*4882a593Smuzhiyun 		err = -ERANGE;
5161*4882a593Smuzhiyun 		goto out_len;
5162*4882a593Smuzhiyun 	}
5163*4882a593Smuzhiyun 
5164*4882a593Smuzhiyun 	if (copy_to_user(optval, scontext, scontext_len))
5165*4882a593Smuzhiyun 		err = -EFAULT;
5166*4882a593Smuzhiyun 
5167*4882a593Smuzhiyun out_len:
5168*4882a593Smuzhiyun 	if (put_user(scontext_len, optlen))
5169*4882a593Smuzhiyun 		err = -EFAULT;
5170*4882a593Smuzhiyun 	kfree(scontext);
5171*4882a593Smuzhiyun 	return err;
5172*4882a593Smuzhiyun }
5173*4882a593Smuzhiyun 
selinux_socket_getpeersec_dgram(struct socket * sock,struct sk_buff * skb,u32 * secid)5174*4882a593Smuzhiyun static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
5175*4882a593Smuzhiyun {
5176*4882a593Smuzhiyun 	u32 peer_secid = SECSID_NULL;
5177*4882a593Smuzhiyun 	u16 family;
5178*4882a593Smuzhiyun 	struct inode_security_struct *isec;
5179*4882a593Smuzhiyun 
5180*4882a593Smuzhiyun 	if (skb && skb->protocol == htons(ETH_P_IP))
5181*4882a593Smuzhiyun 		family = PF_INET;
5182*4882a593Smuzhiyun 	else if (skb && skb->protocol == htons(ETH_P_IPV6))
5183*4882a593Smuzhiyun 		family = PF_INET6;
5184*4882a593Smuzhiyun 	else if (sock)
5185*4882a593Smuzhiyun 		family = sock->sk->sk_family;
5186*4882a593Smuzhiyun 	else
5187*4882a593Smuzhiyun 		goto out;
5188*4882a593Smuzhiyun 
5189*4882a593Smuzhiyun 	if (sock && family == PF_UNIX) {
5190*4882a593Smuzhiyun 		isec = inode_security_novalidate(SOCK_INODE(sock));
5191*4882a593Smuzhiyun 		peer_secid = isec->sid;
5192*4882a593Smuzhiyun 	} else if (skb)
5193*4882a593Smuzhiyun 		selinux_skb_peerlbl_sid(skb, family, &peer_secid);
5194*4882a593Smuzhiyun 
5195*4882a593Smuzhiyun out:
5196*4882a593Smuzhiyun 	*secid = peer_secid;
5197*4882a593Smuzhiyun 	if (peer_secid == SECSID_NULL)
5198*4882a593Smuzhiyun 		return -EINVAL;
5199*4882a593Smuzhiyun 	return 0;
5200*4882a593Smuzhiyun }
5201*4882a593Smuzhiyun 
selinux_sk_alloc_security(struct sock * sk,int family,gfp_t priority)5202*4882a593Smuzhiyun static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
5203*4882a593Smuzhiyun {
5204*4882a593Smuzhiyun 	struct sk_security_struct *sksec;
5205*4882a593Smuzhiyun 
5206*4882a593Smuzhiyun 	sksec = kzalloc(sizeof(*sksec), priority);
5207*4882a593Smuzhiyun 	if (!sksec)
5208*4882a593Smuzhiyun 		return -ENOMEM;
5209*4882a593Smuzhiyun 
5210*4882a593Smuzhiyun 	sksec->peer_sid = SECINITSID_UNLABELED;
5211*4882a593Smuzhiyun 	sksec->sid = SECINITSID_UNLABELED;
5212*4882a593Smuzhiyun 	sksec->sclass = SECCLASS_SOCKET;
5213*4882a593Smuzhiyun 	selinux_netlbl_sk_security_reset(sksec);
5214*4882a593Smuzhiyun 	sk->sk_security = sksec;
5215*4882a593Smuzhiyun 
5216*4882a593Smuzhiyun 	return 0;
5217*4882a593Smuzhiyun }
5218*4882a593Smuzhiyun 
selinux_sk_free_security(struct sock * sk)5219*4882a593Smuzhiyun static void selinux_sk_free_security(struct sock *sk)
5220*4882a593Smuzhiyun {
5221*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5222*4882a593Smuzhiyun 
5223*4882a593Smuzhiyun 	sk->sk_security = NULL;
5224*4882a593Smuzhiyun 	selinux_netlbl_sk_security_free(sksec);
5225*4882a593Smuzhiyun 	kfree(sksec);
5226*4882a593Smuzhiyun }
5227*4882a593Smuzhiyun 
selinux_sk_clone_security(const struct sock * sk,struct sock * newsk)5228*4882a593Smuzhiyun static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
5229*4882a593Smuzhiyun {
5230*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5231*4882a593Smuzhiyun 	struct sk_security_struct *newsksec = newsk->sk_security;
5232*4882a593Smuzhiyun 
5233*4882a593Smuzhiyun 	newsksec->sid = sksec->sid;
5234*4882a593Smuzhiyun 	newsksec->peer_sid = sksec->peer_sid;
5235*4882a593Smuzhiyun 	newsksec->sclass = sksec->sclass;
5236*4882a593Smuzhiyun 
5237*4882a593Smuzhiyun 	selinux_netlbl_sk_security_reset(newsksec);
5238*4882a593Smuzhiyun }
5239*4882a593Smuzhiyun 
selinux_sk_getsecid(struct sock * sk,u32 * secid)5240*4882a593Smuzhiyun static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
5241*4882a593Smuzhiyun {
5242*4882a593Smuzhiyun 	if (!sk)
5243*4882a593Smuzhiyun 		*secid = SECINITSID_ANY_SOCKET;
5244*4882a593Smuzhiyun 	else {
5245*4882a593Smuzhiyun 		struct sk_security_struct *sksec = sk->sk_security;
5246*4882a593Smuzhiyun 
5247*4882a593Smuzhiyun 		*secid = sksec->sid;
5248*4882a593Smuzhiyun 	}
5249*4882a593Smuzhiyun }
5250*4882a593Smuzhiyun 
selinux_sock_graft(struct sock * sk,struct socket * parent)5251*4882a593Smuzhiyun static void selinux_sock_graft(struct sock *sk, struct socket *parent)
5252*4882a593Smuzhiyun {
5253*4882a593Smuzhiyun 	struct inode_security_struct *isec =
5254*4882a593Smuzhiyun 		inode_security_novalidate(SOCK_INODE(parent));
5255*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5256*4882a593Smuzhiyun 
5257*4882a593Smuzhiyun 	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5258*4882a593Smuzhiyun 	    sk->sk_family == PF_UNIX)
5259*4882a593Smuzhiyun 		isec->sid = sksec->sid;
5260*4882a593Smuzhiyun 	sksec->sclass = isec->sclass;
5261*4882a593Smuzhiyun }
5262*4882a593Smuzhiyun 
5263*4882a593Smuzhiyun /* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5264*4882a593Smuzhiyun  * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5265*4882a593Smuzhiyun  * already present).
5266*4882a593Smuzhiyun  */
selinux_sctp_assoc_request(struct sctp_endpoint * ep,struct sk_buff * skb)5267*4882a593Smuzhiyun static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5268*4882a593Smuzhiyun 				      struct sk_buff *skb)
5269*4882a593Smuzhiyun {
5270*4882a593Smuzhiyun 	struct sk_security_struct *sksec = ep->base.sk->sk_security;
5271*4882a593Smuzhiyun 	struct common_audit_data ad;
5272*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5273*4882a593Smuzhiyun 	u8 peerlbl_active;
5274*4882a593Smuzhiyun 	u32 peer_sid = SECINITSID_UNLABELED;
5275*4882a593Smuzhiyun 	u32 conn_sid;
5276*4882a593Smuzhiyun 	int err = 0;
5277*4882a593Smuzhiyun 
5278*4882a593Smuzhiyun 	if (!selinux_policycap_extsockclass())
5279*4882a593Smuzhiyun 		return 0;
5280*4882a593Smuzhiyun 
5281*4882a593Smuzhiyun 	peerlbl_active = selinux_peerlbl_enabled();
5282*4882a593Smuzhiyun 
5283*4882a593Smuzhiyun 	if (peerlbl_active) {
5284*4882a593Smuzhiyun 		/* This will return peer_sid = SECSID_NULL if there are
5285*4882a593Smuzhiyun 		 * no peer labels, see security_net_peersid_resolve().
5286*4882a593Smuzhiyun 		 */
5287*4882a593Smuzhiyun 		err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5288*4882a593Smuzhiyun 					      &peer_sid);
5289*4882a593Smuzhiyun 		if (err)
5290*4882a593Smuzhiyun 			return err;
5291*4882a593Smuzhiyun 
5292*4882a593Smuzhiyun 		if (peer_sid == SECSID_NULL)
5293*4882a593Smuzhiyun 			peer_sid = SECINITSID_UNLABELED;
5294*4882a593Smuzhiyun 	}
5295*4882a593Smuzhiyun 
5296*4882a593Smuzhiyun 	if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5297*4882a593Smuzhiyun 		sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5298*4882a593Smuzhiyun 
5299*4882a593Smuzhiyun 		/* Here as first association on socket. As the peer SID
5300*4882a593Smuzhiyun 		 * was allowed by peer recv (and the netif/node checks),
5301*4882a593Smuzhiyun 		 * then it is approved by policy and used as the primary
5302*4882a593Smuzhiyun 		 * peer SID for getpeercon(3).
5303*4882a593Smuzhiyun 		 */
5304*4882a593Smuzhiyun 		sksec->peer_sid = peer_sid;
5305*4882a593Smuzhiyun 	} else if  (sksec->peer_sid != peer_sid) {
5306*4882a593Smuzhiyun 		/* Other association peer SIDs are checked to enforce
5307*4882a593Smuzhiyun 		 * consistency among the peer SIDs.
5308*4882a593Smuzhiyun 		 */
5309*4882a593Smuzhiyun 		ad.type = LSM_AUDIT_DATA_NET;
5310*4882a593Smuzhiyun 		ad.u.net = &net;
5311*4882a593Smuzhiyun 		ad.u.net->sk = ep->base.sk;
5312*4882a593Smuzhiyun 		err = avc_has_perm(&selinux_state,
5313*4882a593Smuzhiyun 				   sksec->peer_sid, peer_sid, sksec->sclass,
5314*4882a593Smuzhiyun 				   SCTP_SOCKET__ASSOCIATION, &ad);
5315*4882a593Smuzhiyun 		if (err)
5316*4882a593Smuzhiyun 			return err;
5317*4882a593Smuzhiyun 	}
5318*4882a593Smuzhiyun 
5319*4882a593Smuzhiyun 	/* Compute the MLS component for the connection and store
5320*4882a593Smuzhiyun 	 * the information in ep. This will be used by SCTP TCP type
5321*4882a593Smuzhiyun 	 * sockets and peeled off connections as they cause a new
5322*4882a593Smuzhiyun 	 * socket to be generated. selinux_sctp_sk_clone() will then
5323*4882a593Smuzhiyun 	 * plug this into the new socket.
5324*4882a593Smuzhiyun 	 */
5325*4882a593Smuzhiyun 	err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5326*4882a593Smuzhiyun 	if (err)
5327*4882a593Smuzhiyun 		return err;
5328*4882a593Smuzhiyun 
5329*4882a593Smuzhiyun 	ep->secid = conn_sid;
5330*4882a593Smuzhiyun 	ep->peer_secid = peer_sid;
5331*4882a593Smuzhiyun 
5332*4882a593Smuzhiyun 	/* Set any NetLabel labels including CIPSO/CALIPSO options. */
5333*4882a593Smuzhiyun 	return selinux_netlbl_sctp_assoc_request(ep, skb);
5334*4882a593Smuzhiyun }
5335*4882a593Smuzhiyun 
5336*4882a593Smuzhiyun /* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5337*4882a593Smuzhiyun  * based on their @optname.
5338*4882a593Smuzhiyun  */
selinux_sctp_bind_connect(struct sock * sk,int optname,struct sockaddr * address,int addrlen)5339*4882a593Smuzhiyun static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5340*4882a593Smuzhiyun 				     struct sockaddr *address,
5341*4882a593Smuzhiyun 				     int addrlen)
5342*4882a593Smuzhiyun {
5343*4882a593Smuzhiyun 	int len, err = 0, walk_size = 0;
5344*4882a593Smuzhiyun 	void *addr_buf;
5345*4882a593Smuzhiyun 	struct sockaddr *addr;
5346*4882a593Smuzhiyun 	struct socket *sock;
5347*4882a593Smuzhiyun 
5348*4882a593Smuzhiyun 	if (!selinux_policycap_extsockclass())
5349*4882a593Smuzhiyun 		return 0;
5350*4882a593Smuzhiyun 
5351*4882a593Smuzhiyun 	/* Process one or more addresses that may be IPv4 or IPv6 */
5352*4882a593Smuzhiyun 	sock = sk->sk_socket;
5353*4882a593Smuzhiyun 	addr_buf = address;
5354*4882a593Smuzhiyun 
5355*4882a593Smuzhiyun 	while (walk_size < addrlen) {
5356*4882a593Smuzhiyun 		if (walk_size + sizeof(sa_family_t) > addrlen)
5357*4882a593Smuzhiyun 			return -EINVAL;
5358*4882a593Smuzhiyun 
5359*4882a593Smuzhiyun 		addr = addr_buf;
5360*4882a593Smuzhiyun 		switch (addr->sa_family) {
5361*4882a593Smuzhiyun 		case AF_UNSPEC:
5362*4882a593Smuzhiyun 		case AF_INET:
5363*4882a593Smuzhiyun 			len = sizeof(struct sockaddr_in);
5364*4882a593Smuzhiyun 			break;
5365*4882a593Smuzhiyun 		case AF_INET6:
5366*4882a593Smuzhiyun 			len = sizeof(struct sockaddr_in6);
5367*4882a593Smuzhiyun 			break;
5368*4882a593Smuzhiyun 		default:
5369*4882a593Smuzhiyun 			return -EINVAL;
5370*4882a593Smuzhiyun 		}
5371*4882a593Smuzhiyun 
5372*4882a593Smuzhiyun 		if (walk_size + len > addrlen)
5373*4882a593Smuzhiyun 			return -EINVAL;
5374*4882a593Smuzhiyun 
5375*4882a593Smuzhiyun 		err = -EINVAL;
5376*4882a593Smuzhiyun 		switch (optname) {
5377*4882a593Smuzhiyun 		/* Bind checks */
5378*4882a593Smuzhiyun 		case SCTP_PRIMARY_ADDR:
5379*4882a593Smuzhiyun 		case SCTP_SET_PEER_PRIMARY_ADDR:
5380*4882a593Smuzhiyun 		case SCTP_SOCKOPT_BINDX_ADD:
5381*4882a593Smuzhiyun 			err = selinux_socket_bind(sock, addr, len);
5382*4882a593Smuzhiyun 			break;
5383*4882a593Smuzhiyun 		/* Connect checks */
5384*4882a593Smuzhiyun 		case SCTP_SOCKOPT_CONNECTX:
5385*4882a593Smuzhiyun 		case SCTP_PARAM_SET_PRIMARY:
5386*4882a593Smuzhiyun 		case SCTP_PARAM_ADD_IP:
5387*4882a593Smuzhiyun 		case SCTP_SENDMSG_CONNECT:
5388*4882a593Smuzhiyun 			err = selinux_socket_connect_helper(sock, addr, len);
5389*4882a593Smuzhiyun 			if (err)
5390*4882a593Smuzhiyun 				return err;
5391*4882a593Smuzhiyun 
5392*4882a593Smuzhiyun 			/* As selinux_sctp_bind_connect() is called by the
5393*4882a593Smuzhiyun 			 * SCTP protocol layer, the socket is already locked,
5394*4882a593Smuzhiyun 			 * therefore selinux_netlbl_socket_connect_locked()
5395*4882a593Smuzhiyun 			 * is called here. The situations handled are:
5396*4882a593Smuzhiyun 			 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5397*4882a593Smuzhiyun 			 * whenever a new IP address is added or when a new
5398*4882a593Smuzhiyun 			 * primary address is selected.
5399*4882a593Smuzhiyun 			 * Note that an SCTP connect(2) call happens before
5400*4882a593Smuzhiyun 			 * the SCTP protocol layer and is handled via
5401*4882a593Smuzhiyun 			 * selinux_socket_connect().
5402*4882a593Smuzhiyun 			 */
5403*4882a593Smuzhiyun 			err = selinux_netlbl_socket_connect_locked(sk, addr);
5404*4882a593Smuzhiyun 			break;
5405*4882a593Smuzhiyun 		}
5406*4882a593Smuzhiyun 
5407*4882a593Smuzhiyun 		if (err)
5408*4882a593Smuzhiyun 			return err;
5409*4882a593Smuzhiyun 
5410*4882a593Smuzhiyun 		addr_buf += len;
5411*4882a593Smuzhiyun 		walk_size += len;
5412*4882a593Smuzhiyun 	}
5413*4882a593Smuzhiyun 
5414*4882a593Smuzhiyun 	return 0;
5415*4882a593Smuzhiyun }
5416*4882a593Smuzhiyun 
5417*4882a593Smuzhiyun /* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
selinux_sctp_sk_clone(struct sctp_endpoint * ep,struct sock * sk,struct sock * newsk)5418*4882a593Smuzhiyun static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5419*4882a593Smuzhiyun 				  struct sock *newsk)
5420*4882a593Smuzhiyun {
5421*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5422*4882a593Smuzhiyun 	struct sk_security_struct *newsksec = newsk->sk_security;
5423*4882a593Smuzhiyun 
5424*4882a593Smuzhiyun 	/* If policy does not support SECCLASS_SCTP_SOCKET then call
5425*4882a593Smuzhiyun 	 * the non-sctp clone version.
5426*4882a593Smuzhiyun 	 */
5427*4882a593Smuzhiyun 	if (!selinux_policycap_extsockclass())
5428*4882a593Smuzhiyun 		return selinux_sk_clone_security(sk, newsk);
5429*4882a593Smuzhiyun 
5430*4882a593Smuzhiyun 	newsksec->sid = ep->secid;
5431*4882a593Smuzhiyun 	newsksec->peer_sid = ep->peer_secid;
5432*4882a593Smuzhiyun 	newsksec->sclass = sksec->sclass;
5433*4882a593Smuzhiyun 	selinux_netlbl_sctp_sk_clone(sk, newsk);
5434*4882a593Smuzhiyun }
5435*4882a593Smuzhiyun 
selinux_inet_conn_request(struct sock * sk,struct sk_buff * skb,struct request_sock * req)5436*4882a593Smuzhiyun static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
5437*4882a593Smuzhiyun 				     struct request_sock *req)
5438*4882a593Smuzhiyun {
5439*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5440*4882a593Smuzhiyun 	int err;
5441*4882a593Smuzhiyun 	u16 family = req->rsk_ops->family;
5442*4882a593Smuzhiyun 	u32 connsid;
5443*4882a593Smuzhiyun 	u32 peersid;
5444*4882a593Smuzhiyun 
5445*4882a593Smuzhiyun 	err = selinux_skb_peerlbl_sid(skb, family, &peersid);
5446*4882a593Smuzhiyun 	if (err)
5447*4882a593Smuzhiyun 		return err;
5448*4882a593Smuzhiyun 	err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5449*4882a593Smuzhiyun 	if (err)
5450*4882a593Smuzhiyun 		return err;
5451*4882a593Smuzhiyun 	req->secid = connsid;
5452*4882a593Smuzhiyun 	req->peer_secid = peersid;
5453*4882a593Smuzhiyun 
5454*4882a593Smuzhiyun 	return selinux_netlbl_inet_conn_request(req, family);
5455*4882a593Smuzhiyun }
5456*4882a593Smuzhiyun 
selinux_inet_csk_clone(struct sock * newsk,const struct request_sock * req)5457*4882a593Smuzhiyun static void selinux_inet_csk_clone(struct sock *newsk,
5458*4882a593Smuzhiyun 				   const struct request_sock *req)
5459*4882a593Smuzhiyun {
5460*4882a593Smuzhiyun 	struct sk_security_struct *newsksec = newsk->sk_security;
5461*4882a593Smuzhiyun 
5462*4882a593Smuzhiyun 	newsksec->sid = req->secid;
5463*4882a593Smuzhiyun 	newsksec->peer_sid = req->peer_secid;
5464*4882a593Smuzhiyun 	/* NOTE: Ideally, we should also get the isec->sid for the
5465*4882a593Smuzhiyun 	   new socket in sync, but we don't have the isec available yet.
5466*4882a593Smuzhiyun 	   So we will wait until sock_graft to do it, by which
5467*4882a593Smuzhiyun 	   time it will have been created and available. */
5468*4882a593Smuzhiyun 
5469*4882a593Smuzhiyun 	/* We don't need to take any sort of lock here as we are the only
5470*4882a593Smuzhiyun 	 * thread with access to newsksec */
5471*4882a593Smuzhiyun 	selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
5472*4882a593Smuzhiyun }
5473*4882a593Smuzhiyun 
selinux_inet_conn_established(struct sock * sk,struct sk_buff * skb)5474*4882a593Smuzhiyun static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
5475*4882a593Smuzhiyun {
5476*4882a593Smuzhiyun 	u16 family = sk->sk_family;
5477*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5478*4882a593Smuzhiyun 
5479*4882a593Smuzhiyun 	/* handle mapped IPv4 packets arriving via IPv6 sockets */
5480*4882a593Smuzhiyun 	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5481*4882a593Smuzhiyun 		family = PF_INET;
5482*4882a593Smuzhiyun 
5483*4882a593Smuzhiyun 	selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
5484*4882a593Smuzhiyun }
5485*4882a593Smuzhiyun 
selinux_secmark_relabel_packet(u32 sid)5486*4882a593Smuzhiyun static int selinux_secmark_relabel_packet(u32 sid)
5487*4882a593Smuzhiyun {
5488*4882a593Smuzhiyun 	const struct task_security_struct *__tsec;
5489*4882a593Smuzhiyun 	u32 tsid;
5490*4882a593Smuzhiyun 
5491*4882a593Smuzhiyun 	__tsec = selinux_cred(current_cred());
5492*4882a593Smuzhiyun 	tsid = __tsec->sid;
5493*4882a593Smuzhiyun 
5494*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
5495*4882a593Smuzhiyun 			    tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
5496*4882a593Smuzhiyun 			    NULL);
5497*4882a593Smuzhiyun }
5498*4882a593Smuzhiyun 
selinux_secmark_refcount_inc(void)5499*4882a593Smuzhiyun static void selinux_secmark_refcount_inc(void)
5500*4882a593Smuzhiyun {
5501*4882a593Smuzhiyun 	atomic_inc(&selinux_secmark_refcount);
5502*4882a593Smuzhiyun }
5503*4882a593Smuzhiyun 
selinux_secmark_refcount_dec(void)5504*4882a593Smuzhiyun static void selinux_secmark_refcount_dec(void)
5505*4882a593Smuzhiyun {
5506*4882a593Smuzhiyun 	atomic_dec(&selinux_secmark_refcount);
5507*4882a593Smuzhiyun }
5508*4882a593Smuzhiyun 
selinux_req_classify_flow(const struct request_sock * req,struct flowi_common * flic)5509*4882a593Smuzhiyun static void selinux_req_classify_flow(const struct request_sock *req,
5510*4882a593Smuzhiyun 				      struct flowi_common *flic)
5511*4882a593Smuzhiyun {
5512*4882a593Smuzhiyun 	flic->flowic_secid = req->secid;
5513*4882a593Smuzhiyun }
5514*4882a593Smuzhiyun 
selinux_tun_dev_alloc_security(void ** security)5515*4882a593Smuzhiyun static int selinux_tun_dev_alloc_security(void **security)
5516*4882a593Smuzhiyun {
5517*4882a593Smuzhiyun 	struct tun_security_struct *tunsec;
5518*4882a593Smuzhiyun 
5519*4882a593Smuzhiyun 	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5520*4882a593Smuzhiyun 	if (!tunsec)
5521*4882a593Smuzhiyun 		return -ENOMEM;
5522*4882a593Smuzhiyun 	tunsec->sid = current_sid();
5523*4882a593Smuzhiyun 
5524*4882a593Smuzhiyun 	*security = tunsec;
5525*4882a593Smuzhiyun 	return 0;
5526*4882a593Smuzhiyun }
5527*4882a593Smuzhiyun 
selinux_tun_dev_free_security(void * security)5528*4882a593Smuzhiyun static void selinux_tun_dev_free_security(void *security)
5529*4882a593Smuzhiyun {
5530*4882a593Smuzhiyun 	kfree(security);
5531*4882a593Smuzhiyun }
5532*4882a593Smuzhiyun 
selinux_tun_dev_create(void)5533*4882a593Smuzhiyun static int selinux_tun_dev_create(void)
5534*4882a593Smuzhiyun {
5535*4882a593Smuzhiyun 	u32 sid = current_sid();
5536*4882a593Smuzhiyun 
5537*4882a593Smuzhiyun 	/* we aren't taking into account the "sockcreate" SID since the socket
5538*4882a593Smuzhiyun 	 * that is being created here is not a socket in the traditional sense,
5539*4882a593Smuzhiyun 	 * instead it is a private sock, accessible only to the kernel, and
5540*4882a593Smuzhiyun 	 * representing a wide range of network traffic spanning multiple
5541*4882a593Smuzhiyun 	 * connections unlike traditional sockets - check the TUN driver to
5542*4882a593Smuzhiyun 	 * get a better understanding of why this socket is special */
5543*4882a593Smuzhiyun 
5544*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
5545*4882a593Smuzhiyun 			    sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
5546*4882a593Smuzhiyun 			    NULL);
5547*4882a593Smuzhiyun }
5548*4882a593Smuzhiyun 
selinux_tun_dev_attach_queue(void * security)5549*4882a593Smuzhiyun static int selinux_tun_dev_attach_queue(void *security)
5550*4882a593Smuzhiyun {
5551*4882a593Smuzhiyun 	struct tun_security_struct *tunsec = security;
5552*4882a593Smuzhiyun 
5553*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
5554*4882a593Smuzhiyun 			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
5555*4882a593Smuzhiyun 			    TUN_SOCKET__ATTACH_QUEUE, NULL);
5556*4882a593Smuzhiyun }
5557*4882a593Smuzhiyun 
selinux_tun_dev_attach(struct sock * sk,void * security)5558*4882a593Smuzhiyun static int selinux_tun_dev_attach(struct sock *sk, void *security)
5559*4882a593Smuzhiyun {
5560*4882a593Smuzhiyun 	struct tun_security_struct *tunsec = security;
5561*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5562*4882a593Smuzhiyun 
5563*4882a593Smuzhiyun 	/* we don't currently perform any NetLabel based labeling here and it
5564*4882a593Smuzhiyun 	 * isn't clear that we would want to do so anyway; while we could apply
5565*4882a593Smuzhiyun 	 * labeling without the support of the TUN user the resulting labeled
5566*4882a593Smuzhiyun 	 * traffic from the other end of the connection would almost certainly
5567*4882a593Smuzhiyun 	 * cause confusion to the TUN user that had no idea network labeling
5568*4882a593Smuzhiyun 	 * protocols were being used */
5569*4882a593Smuzhiyun 
5570*4882a593Smuzhiyun 	sksec->sid = tunsec->sid;
5571*4882a593Smuzhiyun 	sksec->sclass = SECCLASS_TUN_SOCKET;
5572*4882a593Smuzhiyun 
5573*4882a593Smuzhiyun 	return 0;
5574*4882a593Smuzhiyun }
5575*4882a593Smuzhiyun 
selinux_tun_dev_open(void * security)5576*4882a593Smuzhiyun static int selinux_tun_dev_open(void *security)
5577*4882a593Smuzhiyun {
5578*4882a593Smuzhiyun 	struct tun_security_struct *tunsec = security;
5579*4882a593Smuzhiyun 	u32 sid = current_sid();
5580*4882a593Smuzhiyun 	int err;
5581*4882a593Smuzhiyun 
5582*4882a593Smuzhiyun 	err = avc_has_perm(&selinux_state,
5583*4882a593Smuzhiyun 			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,
5584*4882a593Smuzhiyun 			   TUN_SOCKET__RELABELFROM, NULL);
5585*4882a593Smuzhiyun 	if (err)
5586*4882a593Smuzhiyun 		return err;
5587*4882a593Smuzhiyun 	err = avc_has_perm(&selinux_state,
5588*4882a593Smuzhiyun 			   sid, sid, SECCLASS_TUN_SOCKET,
5589*4882a593Smuzhiyun 			   TUN_SOCKET__RELABELTO, NULL);
5590*4882a593Smuzhiyun 	if (err)
5591*4882a593Smuzhiyun 		return err;
5592*4882a593Smuzhiyun 	tunsec->sid = sid;
5593*4882a593Smuzhiyun 
5594*4882a593Smuzhiyun 	return 0;
5595*4882a593Smuzhiyun }
5596*4882a593Smuzhiyun 
5597*4882a593Smuzhiyun #ifdef CONFIG_NETFILTER
5598*4882a593Smuzhiyun 
selinux_ip_forward(struct sk_buff * skb,const struct net_device * indev,u16 family)5599*4882a593Smuzhiyun static unsigned int selinux_ip_forward(struct sk_buff *skb,
5600*4882a593Smuzhiyun 				       const struct net_device *indev,
5601*4882a593Smuzhiyun 				       u16 family)
5602*4882a593Smuzhiyun {
5603*4882a593Smuzhiyun 	int err;
5604*4882a593Smuzhiyun 	char *addrp;
5605*4882a593Smuzhiyun 	u32 peer_sid;
5606*4882a593Smuzhiyun 	struct common_audit_data ad;
5607*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5608*4882a593Smuzhiyun 	u8 secmark_active;
5609*4882a593Smuzhiyun 	u8 netlbl_active;
5610*4882a593Smuzhiyun 	u8 peerlbl_active;
5611*4882a593Smuzhiyun 
5612*4882a593Smuzhiyun 	if (!selinux_policycap_netpeer())
5613*4882a593Smuzhiyun 		return NF_ACCEPT;
5614*4882a593Smuzhiyun 
5615*4882a593Smuzhiyun 	secmark_active = selinux_secmark_enabled();
5616*4882a593Smuzhiyun 	netlbl_active = netlbl_enabled();
5617*4882a593Smuzhiyun 	peerlbl_active = selinux_peerlbl_enabled();
5618*4882a593Smuzhiyun 	if (!secmark_active && !peerlbl_active)
5619*4882a593Smuzhiyun 		return NF_ACCEPT;
5620*4882a593Smuzhiyun 
5621*4882a593Smuzhiyun 	if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5622*4882a593Smuzhiyun 		return NF_DROP;
5623*4882a593Smuzhiyun 
5624*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5625*4882a593Smuzhiyun 	ad.u.net = &net;
5626*4882a593Smuzhiyun 	ad.u.net->netif = indev->ifindex;
5627*4882a593Smuzhiyun 	ad.u.net->family = family;
5628*4882a593Smuzhiyun 	if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5629*4882a593Smuzhiyun 		return NF_DROP;
5630*4882a593Smuzhiyun 
5631*4882a593Smuzhiyun 	if (peerlbl_active) {
5632*4882a593Smuzhiyun 		err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5633*4882a593Smuzhiyun 					       addrp, family, peer_sid, &ad);
5634*4882a593Smuzhiyun 		if (err) {
5635*4882a593Smuzhiyun 			selinux_netlbl_err(skb, family, err, 1);
5636*4882a593Smuzhiyun 			return NF_DROP;
5637*4882a593Smuzhiyun 		}
5638*4882a593Smuzhiyun 	}
5639*4882a593Smuzhiyun 
5640*4882a593Smuzhiyun 	if (secmark_active)
5641*4882a593Smuzhiyun 		if (avc_has_perm(&selinux_state,
5642*4882a593Smuzhiyun 				 peer_sid, skb->secmark,
5643*4882a593Smuzhiyun 				 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5644*4882a593Smuzhiyun 			return NF_DROP;
5645*4882a593Smuzhiyun 
5646*4882a593Smuzhiyun 	if (netlbl_active)
5647*4882a593Smuzhiyun 		/* we do this in the FORWARD path and not the POST_ROUTING
5648*4882a593Smuzhiyun 		 * path because we want to make sure we apply the necessary
5649*4882a593Smuzhiyun 		 * labeling before IPsec is applied so we can leverage AH
5650*4882a593Smuzhiyun 		 * protection */
5651*4882a593Smuzhiyun 		if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5652*4882a593Smuzhiyun 			return NF_DROP;
5653*4882a593Smuzhiyun 
5654*4882a593Smuzhiyun 	return NF_ACCEPT;
5655*4882a593Smuzhiyun }
5656*4882a593Smuzhiyun 
selinux_ipv4_forward(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5657*4882a593Smuzhiyun static unsigned int selinux_ipv4_forward(void *priv,
5658*4882a593Smuzhiyun 					 struct sk_buff *skb,
5659*4882a593Smuzhiyun 					 const struct nf_hook_state *state)
5660*4882a593Smuzhiyun {
5661*4882a593Smuzhiyun 	return selinux_ip_forward(skb, state->in, PF_INET);
5662*4882a593Smuzhiyun }
5663*4882a593Smuzhiyun 
5664*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
selinux_ipv6_forward(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5665*4882a593Smuzhiyun static unsigned int selinux_ipv6_forward(void *priv,
5666*4882a593Smuzhiyun 					 struct sk_buff *skb,
5667*4882a593Smuzhiyun 					 const struct nf_hook_state *state)
5668*4882a593Smuzhiyun {
5669*4882a593Smuzhiyun 	return selinux_ip_forward(skb, state->in, PF_INET6);
5670*4882a593Smuzhiyun }
5671*4882a593Smuzhiyun #endif	/* IPV6 */
5672*4882a593Smuzhiyun 
selinux_ip_output(struct sk_buff * skb,u16 family)5673*4882a593Smuzhiyun static unsigned int selinux_ip_output(struct sk_buff *skb,
5674*4882a593Smuzhiyun 				      u16 family)
5675*4882a593Smuzhiyun {
5676*4882a593Smuzhiyun 	struct sock *sk;
5677*4882a593Smuzhiyun 	u32 sid;
5678*4882a593Smuzhiyun 
5679*4882a593Smuzhiyun 	if (!netlbl_enabled())
5680*4882a593Smuzhiyun 		return NF_ACCEPT;
5681*4882a593Smuzhiyun 
5682*4882a593Smuzhiyun 	/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5683*4882a593Smuzhiyun 	 * because we want to make sure we apply the necessary labeling
5684*4882a593Smuzhiyun 	 * before IPsec is applied so we can leverage AH protection */
5685*4882a593Smuzhiyun 	sk = skb->sk;
5686*4882a593Smuzhiyun 	if (sk) {
5687*4882a593Smuzhiyun 		struct sk_security_struct *sksec;
5688*4882a593Smuzhiyun 
5689*4882a593Smuzhiyun 		if (sk_listener(sk))
5690*4882a593Smuzhiyun 			/* if the socket is the listening state then this
5691*4882a593Smuzhiyun 			 * packet is a SYN-ACK packet which means it needs to
5692*4882a593Smuzhiyun 			 * be labeled based on the connection/request_sock and
5693*4882a593Smuzhiyun 			 * not the parent socket.  unfortunately, we can't
5694*4882a593Smuzhiyun 			 * lookup the request_sock yet as it isn't queued on
5695*4882a593Smuzhiyun 			 * the parent socket until after the SYN-ACK is sent.
5696*4882a593Smuzhiyun 			 * the "solution" is to simply pass the packet as-is
5697*4882a593Smuzhiyun 			 * as any IP option based labeling should be copied
5698*4882a593Smuzhiyun 			 * from the initial connection request (in the IP
5699*4882a593Smuzhiyun 			 * layer).  it is far from ideal, but until we get a
5700*4882a593Smuzhiyun 			 * security label in the packet itself this is the
5701*4882a593Smuzhiyun 			 * best we can do. */
5702*4882a593Smuzhiyun 			return NF_ACCEPT;
5703*4882a593Smuzhiyun 
5704*4882a593Smuzhiyun 		/* standard practice, label using the parent socket */
5705*4882a593Smuzhiyun 		sksec = sk->sk_security;
5706*4882a593Smuzhiyun 		sid = sksec->sid;
5707*4882a593Smuzhiyun 	} else
5708*4882a593Smuzhiyun 		sid = SECINITSID_KERNEL;
5709*4882a593Smuzhiyun 	if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5710*4882a593Smuzhiyun 		return NF_DROP;
5711*4882a593Smuzhiyun 
5712*4882a593Smuzhiyun 	return NF_ACCEPT;
5713*4882a593Smuzhiyun }
5714*4882a593Smuzhiyun 
selinux_ipv4_output(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5715*4882a593Smuzhiyun static unsigned int selinux_ipv4_output(void *priv,
5716*4882a593Smuzhiyun 					struct sk_buff *skb,
5717*4882a593Smuzhiyun 					const struct nf_hook_state *state)
5718*4882a593Smuzhiyun {
5719*4882a593Smuzhiyun 	return selinux_ip_output(skb, PF_INET);
5720*4882a593Smuzhiyun }
5721*4882a593Smuzhiyun 
5722*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
selinux_ipv6_output(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5723*4882a593Smuzhiyun static unsigned int selinux_ipv6_output(void *priv,
5724*4882a593Smuzhiyun 					struct sk_buff *skb,
5725*4882a593Smuzhiyun 					const struct nf_hook_state *state)
5726*4882a593Smuzhiyun {
5727*4882a593Smuzhiyun 	return selinux_ip_output(skb, PF_INET6);
5728*4882a593Smuzhiyun }
5729*4882a593Smuzhiyun #endif	/* IPV6 */
5730*4882a593Smuzhiyun 
selinux_ip_postroute_compat(struct sk_buff * skb,int ifindex,u16 family)5731*4882a593Smuzhiyun static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5732*4882a593Smuzhiyun 						int ifindex,
5733*4882a593Smuzhiyun 						u16 family)
5734*4882a593Smuzhiyun {
5735*4882a593Smuzhiyun 	struct sock *sk = skb_to_full_sk(skb);
5736*4882a593Smuzhiyun 	struct sk_security_struct *sksec;
5737*4882a593Smuzhiyun 	struct common_audit_data ad;
5738*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5739*4882a593Smuzhiyun 	char *addrp;
5740*4882a593Smuzhiyun 	u8 proto = 0;
5741*4882a593Smuzhiyun 
5742*4882a593Smuzhiyun 	if (sk == NULL)
5743*4882a593Smuzhiyun 		return NF_ACCEPT;
5744*4882a593Smuzhiyun 	sksec = sk->sk_security;
5745*4882a593Smuzhiyun 
5746*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5747*4882a593Smuzhiyun 	ad.u.net = &net;
5748*4882a593Smuzhiyun 	ad.u.net->netif = ifindex;
5749*4882a593Smuzhiyun 	ad.u.net->family = family;
5750*4882a593Smuzhiyun 	if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5751*4882a593Smuzhiyun 		return NF_DROP;
5752*4882a593Smuzhiyun 
5753*4882a593Smuzhiyun 	if (selinux_secmark_enabled())
5754*4882a593Smuzhiyun 		if (avc_has_perm(&selinux_state,
5755*4882a593Smuzhiyun 				 sksec->sid, skb->secmark,
5756*4882a593Smuzhiyun 				 SECCLASS_PACKET, PACKET__SEND, &ad))
5757*4882a593Smuzhiyun 			return NF_DROP_ERR(-ECONNREFUSED);
5758*4882a593Smuzhiyun 
5759*4882a593Smuzhiyun 	if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5760*4882a593Smuzhiyun 		return NF_DROP_ERR(-ECONNREFUSED);
5761*4882a593Smuzhiyun 
5762*4882a593Smuzhiyun 	return NF_ACCEPT;
5763*4882a593Smuzhiyun }
5764*4882a593Smuzhiyun 
selinux_ip_postroute(struct sk_buff * skb,const struct net_device * outdev,u16 family)5765*4882a593Smuzhiyun static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5766*4882a593Smuzhiyun 					 const struct net_device *outdev,
5767*4882a593Smuzhiyun 					 u16 family)
5768*4882a593Smuzhiyun {
5769*4882a593Smuzhiyun 	u32 secmark_perm;
5770*4882a593Smuzhiyun 	u32 peer_sid;
5771*4882a593Smuzhiyun 	int ifindex = outdev->ifindex;
5772*4882a593Smuzhiyun 	struct sock *sk;
5773*4882a593Smuzhiyun 	struct common_audit_data ad;
5774*4882a593Smuzhiyun 	struct lsm_network_audit net = {0,};
5775*4882a593Smuzhiyun 	char *addrp;
5776*4882a593Smuzhiyun 	u8 secmark_active;
5777*4882a593Smuzhiyun 	u8 peerlbl_active;
5778*4882a593Smuzhiyun 
5779*4882a593Smuzhiyun 	/* If any sort of compatibility mode is enabled then handoff processing
5780*4882a593Smuzhiyun 	 * to the selinux_ip_postroute_compat() function to deal with the
5781*4882a593Smuzhiyun 	 * special handling.  We do this in an attempt to keep this function
5782*4882a593Smuzhiyun 	 * as fast and as clean as possible. */
5783*4882a593Smuzhiyun 	if (!selinux_policycap_netpeer())
5784*4882a593Smuzhiyun 		return selinux_ip_postroute_compat(skb, ifindex, family);
5785*4882a593Smuzhiyun 
5786*4882a593Smuzhiyun 	secmark_active = selinux_secmark_enabled();
5787*4882a593Smuzhiyun 	peerlbl_active = selinux_peerlbl_enabled();
5788*4882a593Smuzhiyun 	if (!secmark_active && !peerlbl_active)
5789*4882a593Smuzhiyun 		return NF_ACCEPT;
5790*4882a593Smuzhiyun 
5791*4882a593Smuzhiyun 	sk = skb_to_full_sk(skb);
5792*4882a593Smuzhiyun 
5793*4882a593Smuzhiyun #ifdef CONFIG_XFRM
5794*4882a593Smuzhiyun 	/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5795*4882a593Smuzhiyun 	 * packet transformation so allow the packet to pass without any checks
5796*4882a593Smuzhiyun 	 * since we'll have another chance to perform access control checks
5797*4882a593Smuzhiyun 	 * when the packet is on it's final way out.
5798*4882a593Smuzhiyun 	 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
5799*4882a593Smuzhiyun 	 *       is NULL, in this case go ahead and apply access control.
5800*4882a593Smuzhiyun 	 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5801*4882a593Smuzhiyun 	 *       TCP listening state we cannot wait until the XFRM processing
5802*4882a593Smuzhiyun 	 *       is done as we will miss out on the SA label if we do;
5803*4882a593Smuzhiyun 	 *       unfortunately, this means more work, but it is only once per
5804*4882a593Smuzhiyun 	 *       connection. */
5805*4882a593Smuzhiyun 	if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
5806*4882a593Smuzhiyun 	    !(sk && sk_listener(sk)))
5807*4882a593Smuzhiyun 		return NF_ACCEPT;
5808*4882a593Smuzhiyun #endif
5809*4882a593Smuzhiyun 
5810*4882a593Smuzhiyun 	if (sk == NULL) {
5811*4882a593Smuzhiyun 		/* Without an associated socket the packet is either coming
5812*4882a593Smuzhiyun 		 * from the kernel or it is being forwarded; check the packet
5813*4882a593Smuzhiyun 		 * to determine which and if the packet is being forwarded
5814*4882a593Smuzhiyun 		 * query the packet directly to determine the security label. */
5815*4882a593Smuzhiyun 		if (skb->skb_iif) {
5816*4882a593Smuzhiyun 			secmark_perm = PACKET__FORWARD_OUT;
5817*4882a593Smuzhiyun 			if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
5818*4882a593Smuzhiyun 				return NF_DROP;
5819*4882a593Smuzhiyun 		} else {
5820*4882a593Smuzhiyun 			secmark_perm = PACKET__SEND;
5821*4882a593Smuzhiyun 			peer_sid = SECINITSID_KERNEL;
5822*4882a593Smuzhiyun 		}
5823*4882a593Smuzhiyun 	} else if (sk_listener(sk)) {
5824*4882a593Smuzhiyun 		/* Locally generated packet but the associated socket is in the
5825*4882a593Smuzhiyun 		 * listening state which means this is a SYN-ACK packet.  In
5826*4882a593Smuzhiyun 		 * this particular case the correct security label is assigned
5827*4882a593Smuzhiyun 		 * to the connection/request_sock but unfortunately we can't
5828*4882a593Smuzhiyun 		 * query the request_sock as it isn't queued on the parent
5829*4882a593Smuzhiyun 		 * socket until after the SYN-ACK packet is sent; the only
5830*4882a593Smuzhiyun 		 * viable choice is to regenerate the label like we do in
5831*4882a593Smuzhiyun 		 * selinux_inet_conn_request().  See also selinux_ip_output()
5832*4882a593Smuzhiyun 		 * for similar problems. */
5833*4882a593Smuzhiyun 		u32 skb_sid;
5834*4882a593Smuzhiyun 		struct sk_security_struct *sksec;
5835*4882a593Smuzhiyun 
5836*4882a593Smuzhiyun 		sksec = sk->sk_security;
5837*4882a593Smuzhiyun 		if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5838*4882a593Smuzhiyun 			return NF_DROP;
5839*4882a593Smuzhiyun 		/* At this point, if the returned skb peerlbl is SECSID_NULL
5840*4882a593Smuzhiyun 		 * and the packet has been through at least one XFRM
5841*4882a593Smuzhiyun 		 * transformation then we must be dealing with the "final"
5842*4882a593Smuzhiyun 		 * form of labeled IPsec packet; since we've already applied
5843*4882a593Smuzhiyun 		 * all of our access controls on this packet we can safely
5844*4882a593Smuzhiyun 		 * pass the packet. */
5845*4882a593Smuzhiyun 		if (skb_sid == SECSID_NULL) {
5846*4882a593Smuzhiyun 			switch (family) {
5847*4882a593Smuzhiyun 			case PF_INET:
5848*4882a593Smuzhiyun 				if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5849*4882a593Smuzhiyun 					return NF_ACCEPT;
5850*4882a593Smuzhiyun 				break;
5851*4882a593Smuzhiyun 			case PF_INET6:
5852*4882a593Smuzhiyun 				if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5853*4882a593Smuzhiyun 					return NF_ACCEPT;
5854*4882a593Smuzhiyun 				break;
5855*4882a593Smuzhiyun 			default:
5856*4882a593Smuzhiyun 				return NF_DROP_ERR(-ECONNREFUSED);
5857*4882a593Smuzhiyun 			}
5858*4882a593Smuzhiyun 		}
5859*4882a593Smuzhiyun 		if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5860*4882a593Smuzhiyun 			return NF_DROP;
5861*4882a593Smuzhiyun 		secmark_perm = PACKET__SEND;
5862*4882a593Smuzhiyun 	} else {
5863*4882a593Smuzhiyun 		/* Locally generated packet, fetch the security label from the
5864*4882a593Smuzhiyun 		 * associated socket. */
5865*4882a593Smuzhiyun 		struct sk_security_struct *sksec = sk->sk_security;
5866*4882a593Smuzhiyun 		peer_sid = sksec->sid;
5867*4882a593Smuzhiyun 		secmark_perm = PACKET__SEND;
5868*4882a593Smuzhiyun 	}
5869*4882a593Smuzhiyun 
5870*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_NET;
5871*4882a593Smuzhiyun 	ad.u.net = &net;
5872*4882a593Smuzhiyun 	ad.u.net->netif = ifindex;
5873*4882a593Smuzhiyun 	ad.u.net->family = family;
5874*4882a593Smuzhiyun 	if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
5875*4882a593Smuzhiyun 		return NF_DROP;
5876*4882a593Smuzhiyun 
5877*4882a593Smuzhiyun 	if (secmark_active)
5878*4882a593Smuzhiyun 		if (avc_has_perm(&selinux_state,
5879*4882a593Smuzhiyun 				 peer_sid, skb->secmark,
5880*4882a593Smuzhiyun 				 SECCLASS_PACKET, secmark_perm, &ad))
5881*4882a593Smuzhiyun 			return NF_DROP_ERR(-ECONNREFUSED);
5882*4882a593Smuzhiyun 
5883*4882a593Smuzhiyun 	if (peerlbl_active) {
5884*4882a593Smuzhiyun 		u32 if_sid;
5885*4882a593Smuzhiyun 		u32 node_sid;
5886*4882a593Smuzhiyun 
5887*4882a593Smuzhiyun 		if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
5888*4882a593Smuzhiyun 			return NF_DROP;
5889*4882a593Smuzhiyun 		if (avc_has_perm(&selinux_state,
5890*4882a593Smuzhiyun 				 peer_sid, if_sid,
5891*4882a593Smuzhiyun 				 SECCLASS_NETIF, NETIF__EGRESS, &ad))
5892*4882a593Smuzhiyun 			return NF_DROP_ERR(-ECONNREFUSED);
5893*4882a593Smuzhiyun 
5894*4882a593Smuzhiyun 		if (sel_netnode_sid(addrp, family, &node_sid))
5895*4882a593Smuzhiyun 			return NF_DROP;
5896*4882a593Smuzhiyun 		if (avc_has_perm(&selinux_state,
5897*4882a593Smuzhiyun 				 peer_sid, node_sid,
5898*4882a593Smuzhiyun 				 SECCLASS_NODE, NODE__SENDTO, &ad))
5899*4882a593Smuzhiyun 			return NF_DROP_ERR(-ECONNREFUSED);
5900*4882a593Smuzhiyun 	}
5901*4882a593Smuzhiyun 
5902*4882a593Smuzhiyun 	return NF_ACCEPT;
5903*4882a593Smuzhiyun }
5904*4882a593Smuzhiyun 
selinux_ipv4_postroute(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5905*4882a593Smuzhiyun static unsigned int selinux_ipv4_postroute(void *priv,
5906*4882a593Smuzhiyun 					   struct sk_buff *skb,
5907*4882a593Smuzhiyun 					   const struct nf_hook_state *state)
5908*4882a593Smuzhiyun {
5909*4882a593Smuzhiyun 	return selinux_ip_postroute(skb, state->out, PF_INET);
5910*4882a593Smuzhiyun }
5911*4882a593Smuzhiyun 
5912*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
selinux_ipv6_postroute(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)5913*4882a593Smuzhiyun static unsigned int selinux_ipv6_postroute(void *priv,
5914*4882a593Smuzhiyun 					   struct sk_buff *skb,
5915*4882a593Smuzhiyun 					   const struct nf_hook_state *state)
5916*4882a593Smuzhiyun {
5917*4882a593Smuzhiyun 	return selinux_ip_postroute(skb, state->out, PF_INET6);
5918*4882a593Smuzhiyun }
5919*4882a593Smuzhiyun #endif	/* IPV6 */
5920*4882a593Smuzhiyun 
5921*4882a593Smuzhiyun #endif	/* CONFIG_NETFILTER */
5922*4882a593Smuzhiyun 
selinux_netlink_send(struct sock * sk,struct sk_buff * skb)5923*4882a593Smuzhiyun static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5924*4882a593Smuzhiyun {
5925*4882a593Smuzhiyun 	int rc = 0;
5926*4882a593Smuzhiyun 	unsigned int msg_len;
5927*4882a593Smuzhiyun 	unsigned int data_len = skb->len;
5928*4882a593Smuzhiyun 	unsigned char *data = skb->data;
5929*4882a593Smuzhiyun 	struct nlmsghdr *nlh;
5930*4882a593Smuzhiyun 	struct sk_security_struct *sksec = sk->sk_security;
5931*4882a593Smuzhiyun 	u16 sclass = sksec->sclass;
5932*4882a593Smuzhiyun 	u32 perm;
5933*4882a593Smuzhiyun 
5934*4882a593Smuzhiyun 	while (data_len >= nlmsg_total_size(0)) {
5935*4882a593Smuzhiyun 		nlh = (struct nlmsghdr *)data;
5936*4882a593Smuzhiyun 
5937*4882a593Smuzhiyun 		/* NOTE: the nlmsg_len field isn't reliably set by some netlink
5938*4882a593Smuzhiyun 		 *       users which means we can't reject skb's with bogus
5939*4882a593Smuzhiyun 		 *       length fields; our solution is to follow what
5940*4882a593Smuzhiyun 		 *       netlink_rcv_skb() does and simply skip processing at
5941*4882a593Smuzhiyun 		 *       messages with length fields that are clearly junk
5942*4882a593Smuzhiyun 		 */
5943*4882a593Smuzhiyun 		if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
5944*4882a593Smuzhiyun 			return 0;
5945*4882a593Smuzhiyun 
5946*4882a593Smuzhiyun 		rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
5947*4882a593Smuzhiyun 		if (rc == 0) {
5948*4882a593Smuzhiyun 			rc = sock_has_perm(sk, perm);
5949*4882a593Smuzhiyun 			if (rc)
5950*4882a593Smuzhiyun 				return rc;
5951*4882a593Smuzhiyun 		} else if (rc == -EINVAL) {
5952*4882a593Smuzhiyun 			/* -EINVAL is a missing msg/perm mapping */
5953*4882a593Smuzhiyun 			pr_warn_ratelimited("SELinux: unrecognized netlink"
5954*4882a593Smuzhiyun 				" message: protocol=%hu nlmsg_type=%hu sclass=%s"
5955*4882a593Smuzhiyun 				" pid=%d comm=%s\n",
5956*4882a593Smuzhiyun 				sk->sk_protocol, nlh->nlmsg_type,
5957*4882a593Smuzhiyun 				secclass_map[sclass - 1].name,
5958*4882a593Smuzhiyun 				task_pid_nr(current), current->comm);
5959*4882a593Smuzhiyun 			if (enforcing_enabled(&selinux_state) &&
5960*4882a593Smuzhiyun 			    !security_get_allow_unknown(&selinux_state))
5961*4882a593Smuzhiyun 				return rc;
5962*4882a593Smuzhiyun 			rc = 0;
5963*4882a593Smuzhiyun 		} else if (rc == -ENOENT) {
5964*4882a593Smuzhiyun 			/* -ENOENT is a missing socket/class mapping, ignore */
5965*4882a593Smuzhiyun 			rc = 0;
5966*4882a593Smuzhiyun 		} else {
5967*4882a593Smuzhiyun 			return rc;
5968*4882a593Smuzhiyun 		}
5969*4882a593Smuzhiyun 
5970*4882a593Smuzhiyun 		/* move to the next message after applying netlink padding */
5971*4882a593Smuzhiyun 		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
5972*4882a593Smuzhiyun 		if (msg_len >= data_len)
5973*4882a593Smuzhiyun 			return 0;
5974*4882a593Smuzhiyun 		data_len -= msg_len;
5975*4882a593Smuzhiyun 		data += msg_len;
5976*4882a593Smuzhiyun 	}
5977*4882a593Smuzhiyun 
5978*4882a593Smuzhiyun 	return rc;
5979*4882a593Smuzhiyun }
5980*4882a593Smuzhiyun 
ipc_init_security(struct ipc_security_struct * isec,u16 sclass)5981*4882a593Smuzhiyun static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
5982*4882a593Smuzhiyun {
5983*4882a593Smuzhiyun 	isec->sclass = sclass;
5984*4882a593Smuzhiyun 	isec->sid = current_sid();
5985*4882a593Smuzhiyun }
5986*4882a593Smuzhiyun 
ipc_has_perm(struct kern_ipc_perm * ipc_perms,u32 perms)5987*4882a593Smuzhiyun static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
5988*4882a593Smuzhiyun 			u32 perms)
5989*4882a593Smuzhiyun {
5990*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
5991*4882a593Smuzhiyun 	struct common_audit_data ad;
5992*4882a593Smuzhiyun 	u32 sid = current_sid();
5993*4882a593Smuzhiyun 
5994*4882a593Smuzhiyun 	isec = selinux_ipc(ipc_perms);
5995*4882a593Smuzhiyun 
5996*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
5997*4882a593Smuzhiyun 	ad.u.ipc_id = ipc_perms->key;
5998*4882a593Smuzhiyun 
5999*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6000*4882a593Smuzhiyun 			    sid, isec->sid, isec->sclass, perms, &ad);
6001*4882a593Smuzhiyun }
6002*4882a593Smuzhiyun 
selinux_msg_msg_alloc_security(struct msg_msg * msg)6003*4882a593Smuzhiyun static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
6004*4882a593Smuzhiyun {
6005*4882a593Smuzhiyun 	struct msg_security_struct *msec;
6006*4882a593Smuzhiyun 
6007*4882a593Smuzhiyun 	msec = selinux_msg_msg(msg);
6008*4882a593Smuzhiyun 	msec->sid = SECINITSID_UNLABELED;
6009*4882a593Smuzhiyun 
6010*4882a593Smuzhiyun 	return 0;
6011*4882a593Smuzhiyun }
6012*4882a593Smuzhiyun 
6013*4882a593Smuzhiyun /* message queue security operations */
selinux_msg_queue_alloc_security(struct kern_ipc_perm * msq)6014*4882a593Smuzhiyun static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
6015*4882a593Smuzhiyun {
6016*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6017*4882a593Smuzhiyun 	struct common_audit_data ad;
6018*4882a593Smuzhiyun 	u32 sid = current_sid();
6019*4882a593Smuzhiyun 	int rc;
6020*4882a593Smuzhiyun 
6021*4882a593Smuzhiyun 	isec = selinux_ipc(msq);
6022*4882a593Smuzhiyun 	ipc_init_security(isec, SECCLASS_MSGQ);
6023*4882a593Smuzhiyun 
6024*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6025*4882a593Smuzhiyun 	ad.u.ipc_id = msq->key;
6026*4882a593Smuzhiyun 
6027*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
6028*4882a593Smuzhiyun 			  sid, isec->sid, SECCLASS_MSGQ,
6029*4882a593Smuzhiyun 			  MSGQ__CREATE, &ad);
6030*4882a593Smuzhiyun 	return rc;
6031*4882a593Smuzhiyun }
6032*4882a593Smuzhiyun 
selinux_msg_queue_associate(struct kern_ipc_perm * msq,int msqflg)6033*4882a593Smuzhiyun static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
6034*4882a593Smuzhiyun {
6035*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6036*4882a593Smuzhiyun 	struct common_audit_data ad;
6037*4882a593Smuzhiyun 	u32 sid = current_sid();
6038*4882a593Smuzhiyun 
6039*4882a593Smuzhiyun 	isec = selinux_ipc(msq);
6040*4882a593Smuzhiyun 
6041*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6042*4882a593Smuzhiyun 	ad.u.ipc_id = msq->key;
6043*4882a593Smuzhiyun 
6044*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6045*4882a593Smuzhiyun 			    sid, isec->sid, SECCLASS_MSGQ,
6046*4882a593Smuzhiyun 			    MSGQ__ASSOCIATE, &ad);
6047*4882a593Smuzhiyun }
6048*4882a593Smuzhiyun 
selinux_msg_queue_msgctl(struct kern_ipc_perm * msq,int cmd)6049*4882a593Smuzhiyun static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
6050*4882a593Smuzhiyun {
6051*4882a593Smuzhiyun 	int err;
6052*4882a593Smuzhiyun 	int perms;
6053*4882a593Smuzhiyun 
6054*4882a593Smuzhiyun 	switch (cmd) {
6055*4882a593Smuzhiyun 	case IPC_INFO:
6056*4882a593Smuzhiyun 	case MSG_INFO:
6057*4882a593Smuzhiyun 		/* No specific object, just general system-wide information. */
6058*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
6059*4882a593Smuzhiyun 				    current_sid(), SECINITSID_KERNEL,
6060*4882a593Smuzhiyun 				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
6061*4882a593Smuzhiyun 	case IPC_STAT:
6062*4882a593Smuzhiyun 	case MSG_STAT:
6063*4882a593Smuzhiyun 	case MSG_STAT_ANY:
6064*4882a593Smuzhiyun 		perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
6065*4882a593Smuzhiyun 		break;
6066*4882a593Smuzhiyun 	case IPC_SET:
6067*4882a593Smuzhiyun 		perms = MSGQ__SETATTR;
6068*4882a593Smuzhiyun 		break;
6069*4882a593Smuzhiyun 	case IPC_RMID:
6070*4882a593Smuzhiyun 		perms = MSGQ__DESTROY;
6071*4882a593Smuzhiyun 		break;
6072*4882a593Smuzhiyun 	default:
6073*4882a593Smuzhiyun 		return 0;
6074*4882a593Smuzhiyun 	}
6075*4882a593Smuzhiyun 
6076*4882a593Smuzhiyun 	err = ipc_has_perm(msq, perms);
6077*4882a593Smuzhiyun 	return err;
6078*4882a593Smuzhiyun }
6079*4882a593Smuzhiyun 
selinux_msg_queue_msgsnd(struct kern_ipc_perm * msq,struct msg_msg * msg,int msqflg)6080*4882a593Smuzhiyun static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
6081*4882a593Smuzhiyun {
6082*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6083*4882a593Smuzhiyun 	struct msg_security_struct *msec;
6084*4882a593Smuzhiyun 	struct common_audit_data ad;
6085*4882a593Smuzhiyun 	u32 sid = current_sid();
6086*4882a593Smuzhiyun 	int rc;
6087*4882a593Smuzhiyun 
6088*4882a593Smuzhiyun 	isec = selinux_ipc(msq);
6089*4882a593Smuzhiyun 	msec = selinux_msg_msg(msg);
6090*4882a593Smuzhiyun 
6091*4882a593Smuzhiyun 	/*
6092*4882a593Smuzhiyun 	 * First time through, need to assign label to the message
6093*4882a593Smuzhiyun 	 */
6094*4882a593Smuzhiyun 	if (msec->sid == SECINITSID_UNLABELED) {
6095*4882a593Smuzhiyun 		/*
6096*4882a593Smuzhiyun 		 * Compute new sid based on current process and
6097*4882a593Smuzhiyun 		 * message queue this message will be stored in
6098*4882a593Smuzhiyun 		 */
6099*4882a593Smuzhiyun 		rc = security_transition_sid(&selinux_state, sid, isec->sid,
6100*4882a593Smuzhiyun 					     SECCLASS_MSG, NULL, &msec->sid);
6101*4882a593Smuzhiyun 		if (rc)
6102*4882a593Smuzhiyun 			return rc;
6103*4882a593Smuzhiyun 	}
6104*4882a593Smuzhiyun 
6105*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6106*4882a593Smuzhiyun 	ad.u.ipc_id = msq->key;
6107*4882a593Smuzhiyun 
6108*4882a593Smuzhiyun 	/* Can this process write to the queue? */
6109*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
6110*4882a593Smuzhiyun 			  sid, isec->sid, SECCLASS_MSGQ,
6111*4882a593Smuzhiyun 			  MSGQ__WRITE, &ad);
6112*4882a593Smuzhiyun 	if (!rc)
6113*4882a593Smuzhiyun 		/* Can this process send the message */
6114*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
6115*4882a593Smuzhiyun 				  sid, msec->sid, SECCLASS_MSG,
6116*4882a593Smuzhiyun 				  MSG__SEND, &ad);
6117*4882a593Smuzhiyun 	if (!rc)
6118*4882a593Smuzhiyun 		/* Can the message be put in the queue? */
6119*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
6120*4882a593Smuzhiyun 				  msec->sid, isec->sid, SECCLASS_MSGQ,
6121*4882a593Smuzhiyun 				  MSGQ__ENQUEUE, &ad);
6122*4882a593Smuzhiyun 
6123*4882a593Smuzhiyun 	return rc;
6124*4882a593Smuzhiyun }
6125*4882a593Smuzhiyun 
selinux_msg_queue_msgrcv(struct kern_ipc_perm * msq,struct msg_msg * msg,struct task_struct * target,long type,int mode)6126*4882a593Smuzhiyun static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
6127*4882a593Smuzhiyun 				    struct task_struct *target,
6128*4882a593Smuzhiyun 				    long type, int mode)
6129*4882a593Smuzhiyun {
6130*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6131*4882a593Smuzhiyun 	struct msg_security_struct *msec;
6132*4882a593Smuzhiyun 	struct common_audit_data ad;
6133*4882a593Smuzhiyun 	u32 sid = task_sid(target);
6134*4882a593Smuzhiyun 	int rc;
6135*4882a593Smuzhiyun 
6136*4882a593Smuzhiyun 	isec = selinux_ipc(msq);
6137*4882a593Smuzhiyun 	msec = selinux_msg_msg(msg);
6138*4882a593Smuzhiyun 
6139*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6140*4882a593Smuzhiyun 	ad.u.ipc_id = msq->key;
6141*4882a593Smuzhiyun 
6142*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
6143*4882a593Smuzhiyun 			  sid, isec->sid,
6144*4882a593Smuzhiyun 			  SECCLASS_MSGQ, MSGQ__READ, &ad);
6145*4882a593Smuzhiyun 	if (!rc)
6146*4882a593Smuzhiyun 		rc = avc_has_perm(&selinux_state,
6147*4882a593Smuzhiyun 				  sid, msec->sid,
6148*4882a593Smuzhiyun 				  SECCLASS_MSG, MSG__RECEIVE, &ad);
6149*4882a593Smuzhiyun 	return rc;
6150*4882a593Smuzhiyun }
6151*4882a593Smuzhiyun 
6152*4882a593Smuzhiyun /* Shared Memory security operations */
selinux_shm_alloc_security(struct kern_ipc_perm * shp)6153*4882a593Smuzhiyun static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
6154*4882a593Smuzhiyun {
6155*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6156*4882a593Smuzhiyun 	struct common_audit_data ad;
6157*4882a593Smuzhiyun 	u32 sid = current_sid();
6158*4882a593Smuzhiyun 	int rc;
6159*4882a593Smuzhiyun 
6160*4882a593Smuzhiyun 	isec = selinux_ipc(shp);
6161*4882a593Smuzhiyun 	ipc_init_security(isec, SECCLASS_SHM);
6162*4882a593Smuzhiyun 
6163*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6164*4882a593Smuzhiyun 	ad.u.ipc_id = shp->key;
6165*4882a593Smuzhiyun 
6166*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
6167*4882a593Smuzhiyun 			  sid, isec->sid, SECCLASS_SHM,
6168*4882a593Smuzhiyun 			  SHM__CREATE, &ad);
6169*4882a593Smuzhiyun 	return rc;
6170*4882a593Smuzhiyun }
6171*4882a593Smuzhiyun 
selinux_shm_associate(struct kern_ipc_perm * shp,int shmflg)6172*4882a593Smuzhiyun static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
6173*4882a593Smuzhiyun {
6174*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6175*4882a593Smuzhiyun 	struct common_audit_data ad;
6176*4882a593Smuzhiyun 	u32 sid = current_sid();
6177*4882a593Smuzhiyun 
6178*4882a593Smuzhiyun 	isec = selinux_ipc(shp);
6179*4882a593Smuzhiyun 
6180*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6181*4882a593Smuzhiyun 	ad.u.ipc_id = shp->key;
6182*4882a593Smuzhiyun 
6183*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6184*4882a593Smuzhiyun 			    sid, isec->sid, SECCLASS_SHM,
6185*4882a593Smuzhiyun 			    SHM__ASSOCIATE, &ad);
6186*4882a593Smuzhiyun }
6187*4882a593Smuzhiyun 
6188*4882a593Smuzhiyun /* Note, at this point, shp is locked down */
selinux_shm_shmctl(struct kern_ipc_perm * shp,int cmd)6189*4882a593Smuzhiyun static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
6190*4882a593Smuzhiyun {
6191*4882a593Smuzhiyun 	int perms;
6192*4882a593Smuzhiyun 	int err;
6193*4882a593Smuzhiyun 
6194*4882a593Smuzhiyun 	switch (cmd) {
6195*4882a593Smuzhiyun 	case IPC_INFO:
6196*4882a593Smuzhiyun 	case SHM_INFO:
6197*4882a593Smuzhiyun 		/* No specific object, just general system-wide information. */
6198*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
6199*4882a593Smuzhiyun 				    current_sid(), SECINITSID_KERNEL,
6200*4882a593Smuzhiyun 				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
6201*4882a593Smuzhiyun 	case IPC_STAT:
6202*4882a593Smuzhiyun 	case SHM_STAT:
6203*4882a593Smuzhiyun 	case SHM_STAT_ANY:
6204*4882a593Smuzhiyun 		perms = SHM__GETATTR | SHM__ASSOCIATE;
6205*4882a593Smuzhiyun 		break;
6206*4882a593Smuzhiyun 	case IPC_SET:
6207*4882a593Smuzhiyun 		perms = SHM__SETATTR;
6208*4882a593Smuzhiyun 		break;
6209*4882a593Smuzhiyun 	case SHM_LOCK:
6210*4882a593Smuzhiyun 	case SHM_UNLOCK:
6211*4882a593Smuzhiyun 		perms = SHM__LOCK;
6212*4882a593Smuzhiyun 		break;
6213*4882a593Smuzhiyun 	case IPC_RMID:
6214*4882a593Smuzhiyun 		perms = SHM__DESTROY;
6215*4882a593Smuzhiyun 		break;
6216*4882a593Smuzhiyun 	default:
6217*4882a593Smuzhiyun 		return 0;
6218*4882a593Smuzhiyun 	}
6219*4882a593Smuzhiyun 
6220*4882a593Smuzhiyun 	err = ipc_has_perm(shp, perms);
6221*4882a593Smuzhiyun 	return err;
6222*4882a593Smuzhiyun }
6223*4882a593Smuzhiyun 
selinux_shm_shmat(struct kern_ipc_perm * shp,char __user * shmaddr,int shmflg)6224*4882a593Smuzhiyun static int selinux_shm_shmat(struct kern_ipc_perm *shp,
6225*4882a593Smuzhiyun 			     char __user *shmaddr, int shmflg)
6226*4882a593Smuzhiyun {
6227*4882a593Smuzhiyun 	u32 perms;
6228*4882a593Smuzhiyun 
6229*4882a593Smuzhiyun 	if (shmflg & SHM_RDONLY)
6230*4882a593Smuzhiyun 		perms = SHM__READ;
6231*4882a593Smuzhiyun 	else
6232*4882a593Smuzhiyun 		perms = SHM__READ | SHM__WRITE;
6233*4882a593Smuzhiyun 
6234*4882a593Smuzhiyun 	return ipc_has_perm(shp, perms);
6235*4882a593Smuzhiyun }
6236*4882a593Smuzhiyun 
6237*4882a593Smuzhiyun /* Semaphore security operations */
selinux_sem_alloc_security(struct kern_ipc_perm * sma)6238*4882a593Smuzhiyun static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
6239*4882a593Smuzhiyun {
6240*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6241*4882a593Smuzhiyun 	struct common_audit_data ad;
6242*4882a593Smuzhiyun 	u32 sid = current_sid();
6243*4882a593Smuzhiyun 	int rc;
6244*4882a593Smuzhiyun 
6245*4882a593Smuzhiyun 	isec = selinux_ipc(sma);
6246*4882a593Smuzhiyun 	ipc_init_security(isec, SECCLASS_SEM);
6247*4882a593Smuzhiyun 
6248*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6249*4882a593Smuzhiyun 	ad.u.ipc_id = sma->key;
6250*4882a593Smuzhiyun 
6251*4882a593Smuzhiyun 	rc = avc_has_perm(&selinux_state,
6252*4882a593Smuzhiyun 			  sid, isec->sid, SECCLASS_SEM,
6253*4882a593Smuzhiyun 			  SEM__CREATE, &ad);
6254*4882a593Smuzhiyun 	return rc;
6255*4882a593Smuzhiyun }
6256*4882a593Smuzhiyun 
selinux_sem_associate(struct kern_ipc_perm * sma,int semflg)6257*4882a593Smuzhiyun static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
6258*4882a593Smuzhiyun {
6259*4882a593Smuzhiyun 	struct ipc_security_struct *isec;
6260*4882a593Smuzhiyun 	struct common_audit_data ad;
6261*4882a593Smuzhiyun 	u32 sid = current_sid();
6262*4882a593Smuzhiyun 
6263*4882a593Smuzhiyun 	isec = selinux_ipc(sma);
6264*4882a593Smuzhiyun 
6265*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IPC;
6266*4882a593Smuzhiyun 	ad.u.ipc_id = sma->key;
6267*4882a593Smuzhiyun 
6268*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6269*4882a593Smuzhiyun 			    sid, isec->sid, SECCLASS_SEM,
6270*4882a593Smuzhiyun 			    SEM__ASSOCIATE, &ad);
6271*4882a593Smuzhiyun }
6272*4882a593Smuzhiyun 
6273*4882a593Smuzhiyun /* Note, at this point, sma is locked down */
selinux_sem_semctl(struct kern_ipc_perm * sma,int cmd)6274*4882a593Smuzhiyun static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
6275*4882a593Smuzhiyun {
6276*4882a593Smuzhiyun 	int err;
6277*4882a593Smuzhiyun 	u32 perms;
6278*4882a593Smuzhiyun 
6279*4882a593Smuzhiyun 	switch (cmd) {
6280*4882a593Smuzhiyun 	case IPC_INFO:
6281*4882a593Smuzhiyun 	case SEM_INFO:
6282*4882a593Smuzhiyun 		/* No specific object, just general system-wide information. */
6283*4882a593Smuzhiyun 		return avc_has_perm(&selinux_state,
6284*4882a593Smuzhiyun 				    current_sid(), SECINITSID_KERNEL,
6285*4882a593Smuzhiyun 				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
6286*4882a593Smuzhiyun 	case GETPID:
6287*4882a593Smuzhiyun 	case GETNCNT:
6288*4882a593Smuzhiyun 	case GETZCNT:
6289*4882a593Smuzhiyun 		perms = SEM__GETATTR;
6290*4882a593Smuzhiyun 		break;
6291*4882a593Smuzhiyun 	case GETVAL:
6292*4882a593Smuzhiyun 	case GETALL:
6293*4882a593Smuzhiyun 		perms = SEM__READ;
6294*4882a593Smuzhiyun 		break;
6295*4882a593Smuzhiyun 	case SETVAL:
6296*4882a593Smuzhiyun 	case SETALL:
6297*4882a593Smuzhiyun 		perms = SEM__WRITE;
6298*4882a593Smuzhiyun 		break;
6299*4882a593Smuzhiyun 	case IPC_RMID:
6300*4882a593Smuzhiyun 		perms = SEM__DESTROY;
6301*4882a593Smuzhiyun 		break;
6302*4882a593Smuzhiyun 	case IPC_SET:
6303*4882a593Smuzhiyun 		perms = SEM__SETATTR;
6304*4882a593Smuzhiyun 		break;
6305*4882a593Smuzhiyun 	case IPC_STAT:
6306*4882a593Smuzhiyun 	case SEM_STAT:
6307*4882a593Smuzhiyun 	case SEM_STAT_ANY:
6308*4882a593Smuzhiyun 		perms = SEM__GETATTR | SEM__ASSOCIATE;
6309*4882a593Smuzhiyun 		break;
6310*4882a593Smuzhiyun 	default:
6311*4882a593Smuzhiyun 		return 0;
6312*4882a593Smuzhiyun 	}
6313*4882a593Smuzhiyun 
6314*4882a593Smuzhiyun 	err = ipc_has_perm(sma, perms);
6315*4882a593Smuzhiyun 	return err;
6316*4882a593Smuzhiyun }
6317*4882a593Smuzhiyun 
selinux_sem_semop(struct kern_ipc_perm * sma,struct sembuf * sops,unsigned nsops,int alter)6318*4882a593Smuzhiyun static int selinux_sem_semop(struct kern_ipc_perm *sma,
6319*4882a593Smuzhiyun 			     struct sembuf *sops, unsigned nsops, int alter)
6320*4882a593Smuzhiyun {
6321*4882a593Smuzhiyun 	u32 perms;
6322*4882a593Smuzhiyun 
6323*4882a593Smuzhiyun 	if (alter)
6324*4882a593Smuzhiyun 		perms = SEM__READ | SEM__WRITE;
6325*4882a593Smuzhiyun 	else
6326*4882a593Smuzhiyun 		perms = SEM__READ;
6327*4882a593Smuzhiyun 
6328*4882a593Smuzhiyun 	return ipc_has_perm(sma, perms);
6329*4882a593Smuzhiyun }
6330*4882a593Smuzhiyun 
selinux_ipc_permission(struct kern_ipc_perm * ipcp,short flag)6331*4882a593Smuzhiyun static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6332*4882a593Smuzhiyun {
6333*4882a593Smuzhiyun 	u32 av = 0;
6334*4882a593Smuzhiyun 
6335*4882a593Smuzhiyun 	av = 0;
6336*4882a593Smuzhiyun 	if (flag & S_IRUGO)
6337*4882a593Smuzhiyun 		av |= IPC__UNIX_READ;
6338*4882a593Smuzhiyun 	if (flag & S_IWUGO)
6339*4882a593Smuzhiyun 		av |= IPC__UNIX_WRITE;
6340*4882a593Smuzhiyun 
6341*4882a593Smuzhiyun 	if (av == 0)
6342*4882a593Smuzhiyun 		return 0;
6343*4882a593Smuzhiyun 
6344*4882a593Smuzhiyun 	return ipc_has_perm(ipcp, av);
6345*4882a593Smuzhiyun }
6346*4882a593Smuzhiyun 
selinux_ipc_getsecid(struct kern_ipc_perm * ipcp,u32 * secid)6347*4882a593Smuzhiyun static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6348*4882a593Smuzhiyun {
6349*4882a593Smuzhiyun 	struct ipc_security_struct *isec = selinux_ipc(ipcp);
6350*4882a593Smuzhiyun 	*secid = isec->sid;
6351*4882a593Smuzhiyun }
6352*4882a593Smuzhiyun 
selinux_d_instantiate(struct dentry * dentry,struct inode * inode)6353*4882a593Smuzhiyun static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
6354*4882a593Smuzhiyun {
6355*4882a593Smuzhiyun 	if (inode)
6356*4882a593Smuzhiyun 		inode_doinit_with_dentry(inode, dentry);
6357*4882a593Smuzhiyun }
6358*4882a593Smuzhiyun 
selinux_getprocattr(struct task_struct * p,char * name,char ** value)6359*4882a593Smuzhiyun static int selinux_getprocattr(struct task_struct *p,
6360*4882a593Smuzhiyun 			       char *name, char **value)
6361*4882a593Smuzhiyun {
6362*4882a593Smuzhiyun 	const struct task_security_struct *__tsec;
6363*4882a593Smuzhiyun 	u32 sid;
6364*4882a593Smuzhiyun 	int error;
6365*4882a593Smuzhiyun 	unsigned len;
6366*4882a593Smuzhiyun 
6367*4882a593Smuzhiyun 	rcu_read_lock();
6368*4882a593Smuzhiyun 	__tsec = selinux_cred(__task_cred(p));
6369*4882a593Smuzhiyun 
6370*4882a593Smuzhiyun 	if (current != p) {
6371*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6372*4882a593Smuzhiyun 				     current_sid(), __tsec->sid,
6373*4882a593Smuzhiyun 				     SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6374*4882a593Smuzhiyun 		if (error)
6375*4882a593Smuzhiyun 			goto bad;
6376*4882a593Smuzhiyun 	}
6377*4882a593Smuzhiyun 
6378*4882a593Smuzhiyun 	if (!strcmp(name, "current"))
6379*4882a593Smuzhiyun 		sid = __tsec->sid;
6380*4882a593Smuzhiyun 	else if (!strcmp(name, "prev"))
6381*4882a593Smuzhiyun 		sid = __tsec->osid;
6382*4882a593Smuzhiyun 	else if (!strcmp(name, "exec"))
6383*4882a593Smuzhiyun 		sid = __tsec->exec_sid;
6384*4882a593Smuzhiyun 	else if (!strcmp(name, "fscreate"))
6385*4882a593Smuzhiyun 		sid = __tsec->create_sid;
6386*4882a593Smuzhiyun 	else if (!strcmp(name, "keycreate"))
6387*4882a593Smuzhiyun 		sid = __tsec->keycreate_sid;
6388*4882a593Smuzhiyun 	else if (!strcmp(name, "sockcreate"))
6389*4882a593Smuzhiyun 		sid = __tsec->sockcreate_sid;
6390*4882a593Smuzhiyun 	else {
6391*4882a593Smuzhiyun 		error = -EINVAL;
6392*4882a593Smuzhiyun 		goto bad;
6393*4882a593Smuzhiyun 	}
6394*4882a593Smuzhiyun 	rcu_read_unlock();
6395*4882a593Smuzhiyun 
6396*4882a593Smuzhiyun 	if (!sid)
6397*4882a593Smuzhiyun 		return 0;
6398*4882a593Smuzhiyun 
6399*4882a593Smuzhiyun 	error = security_sid_to_context(&selinux_state, sid, value, &len);
6400*4882a593Smuzhiyun 	if (error)
6401*4882a593Smuzhiyun 		return error;
6402*4882a593Smuzhiyun 	return len;
6403*4882a593Smuzhiyun 
6404*4882a593Smuzhiyun bad:
6405*4882a593Smuzhiyun 	rcu_read_unlock();
6406*4882a593Smuzhiyun 	return error;
6407*4882a593Smuzhiyun }
6408*4882a593Smuzhiyun 
selinux_setprocattr(const char * name,void * value,size_t size)6409*4882a593Smuzhiyun static int selinux_setprocattr(const char *name, void *value, size_t size)
6410*4882a593Smuzhiyun {
6411*4882a593Smuzhiyun 	struct task_security_struct *tsec;
6412*4882a593Smuzhiyun 	struct cred *new;
6413*4882a593Smuzhiyun 	u32 mysid = current_sid(), sid = 0, ptsid;
6414*4882a593Smuzhiyun 	int error;
6415*4882a593Smuzhiyun 	char *str = value;
6416*4882a593Smuzhiyun 
6417*4882a593Smuzhiyun 	/*
6418*4882a593Smuzhiyun 	 * Basic control over ability to set these attributes at all.
6419*4882a593Smuzhiyun 	 */
6420*4882a593Smuzhiyun 	if (!strcmp(name, "exec"))
6421*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6422*4882a593Smuzhiyun 				     mysid, mysid, SECCLASS_PROCESS,
6423*4882a593Smuzhiyun 				     PROCESS__SETEXEC, NULL);
6424*4882a593Smuzhiyun 	else if (!strcmp(name, "fscreate"))
6425*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6426*4882a593Smuzhiyun 				     mysid, mysid, SECCLASS_PROCESS,
6427*4882a593Smuzhiyun 				     PROCESS__SETFSCREATE, NULL);
6428*4882a593Smuzhiyun 	else if (!strcmp(name, "keycreate"))
6429*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6430*4882a593Smuzhiyun 				     mysid, mysid, SECCLASS_PROCESS,
6431*4882a593Smuzhiyun 				     PROCESS__SETKEYCREATE, NULL);
6432*4882a593Smuzhiyun 	else if (!strcmp(name, "sockcreate"))
6433*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6434*4882a593Smuzhiyun 				     mysid, mysid, SECCLASS_PROCESS,
6435*4882a593Smuzhiyun 				     PROCESS__SETSOCKCREATE, NULL);
6436*4882a593Smuzhiyun 	else if (!strcmp(name, "current"))
6437*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6438*4882a593Smuzhiyun 				     mysid, mysid, SECCLASS_PROCESS,
6439*4882a593Smuzhiyun 				     PROCESS__SETCURRENT, NULL);
6440*4882a593Smuzhiyun 	else
6441*4882a593Smuzhiyun 		error = -EINVAL;
6442*4882a593Smuzhiyun 	if (error)
6443*4882a593Smuzhiyun 		return error;
6444*4882a593Smuzhiyun 
6445*4882a593Smuzhiyun 	/* Obtain a SID for the context, if one was specified. */
6446*4882a593Smuzhiyun 	if (size && str[0] && str[0] != '\n') {
6447*4882a593Smuzhiyun 		if (str[size-1] == '\n') {
6448*4882a593Smuzhiyun 			str[size-1] = 0;
6449*4882a593Smuzhiyun 			size--;
6450*4882a593Smuzhiyun 		}
6451*4882a593Smuzhiyun 		error = security_context_to_sid(&selinux_state, value, size,
6452*4882a593Smuzhiyun 						&sid, GFP_KERNEL);
6453*4882a593Smuzhiyun 		if (error == -EINVAL && !strcmp(name, "fscreate")) {
6454*4882a593Smuzhiyun 			if (!has_cap_mac_admin(true)) {
6455*4882a593Smuzhiyun 				struct audit_buffer *ab;
6456*4882a593Smuzhiyun 				size_t audit_size;
6457*4882a593Smuzhiyun 
6458*4882a593Smuzhiyun 				/* We strip a nul only if it is at the end, otherwise the
6459*4882a593Smuzhiyun 				 * context contains a nul and we should audit that */
6460*4882a593Smuzhiyun 				if (str[size - 1] == '\0')
6461*4882a593Smuzhiyun 					audit_size = size - 1;
6462*4882a593Smuzhiyun 				else
6463*4882a593Smuzhiyun 					audit_size = size;
6464*4882a593Smuzhiyun 				ab = audit_log_start(audit_context(),
6465*4882a593Smuzhiyun 						     GFP_ATOMIC,
6466*4882a593Smuzhiyun 						     AUDIT_SELINUX_ERR);
6467*4882a593Smuzhiyun 				audit_log_format(ab, "op=fscreate invalid_context=");
6468*4882a593Smuzhiyun 				audit_log_n_untrustedstring(ab, value, audit_size);
6469*4882a593Smuzhiyun 				audit_log_end(ab);
6470*4882a593Smuzhiyun 
6471*4882a593Smuzhiyun 				return error;
6472*4882a593Smuzhiyun 			}
6473*4882a593Smuzhiyun 			error = security_context_to_sid_force(
6474*4882a593Smuzhiyun 						      &selinux_state,
6475*4882a593Smuzhiyun 						      value, size, &sid);
6476*4882a593Smuzhiyun 		}
6477*4882a593Smuzhiyun 		if (error)
6478*4882a593Smuzhiyun 			return error;
6479*4882a593Smuzhiyun 	}
6480*4882a593Smuzhiyun 
6481*4882a593Smuzhiyun 	new = prepare_creds();
6482*4882a593Smuzhiyun 	if (!new)
6483*4882a593Smuzhiyun 		return -ENOMEM;
6484*4882a593Smuzhiyun 
6485*4882a593Smuzhiyun 	/* Permission checking based on the specified context is
6486*4882a593Smuzhiyun 	   performed during the actual operation (execve,
6487*4882a593Smuzhiyun 	   open/mkdir/...), when we know the full context of the
6488*4882a593Smuzhiyun 	   operation.  See selinux_bprm_creds_for_exec for the execve
6489*4882a593Smuzhiyun 	   checks and may_create for the file creation checks. The
6490*4882a593Smuzhiyun 	   operation will then fail if the context is not permitted. */
6491*4882a593Smuzhiyun 	tsec = selinux_cred(new);
6492*4882a593Smuzhiyun 	if (!strcmp(name, "exec")) {
6493*4882a593Smuzhiyun 		tsec->exec_sid = sid;
6494*4882a593Smuzhiyun 	} else if (!strcmp(name, "fscreate")) {
6495*4882a593Smuzhiyun 		tsec->create_sid = sid;
6496*4882a593Smuzhiyun 	} else if (!strcmp(name, "keycreate")) {
6497*4882a593Smuzhiyun 		if (sid) {
6498*4882a593Smuzhiyun 			error = avc_has_perm(&selinux_state, mysid, sid,
6499*4882a593Smuzhiyun 					     SECCLASS_KEY, KEY__CREATE, NULL);
6500*4882a593Smuzhiyun 			if (error)
6501*4882a593Smuzhiyun 				goto abort_change;
6502*4882a593Smuzhiyun 		}
6503*4882a593Smuzhiyun 		tsec->keycreate_sid = sid;
6504*4882a593Smuzhiyun 	} else if (!strcmp(name, "sockcreate")) {
6505*4882a593Smuzhiyun 		tsec->sockcreate_sid = sid;
6506*4882a593Smuzhiyun 	} else if (!strcmp(name, "current")) {
6507*4882a593Smuzhiyun 		error = -EINVAL;
6508*4882a593Smuzhiyun 		if (sid == 0)
6509*4882a593Smuzhiyun 			goto abort_change;
6510*4882a593Smuzhiyun 
6511*4882a593Smuzhiyun 		/* Only allow single threaded processes to change context */
6512*4882a593Smuzhiyun 		error = -EPERM;
6513*4882a593Smuzhiyun 		if (!current_is_single_threaded()) {
6514*4882a593Smuzhiyun 			error = security_bounded_transition(&selinux_state,
6515*4882a593Smuzhiyun 							    tsec->sid, sid);
6516*4882a593Smuzhiyun 			if (error)
6517*4882a593Smuzhiyun 				goto abort_change;
6518*4882a593Smuzhiyun 		}
6519*4882a593Smuzhiyun 
6520*4882a593Smuzhiyun 		/* Check permissions for the transition. */
6521*4882a593Smuzhiyun 		error = avc_has_perm(&selinux_state,
6522*4882a593Smuzhiyun 				     tsec->sid, sid, SECCLASS_PROCESS,
6523*4882a593Smuzhiyun 				     PROCESS__DYNTRANSITION, NULL);
6524*4882a593Smuzhiyun 		if (error)
6525*4882a593Smuzhiyun 			goto abort_change;
6526*4882a593Smuzhiyun 
6527*4882a593Smuzhiyun 		/* Check for ptracing, and update the task SID if ok.
6528*4882a593Smuzhiyun 		   Otherwise, leave SID unchanged and fail. */
6529*4882a593Smuzhiyun 		ptsid = ptrace_parent_sid();
6530*4882a593Smuzhiyun 		if (ptsid != 0) {
6531*4882a593Smuzhiyun 			error = avc_has_perm(&selinux_state,
6532*4882a593Smuzhiyun 					     ptsid, sid, SECCLASS_PROCESS,
6533*4882a593Smuzhiyun 					     PROCESS__PTRACE, NULL);
6534*4882a593Smuzhiyun 			if (error)
6535*4882a593Smuzhiyun 				goto abort_change;
6536*4882a593Smuzhiyun 		}
6537*4882a593Smuzhiyun 
6538*4882a593Smuzhiyun 		tsec->sid = sid;
6539*4882a593Smuzhiyun 	} else {
6540*4882a593Smuzhiyun 		error = -EINVAL;
6541*4882a593Smuzhiyun 		goto abort_change;
6542*4882a593Smuzhiyun 	}
6543*4882a593Smuzhiyun 
6544*4882a593Smuzhiyun 	commit_creds(new);
6545*4882a593Smuzhiyun 	return size;
6546*4882a593Smuzhiyun 
6547*4882a593Smuzhiyun abort_change:
6548*4882a593Smuzhiyun 	abort_creds(new);
6549*4882a593Smuzhiyun 	return error;
6550*4882a593Smuzhiyun }
6551*4882a593Smuzhiyun 
selinux_ismaclabel(const char * name)6552*4882a593Smuzhiyun static int selinux_ismaclabel(const char *name)
6553*4882a593Smuzhiyun {
6554*4882a593Smuzhiyun 	return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6555*4882a593Smuzhiyun }
6556*4882a593Smuzhiyun 
selinux_secid_to_secctx(u32 secid,char ** secdata,u32 * seclen)6557*4882a593Smuzhiyun static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6558*4882a593Smuzhiyun {
6559*4882a593Smuzhiyun 	return security_sid_to_context(&selinux_state, secid,
6560*4882a593Smuzhiyun 				       secdata, seclen);
6561*4882a593Smuzhiyun }
6562*4882a593Smuzhiyun 
selinux_secctx_to_secid(const char * secdata,u32 seclen,u32 * secid)6563*4882a593Smuzhiyun static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
6564*4882a593Smuzhiyun {
6565*4882a593Smuzhiyun 	return security_context_to_sid(&selinux_state, secdata, seclen,
6566*4882a593Smuzhiyun 				       secid, GFP_KERNEL);
6567*4882a593Smuzhiyun }
6568*4882a593Smuzhiyun 
selinux_release_secctx(char * secdata,u32 seclen)6569*4882a593Smuzhiyun static void selinux_release_secctx(char *secdata, u32 seclen)
6570*4882a593Smuzhiyun {
6571*4882a593Smuzhiyun 	kfree(secdata);
6572*4882a593Smuzhiyun }
6573*4882a593Smuzhiyun 
selinux_inode_invalidate_secctx(struct inode * inode)6574*4882a593Smuzhiyun static void selinux_inode_invalidate_secctx(struct inode *inode)
6575*4882a593Smuzhiyun {
6576*4882a593Smuzhiyun 	struct inode_security_struct *isec = selinux_inode(inode);
6577*4882a593Smuzhiyun 
6578*4882a593Smuzhiyun 	spin_lock(&isec->lock);
6579*4882a593Smuzhiyun 	isec->initialized = LABEL_INVALID;
6580*4882a593Smuzhiyun 	spin_unlock(&isec->lock);
6581*4882a593Smuzhiyun }
6582*4882a593Smuzhiyun 
6583*4882a593Smuzhiyun /*
6584*4882a593Smuzhiyun  *	called with inode->i_mutex locked
6585*4882a593Smuzhiyun  */
selinux_inode_notifysecctx(struct inode * inode,void * ctx,u32 ctxlen)6586*4882a593Smuzhiyun static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6587*4882a593Smuzhiyun {
6588*4882a593Smuzhiyun 	int rc = selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX,
6589*4882a593Smuzhiyun 					   ctx, ctxlen, 0);
6590*4882a593Smuzhiyun 	/* Do not return error when suppressing label (SBLABEL_MNT not set). */
6591*4882a593Smuzhiyun 	return rc == -EOPNOTSUPP ? 0 : rc;
6592*4882a593Smuzhiyun }
6593*4882a593Smuzhiyun 
6594*4882a593Smuzhiyun /*
6595*4882a593Smuzhiyun  *	called with inode->i_mutex locked
6596*4882a593Smuzhiyun  */
selinux_inode_setsecctx(struct dentry * dentry,void * ctx,u32 ctxlen)6597*4882a593Smuzhiyun static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6598*4882a593Smuzhiyun {
6599*4882a593Smuzhiyun 	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6600*4882a593Smuzhiyun }
6601*4882a593Smuzhiyun 
selinux_inode_getsecctx(struct inode * inode,void ** ctx,u32 * ctxlen)6602*4882a593Smuzhiyun static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6603*4882a593Smuzhiyun {
6604*4882a593Smuzhiyun 	int len = 0;
6605*4882a593Smuzhiyun 	len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6606*4882a593Smuzhiyun 						ctx, true);
6607*4882a593Smuzhiyun 	if (len < 0)
6608*4882a593Smuzhiyun 		return len;
6609*4882a593Smuzhiyun 	*ctxlen = len;
6610*4882a593Smuzhiyun 	return 0;
6611*4882a593Smuzhiyun }
6612*4882a593Smuzhiyun #ifdef CONFIG_KEYS
6613*4882a593Smuzhiyun 
selinux_key_alloc(struct key * k,const struct cred * cred,unsigned long flags)6614*4882a593Smuzhiyun static int selinux_key_alloc(struct key *k, const struct cred *cred,
6615*4882a593Smuzhiyun 			     unsigned long flags)
6616*4882a593Smuzhiyun {
6617*4882a593Smuzhiyun 	const struct task_security_struct *tsec;
6618*4882a593Smuzhiyun 	struct key_security_struct *ksec;
6619*4882a593Smuzhiyun 
6620*4882a593Smuzhiyun 	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6621*4882a593Smuzhiyun 	if (!ksec)
6622*4882a593Smuzhiyun 		return -ENOMEM;
6623*4882a593Smuzhiyun 
6624*4882a593Smuzhiyun 	tsec = selinux_cred(cred);
6625*4882a593Smuzhiyun 	if (tsec->keycreate_sid)
6626*4882a593Smuzhiyun 		ksec->sid = tsec->keycreate_sid;
6627*4882a593Smuzhiyun 	else
6628*4882a593Smuzhiyun 		ksec->sid = tsec->sid;
6629*4882a593Smuzhiyun 
6630*4882a593Smuzhiyun 	k->security = ksec;
6631*4882a593Smuzhiyun 	return 0;
6632*4882a593Smuzhiyun }
6633*4882a593Smuzhiyun 
selinux_key_free(struct key * k)6634*4882a593Smuzhiyun static void selinux_key_free(struct key *k)
6635*4882a593Smuzhiyun {
6636*4882a593Smuzhiyun 	struct key_security_struct *ksec = k->security;
6637*4882a593Smuzhiyun 
6638*4882a593Smuzhiyun 	k->security = NULL;
6639*4882a593Smuzhiyun 	kfree(ksec);
6640*4882a593Smuzhiyun }
6641*4882a593Smuzhiyun 
selinux_key_permission(key_ref_t key_ref,const struct cred * cred,enum key_need_perm need_perm)6642*4882a593Smuzhiyun static int selinux_key_permission(key_ref_t key_ref,
6643*4882a593Smuzhiyun 				  const struct cred *cred,
6644*4882a593Smuzhiyun 				  enum key_need_perm need_perm)
6645*4882a593Smuzhiyun {
6646*4882a593Smuzhiyun 	struct key *key;
6647*4882a593Smuzhiyun 	struct key_security_struct *ksec;
6648*4882a593Smuzhiyun 	u32 perm, sid;
6649*4882a593Smuzhiyun 
6650*4882a593Smuzhiyun 	switch (need_perm) {
6651*4882a593Smuzhiyun 	case KEY_NEED_VIEW:
6652*4882a593Smuzhiyun 		perm = KEY__VIEW;
6653*4882a593Smuzhiyun 		break;
6654*4882a593Smuzhiyun 	case KEY_NEED_READ:
6655*4882a593Smuzhiyun 		perm = KEY__READ;
6656*4882a593Smuzhiyun 		break;
6657*4882a593Smuzhiyun 	case KEY_NEED_WRITE:
6658*4882a593Smuzhiyun 		perm = KEY__WRITE;
6659*4882a593Smuzhiyun 		break;
6660*4882a593Smuzhiyun 	case KEY_NEED_SEARCH:
6661*4882a593Smuzhiyun 		perm = KEY__SEARCH;
6662*4882a593Smuzhiyun 		break;
6663*4882a593Smuzhiyun 	case KEY_NEED_LINK:
6664*4882a593Smuzhiyun 		perm = KEY__LINK;
6665*4882a593Smuzhiyun 		break;
6666*4882a593Smuzhiyun 	case KEY_NEED_SETATTR:
6667*4882a593Smuzhiyun 		perm = KEY__SETATTR;
6668*4882a593Smuzhiyun 		break;
6669*4882a593Smuzhiyun 	case KEY_NEED_UNLINK:
6670*4882a593Smuzhiyun 	case KEY_SYSADMIN_OVERRIDE:
6671*4882a593Smuzhiyun 	case KEY_AUTHTOKEN_OVERRIDE:
6672*4882a593Smuzhiyun 	case KEY_DEFER_PERM_CHECK:
6673*4882a593Smuzhiyun 		return 0;
6674*4882a593Smuzhiyun 	default:
6675*4882a593Smuzhiyun 		WARN_ON(1);
6676*4882a593Smuzhiyun 		return -EPERM;
6677*4882a593Smuzhiyun 
6678*4882a593Smuzhiyun 	}
6679*4882a593Smuzhiyun 
6680*4882a593Smuzhiyun 	sid = cred_sid(cred);
6681*4882a593Smuzhiyun 	key = key_ref_to_ptr(key_ref);
6682*4882a593Smuzhiyun 	ksec = key->security;
6683*4882a593Smuzhiyun 
6684*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6685*4882a593Smuzhiyun 			    sid, ksec->sid, SECCLASS_KEY, perm, NULL);
6686*4882a593Smuzhiyun }
6687*4882a593Smuzhiyun 
selinux_key_getsecurity(struct key * key,char ** _buffer)6688*4882a593Smuzhiyun static int selinux_key_getsecurity(struct key *key, char **_buffer)
6689*4882a593Smuzhiyun {
6690*4882a593Smuzhiyun 	struct key_security_struct *ksec = key->security;
6691*4882a593Smuzhiyun 	char *context = NULL;
6692*4882a593Smuzhiyun 	unsigned len;
6693*4882a593Smuzhiyun 	int rc;
6694*4882a593Smuzhiyun 
6695*4882a593Smuzhiyun 	rc = security_sid_to_context(&selinux_state, ksec->sid,
6696*4882a593Smuzhiyun 				     &context, &len);
6697*4882a593Smuzhiyun 	if (!rc)
6698*4882a593Smuzhiyun 		rc = len;
6699*4882a593Smuzhiyun 	*_buffer = context;
6700*4882a593Smuzhiyun 	return rc;
6701*4882a593Smuzhiyun }
6702*4882a593Smuzhiyun 
6703*4882a593Smuzhiyun #ifdef CONFIG_KEY_NOTIFICATIONS
selinux_watch_key(struct key * key)6704*4882a593Smuzhiyun static int selinux_watch_key(struct key *key)
6705*4882a593Smuzhiyun {
6706*4882a593Smuzhiyun 	struct key_security_struct *ksec = key->security;
6707*4882a593Smuzhiyun 	u32 sid = current_sid();
6708*4882a593Smuzhiyun 
6709*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6710*4882a593Smuzhiyun 			    sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL);
6711*4882a593Smuzhiyun }
6712*4882a593Smuzhiyun #endif
6713*4882a593Smuzhiyun #endif
6714*4882a593Smuzhiyun 
6715*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_INFINIBAND
selinux_ib_pkey_access(void * ib_sec,u64 subnet_prefix,u16 pkey_val)6716*4882a593Smuzhiyun static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6717*4882a593Smuzhiyun {
6718*4882a593Smuzhiyun 	struct common_audit_data ad;
6719*4882a593Smuzhiyun 	int err;
6720*4882a593Smuzhiyun 	u32 sid = 0;
6721*4882a593Smuzhiyun 	struct ib_security_struct *sec = ib_sec;
6722*4882a593Smuzhiyun 	struct lsm_ibpkey_audit ibpkey;
6723*4882a593Smuzhiyun 
6724*4882a593Smuzhiyun 	err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
6725*4882a593Smuzhiyun 	if (err)
6726*4882a593Smuzhiyun 		return err;
6727*4882a593Smuzhiyun 
6728*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IBPKEY;
6729*4882a593Smuzhiyun 	ibpkey.subnet_prefix = subnet_prefix;
6730*4882a593Smuzhiyun 	ibpkey.pkey = pkey_val;
6731*4882a593Smuzhiyun 	ad.u.ibpkey = &ibpkey;
6732*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6733*4882a593Smuzhiyun 			    sec->sid, sid,
6734*4882a593Smuzhiyun 			    SECCLASS_INFINIBAND_PKEY,
6735*4882a593Smuzhiyun 			    INFINIBAND_PKEY__ACCESS, &ad);
6736*4882a593Smuzhiyun }
6737*4882a593Smuzhiyun 
selinux_ib_endport_manage_subnet(void * ib_sec,const char * dev_name,u8 port_num)6738*4882a593Smuzhiyun static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6739*4882a593Smuzhiyun 					    u8 port_num)
6740*4882a593Smuzhiyun {
6741*4882a593Smuzhiyun 	struct common_audit_data ad;
6742*4882a593Smuzhiyun 	int err;
6743*4882a593Smuzhiyun 	u32 sid = 0;
6744*4882a593Smuzhiyun 	struct ib_security_struct *sec = ib_sec;
6745*4882a593Smuzhiyun 	struct lsm_ibendport_audit ibendport;
6746*4882a593Smuzhiyun 
6747*4882a593Smuzhiyun 	err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
6748*4882a593Smuzhiyun 				      &sid);
6749*4882a593Smuzhiyun 
6750*4882a593Smuzhiyun 	if (err)
6751*4882a593Smuzhiyun 		return err;
6752*4882a593Smuzhiyun 
6753*4882a593Smuzhiyun 	ad.type = LSM_AUDIT_DATA_IBENDPORT;
6754*4882a593Smuzhiyun 	strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6755*4882a593Smuzhiyun 	ibendport.port = port_num;
6756*4882a593Smuzhiyun 	ad.u.ibendport = &ibendport;
6757*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6758*4882a593Smuzhiyun 			    sec->sid, sid,
6759*4882a593Smuzhiyun 			    SECCLASS_INFINIBAND_ENDPORT,
6760*4882a593Smuzhiyun 			    INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6761*4882a593Smuzhiyun }
6762*4882a593Smuzhiyun 
selinux_ib_alloc_security(void ** ib_sec)6763*4882a593Smuzhiyun static int selinux_ib_alloc_security(void **ib_sec)
6764*4882a593Smuzhiyun {
6765*4882a593Smuzhiyun 	struct ib_security_struct *sec;
6766*4882a593Smuzhiyun 
6767*4882a593Smuzhiyun 	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6768*4882a593Smuzhiyun 	if (!sec)
6769*4882a593Smuzhiyun 		return -ENOMEM;
6770*4882a593Smuzhiyun 	sec->sid = current_sid();
6771*4882a593Smuzhiyun 
6772*4882a593Smuzhiyun 	*ib_sec = sec;
6773*4882a593Smuzhiyun 	return 0;
6774*4882a593Smuzhiyun }
6775*4882a593Smuzhiyun 
selinux_ib_free_security(void * ib_sec)6776*4882a593Smuzhiyun static void selinux_ib_free_security(void *ib_sec)
6777*4882a593Smuzhiyun {
6778*4882a593Smuzhiyun 	kfree(ib_sec);
6779*4882a593Smuzhiyun }
6780*4882a593Smuzhiyun #endif
6781*4882a593Smuzhiyun 
6782*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
selinux_bpf(int cmd,union bpf_attr * attr,unsigned int size)6783*4882a593Smuzhiyun static int selinux_bpf(int cmd, union bpf_attr *attr,
6784*4882a593Smuzhiyun 				     unsigned int size)
6785*4882a593Smuzhiyun {
6786*4882a593Smuzhiyun 	u32 sid = current_sid();
6787*4882a593Smuzhiyun 	int ret;
6788*4882a593Smuzhiyun 
6789*4882a593Smuzhiyun 	switch (cmd) {
6790*4882a593Smuzhiyun 	case BPF_MAP_CREATE:
6791*4882a593Smuzhiyun 		ret = avc_has_perm(&selinux_state,
6792*4882a593Smuzhiyun 				   sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
6793*4882a593Smuzhiyun 				   NULL);
6794*4882a593Smuzhiyun 		break;
6795*4882a593Smuzhiyun 	case BPF_PROG_LOAD:
6796*4882a593Smuzhiyun 		ret = avc_has_perm(&selinux_state,
6797*4882a593Smuzhiyun 				   sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
6798*4882a593Smuzhiyun 				   NULL);
6799*4882a593Smuzhiyun 		break;
6800*4882a593Smuzhiyun 	default:
6801*4882a593Smuzhiyun 		ret = 0;
6802*4882a593Smuzhiyun 		break;
6803*4882a593Smuzhiyun 	}
6804*4882a593Smuzhiyun 
6805*4882a593Smuzhiyun 	return ret;
6806*4882a593Smuzhiyun }
6807*4882a593Smuzhiyun 
bpf_map_fmode_to_av(fmode_t fmode)6808*4882a593Smuzhiyun static u32 bpf_map_fmode_to_av(fmode_t fmode)
6809*4882a593Smuzhiyun {
6810*4882a593Smuzhiyun 	u32 av = 0;
6811*4882a593Smuzhiyun 
6812*4882a593Smuzhiyun 	if (fmode & FMODE_READ)
6813*4882a593Smuzhiyun 		av |= BPF__MAP_READ;
6814*4882a593Smuzhiyun 	if (fmode & FMODE_WRITE)
6815*4882a593Smuzhiyun 		av |= BPF__MAP_WRITE;
6816*4882a593Smuzhiyun 	return av;
6817*4882a593Smuzhiyun }
6818*4882a593Smuzhiyun 
6819*4882a593Smuzhiyun /* This function will check the file pass through unix socket or binder to see
6820*4882a593Smuzhiyun  * if it is a bpf related object. And apply correspinding checks on the bpf
6821*4882a593Smuzhiyun  * object based on the type. The bpf maps and programs, not like other files and
6822*4882a593Smuzhiyun  * socket, are using a shared anonymous inode inside the kernel as their inode.
6823*4882a593Smuzhiyun  * So checking that inode cannot identify if the process have privilege to
6824*4882a593Smuzhiyun  * access the bpf object and that's why we have to add this additional check in
6825*4882a593Smuzhiyun  * selinux_file_receive and selinux_binder_transfer_files.
6826*4882a593Smuzhiyun  */
bpf_fd_pass(struct file * file,u32 sid)6827*4882a593Smuzhiyun static int bpf_fd_pass(struct file *file, u32 sid)
6828*4882a593Smuzhiyun {
6829*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec;
6830*4882a593Smuzhiyun 	struct bpf_prog *prog;
6831*4882a593Smuzhiyun 	struct bpf_map *map;
6832*4882a593Smuzhiyun 	int ret;
6833*4882a593Smuzhiyun 
6834*4882a593Smuzhiyun 	if (file->f_op == &bpf_map_fops) {
6835*4882a593Smuzhiyun 		map = file->private_data;
6836*4882a593Smuzhiyun 		bpfsec = map->security;
6837*4882a593Smuzhiyun 		ret = avc_has_perm(&selinux_state,
6838*4882a593Smuzhiyun 				   sid, bpfsec->sid, SECCLASS_BPF,
6839*4882a593Smuzhiyun 				   bpf_map_fmode_to_av(file->f_mode), NULL);
6840*4882a593Smuzhiyun 		if (ret)
6841*4882a593Smuzhiyun 			return ret;
6842*4882a593Smuzhiyun 	} else if (file->f_op == &bpf_prog_fops) {
6843*4882a593Smuzhiyun 		prog = file->private_data;
6844*4882a593Smuzhiyun 		bpfsec = prog->aux->security;
6845*4882a593Smuzhiyun 		ret = avc_has_perm(&selinux_state,
6846*4882a593Smuzhiyun 				   sid, bpfsec->sid, SECCLASS_BPF,
6847*4882a593Smuzhiyun 				   BPF__PROG_RUN, NULL);
6848*4882a593Smuzhiyun 		if (ret)
6849*4882a593Smuzhiyun 			return ret;
6850*4882a593Smuzhiyun 	}
6851*4882a593Smuzhiyun 	return 0;
6852*4882a593Smuzhiyun }
6853*4882a593Smuzhiyun 
selinux_bpf_map(struct bpf_map * map,fmode_t fmode)6854*4882a593Smuzhiyun static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6855*4882a593Smuzhiyun {
6856*4882a593Smuzhiyun 	u32 sid = current_sid();
6857*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec;
6858*4882a593Smuzhiyun 
6859*4882a593Smuzhiyun 	bpfsec = map->security;
6860*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6861*4882a593Smuzhiyun 			    sid, bpfsec->sid, SECCLASS_BPF,
6862*4882a593Smuzhiyun 			    bpf_map_fmode_to_av(fmode), NULL);
6863*4882a593Smuzhiyun }
6864*4882a593Smuzhiyun 
selinux_bpf_prog(struct bpf_prog * prog)6865*4882a593Smuzhiyun static int selinux_bpf_prog(struct bpf_prog *prog)
6866*4882a593Smuzhiyun {
6867*4882a593Smuzhiyun 	u32 sid = current_sid();
6868*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec;
6869*4882a593Smuzhiyun 
6870*4882a593Smuzhiyun 	bpfsec = prog->aux->security;
6871*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state,
6872*4882a593Smuzhiyun 			    sid, bpfsec->sid, SECCLASS_BPF,
6873*4882a593Smuzhiyun 			    BPF__PROG_RUN, NULL);
6874*4882a593Smuzhiyun }
6875*4882a593Smuzhiyun 
selinux_bpf_map_alloc(struct bpf_map * map)6876*4882a593Smuzhiyun static int selinux_bpf_map_alloc(struct bpf_map *map)
6877*4882a593Smuzhiyun {
6878*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec;
6879*4882a593Smuzhiyun 
6880*4882a593Smuzhiyun 	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6881*4882a593Smuzhiyun 	if (!bpfsec)
6882*4882a593Smuzhiyun 		return -ENOMEM;
6883*4882a593Smuzhiyun 
6884*4882a593Smuzhiyun 	bpfsec->sid = current_sid();
6885*4882a593Smuzhiyun 	map->security = bpfsec;
6886*4882a593Smuzhiyun 
6887*4882a593Smuzhiyun 	return 0;
6888*4882a593Smuzhiyun }
6889*4882a593Smuzhiyun 
selinux_bpf_map_free(struct bpf_map * map)6890*4882a593Smuzhiyun static void selinux_bpf_map_free(struct bpf_map *map)
6891*4882a593Smuzhiyun {
6892*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec = map->security;
6893*4882a593Smuzhiyun 
6894*4882a593Smuzhiyun 	map->security = NULL;
6895*4882a593Smuzhiyun 	kfree(bpfsec);
6896*4882a593Smuzhiyun }
6897*4882a593Smuzhiyun 
selinux_bpf_prog_alloc(struct bpf_prog_aux * aux)6898*4882a593Smuzhiyun static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6899*4882a593Smuzhiyun {
6900*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec;
6901*4882a593Smuzhiyun 
6902*4882a593Smuzhiyun 	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6903*4882a593Smuzhiyun 	if (!bpfsec)
6904*4882a593Smuzhiyun 		return -ENOMEM;
6905*4882a593Smuzhiyun 
6906*4882a593Smuzhiyun 	bpfsec->sid = current_sid();
6907*4882a593Smuzhiyun 	aux->security = bpfsec;
6908*4882a593Smuzhiyun 
6909*4882a593Smuzhiyun 	return 0;
6910*4882a593Smuzhiyun }
6911*4882a593Smuzhiyun 
selinux_bpf_prog_free(struct bpf_prog_aux * aux)6912*4882a593Smuzhiyun static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6913*4882a593Smuzhiyun {
6914*4882a593Smuzhiyun 	struct bpf_security_struct *bpfsec = aux->security;
6915*4882a593Smuzhiyun 
6916*4882a593Smuzhiyun 	aux->security = NULL;
6917*4882a593Smuzhiyun 	kfree(bpfsec);
6918*4882a593Smuzhiyun }
6919*4882a593Smuzhiyun #endif
6920*4882a593Smuzhiyun 
6921*4882a593Smuzhiyun struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
6922*4882a593Smuzhiyun 	.lbs_cred = sizeof(struct task_security_struct),
6923*4882a593Smuzhiyun 	.lbs_file = sizeof(struct file_security_struct),
6924*4882a593Smuzhiyun 	.lbs_inode = sizeof(struct inode_security_struct),
6925*4882a593Smuzhiyun 	.lbs_ipc = sizeof(struct ipc_security_struct),
6926*4882a593Smuzhiyun 	.lbs_msg_msg = sizeof(struct msg_security_struct),
6927*4882a593Smuzhiyun };
6928*4882a593Smuzhiyun 
6929*4882a593Smuzhiyun #ifdef CONFIG_PERF_EVENTS
selinux_perf_event_open(struct perf_event_attr * attr,int type)6930*4882a593Smuzhiyun static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
6931*4882a593Smuzhiyun {
6932*4882a593Smuzhiyun 	u32 requested, sid = current_sid();
6933*4882a593Smuzhiyun 
6934*4882a593Smuzhiyun 	if (type == PERF_SECURITY_OPEN)
6935*4882a593Smuzhiyun 		requested = PERF_EVENT__OPEN;
6936*4882a593Smuzhiyun 	else if (type == PERF_SECURITY_CPU)
6937*4882a593Smuzhiyun 		requested = PERF_EVENT__CPU;
6938*4882a593Smuzhiyun 	else if (type == PERF_SECURITY_KERNEL)
6939*4882a593Smuzhiyun 		requested = PERF_EVENT__KERNEL;
6940*4882a593Smuzhiyun 	else if (type == PERF_SECURITY_TRACEPOINT)
6941*4882a593Smuzhiyun 		requested = PERF_EVENT__TRACEPOINT;
6942*4882a593Smuzhiyun 	else
6943*4882a593Smuzhiyun 		return -EINVAL;
6944*4882a593Smuzhiyun 
6945*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
6946*4882a593Smuzhiyun 			    requested, NULL);
6947*4882a593Smuzhiyun }
6948*4882a593Smuzhiyun 
selinux_perf_event_alloc(struct perf_event * event)6949*4882a593Smuzhiyun static int selinux_perf_event_alloc(struct perf_event *event)
6950*4882a593Smuzhiyun {
6951*4882a593Smuzhiyun 	struct perf_event_security_struct *perfsec;
6952*4882a593Smuzhiyun 
6953*4882a593Smuzhiyun 	perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
6954*4882a593Smuzhiyun 	if (!perfsec)
6955*4882a593Smuzhiyun 		return -ENOMEM;
6956*4882a593Smuzhiyun 
6957*4882a593Smuzhiyun 	perfsec->sid = current_sid();
6958*4882a593Smuzhiyun 	event->security = perfsec;
6959*4882a593Smuzhiyun 
6960*4882a593Smuzhiyun 	return 0;
6961*4882a593Smuzhiyun }
6962*4882a593Smuzhiyun 
selinux_perf_event_free(struct perf_event * event)6963*4882a593Smuzhiyun static void selinux_perf_event_free(struct perf_event *event)
6964*4882a593Smuzhiyun {
6965*4882a593Smuzhiyun 	struct perf_event_security_struct *perfsec = event->security;
6966*4882a593Smuzhiyun 
6967*4882a593Smuzhiyun 	event->security = NULL;
6968*4882a593Smuzhiyun 	kfree(perfsec);
6969*4882a593Smuzhiyun }
6970*4882a593Smuzhiyun 
selinux_perf_event_read(struct perf_event * event)6971*4882a593Smuzhiyun static int selinux_perf_event_read(struct perf_event *event)
6972*4882a593Smuzhiyun {
6973*4882a593Smuzhiyun 	struct perf_event_security_struct *perfsec = event->security;
6974*4882a593Smuzhiyun 	u32 sid = current_sid();
6975*4882a593Smuzhiyun 
6976*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state, sid, perfsec->sid,
6977*4882a593Smuzhiyun 			    SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
6978*4882a593Smuzhiyun }
6979*4882a593Smuzhiyun 
selinux_perf_event_write(struct perf_event * event)6980*4882a593Smuzhiyun static int selinux_perf_event_write(struct perf_event *event)
6981*4882a593Smuzhiyun {
6982*4882a593Smuzhiyun 	struct perf_event_security_struct *perfsec = event->security;
6983*4882a593Smuzhiyun 	u32 sid = current_sid();
6984*4882a593Smuzhiyun 
6985*4882a593Smuzhiyun 	return avc_has_perm(&selinux_state, sid, perfsec->sid,
6986*4882a593Smuzhiyun 			    SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
6987*4882a593Smuzhiyun }
6988*4882a593Smuzhiyun #endif
6989*4882a593Smuzhiyun 
6990*4882a593Smuzhiyun /*
6991*4882a593Smuzhiyun  * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
6992*4882a593Smuzhiyun  * 1. any hooks that don't belong to (2.) or (3.) below,
6993*4882a593Smuzhiyun  * 2. hooks that both access structures allocated by other hooks, and allocate
6994*4882a593Smuzhiyun  *    structures that can be later accessed by other hooks (mostly "cloning"
6995*4882a593Smuzhiyun  *    hooks),
6996*4882a593Smuzhiyun  * 3. hooks that only allocate structures that can be later accessed by other
6997*4882a593Smuzhiyun  *    hooks ("allocating" hooks).
6998*4882a593Smuzhiyun  *
6999*4882a593Smuzhiyun  * Please follow block comment delimiters in the list to keep this order.
7000*4882a593Smuzhiyun  *
7001*4882a593Smuzhiyun  * This ordering is needed for SELinux runtime disable to work at least somewhat
7002*4882a593Smuzhiyun  * safely. Breaking the ordering rules above might lead to NULL pointer derefs
7003*4882a593Smuzhiyun  * when disabling SELinux at runtime.
7004*4882a593Smuzhiyun  */
7005*4882a593Smuzhiyun static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
7006*4882a593Smuzhiyun 	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
7007*4882a593Smuzhiyun 	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
7008*4882a593Smuzhiyun 	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
7009*4882a593Smuzhiyun 	LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
7010*4882a593Smuzhiyun 
7011*4882a593Smuzhiyun 	LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
7012*4882a593Smuzhiyun 	LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
7013*4882a593Smuzhiyun 	LSM_HOOK_INIT(capget, selinux_capget),
7014*4882a593Smuzhiyun 	LSM_HOOK_INIT(capset, selinux_capset),
7015*4882a593Smuzhiyun 	LSM_HOOK_INIT(capable, selinux_capable),
7016*4882a593Smuzhiyun 	LSM_HOOK_INIT(quotactl, selinux_quotactl),
7017*4882a593Smuzhiyun 	LSM_HOOK_INIT(quota_on, selinux_quota_on),
7018*4882a593Smuzhiyun 	LSM_HOOK_INIT(syslog, selinux_syslog),
7019*4882a593Smuzhiyun 	LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
7020*4882a593Smuzhiyun 
7021*4882a593Smuzhiyun 	LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
7022*4882a593Smuzhiyun 
7023*4882a593Smuzhiyun 	LSM_HOOK_INIT(bprm_creds_for_exec, selinux_bprm_creds_for_exec),
7024*4882a593Smuzhiyun 	LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
7025*4882a593Smuzhiyun 	LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
7026*4882a593Smuzhiyun 
7027*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
7028*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
7029*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
7030*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
7031*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
7032*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
7033*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_mount, selinux_mount),
7034*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_umount, selinux_umount),
7035*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
7036*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
7037*4882a593Smuzhiyun 
7038*4882a593Smuzhiyun 	LSM_HOOK_INIT(move_mount, selinux_move_mount),
7039*4882a593Smuzhiyun 
7040*4882a593Smuzhiyun 	LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
7041*4882a593Smuzhiyun 	LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
7042*4882a593Smuzhiyun 
7043*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
7044*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
7045*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_init_security_anon, selinux_inode_init_security_anon),
7046*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_create, selinux_inode_create),
7047*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_link, selinux_inode_link),
7048*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
7049*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
7050*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
7051*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
7052*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
7053*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
7054*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
7055*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
7056*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
7057*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
7058*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
7059*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
7060*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
7061*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
7062*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
7063*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
7064*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
7065*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
7066*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
7067*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
7068*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
7069*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
7070*4882a593Smuzhiyun 	LSM_HOOK_INIT(path_notify, selinux_path_notify),
7071*4882a593Smuzhiyun 
7072*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
7073*4882a593Smuzhiyun 
7074*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_permission, selinux_file_permission),
7075*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
7076*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
7077*4882a593Smuzhiyun 	LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
7078*4882a593Smuzhiyun 	LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
7079*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
7080*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_lock, selinux_file_lock),
7081*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
7082*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
7083*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
7084*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_receive, selinux_file_receive),
7085*4882a593Smuzhiyun 
7086*4882a593Smuzhiyun 	LSM_HOOK_INIT(file_open, selinux_file_open),
7087*4882a593Smuzhiyun 
7088*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
7089*4882a593Smuzhiyun 	LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
7090*4882a593Smuzhiyun 	LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
7091*4882a593Smuzhiyun 	LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
7092*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
7093*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
7094*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
7095*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
7096*4882a593Smuzhiyun 	LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
7097*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
7098*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
7099*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
7100*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
7101*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
7102*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
7103*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
7104*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
7105*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
7106*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
7107*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
7108*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
7109*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_kill, selinux_task_kill),
7110*4882a593Smuzhiyun 	LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
7111*4882a593Smuzhiyun 
7112*4882a593Smuzhiyun 	LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
7113*4882a593Smuzhiyun 	LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
7114*4882a593Smuzhiyun 
7115*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
7116*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
7117*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
7118*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
7119*4882a593Smuzhiyun 
7120*4882a593Smuzhiyun 	LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
7121*4882a593Smuzhiyun 	LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
7122*4882a593Smuzhiyun 	LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
7123*4882a593Smuzhiyun 
7124*4882a593Smuzhiyun 	LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
7125*4882a593Smuzhiyun 	LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
7126*4882a593Smuzhiyun 	LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
7127*4882a593Smuzhiyun 
7128*4882a593Smuzhiyun 	LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
7129*4882a593Smuzhiyun 
7130*4882a593Smuzhiyun 	LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
7131*4882a593Smuzhiyun 	LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
7132*4882a593Smuzhiyun 
7133*4882a593Smuzhiyun 	LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
7134*4882a593Smuzhiyun 	LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
7135*4882a593Smuzhiyun 	LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
7136*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
7137*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
7138*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
7139*4882a593Smuzhiyun 
7140*4882a593Smuzhiyun 	LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
7141*4882a593Smuzhiyun 	LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
7142*4882a593Smuzhiyun 
7143*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_create, selinux_socket_create),
7144*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
7145*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
7146*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
7147*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
7148*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
7149*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
7150*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
7151*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
7152*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
7153*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
7154*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
7155*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
7156*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
7157*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
7158*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_getpeersec_stream,
7159*4882a593Smuzhiyun 			selinux_socket_getpeersec_stream),
7160*4882a593Smuzhiyun 	LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
7161*4882a593Smuzhiyun 	LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
7162*4882a593Smuzhiyun 	LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
7163*4882a593Smuzhiyun 	LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
7164*4882a593Smuzhiyun 	LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
7165*4882a593Smuzhiyun 	LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
7166*4882a593Smuzhiyun 	LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
7167*4882a593Smuzhiyun 	LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
7168*4882a593Smuzhiyun 	LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
7169*4882a593Smuzhiyun 	LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
7170*4882a593Smuzhiyun 	LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
7171*4882a593Smuzhiyun 	LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
7172*4882a593Smuzhiyun 	LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
7173*4882a593Smuzhiyun 	LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
7174*4882a593Smuzhiyun 	LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
7175*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
7176*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
7177*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
7178*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
7179*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
7180*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_INFINIBAND
7181*4882a593Smuzhiyun 	LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
7182*4882a593Smuzhiyun 	LSM_HOOK_INIT(ib_endport_manage_subnet,
7183*4882a593Smuzhiyun 		      selinux_ib_endport_manage_subnet),
7184*4882a593Smuzhiyun 	LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
7185*4882a593Smuzhiyun #endif
7186*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_NETWORK_XFRM
7187*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
7188*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
7189*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
7190*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
7191*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
7192*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_state_pol_flow_match,
7193*4882a593Smuzhiyun 			selinux_xfrm_state_pol_flow_match),
7194*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
7195*4882a593Smuzhiyun #endif
7196*4882a593Smuzhiyun 
7197*4882a593Smuzhiyun #ifdef CONFIG_KEYS
7198*4882a593Smuzhiyun 	LSM_HOOK_INIT(key_free, selinux_key_free),
7199*4882a593Smuzhiyun 	LSM_HOOK_INIT(key_permission, selinux_key_permission),
7200*4882a593Smuzhiyun 	LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
7201*4882a593Smuzhiyun #ifdef CONFIG_KEY_NOTIFICATIONS
7202*4882a593Smuzhiyun 	LSM_HOOK_INIT(watch_key, selinux_watch_key),
7203*4882a593Smuzhiyun #endif
7204*4882a593Smuzhiyun #endif
7205*4882a593Smuzhiyun 
7206*4882a593Smuzhiyun #ifdef CONFIG_AUDIT
7207*4882a593Smuzhiyun 	LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
7208*4882a593Smuzhiyun 	LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
7209*4882a593Smuzhiyun 	LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
7210*4882a593Smuzhiyun #endif
7211*4882a593Smuzhiyun 
7212*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
7213*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf, selinux_bpf),
7214*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
7215*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
7216*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
7217*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
7218*4882a593Smuzhiyun #endif
7219*4882a593Smuzhiyun 
7220*4882a593Smuzhiyun #ifdef CONFIG_PERF_EVENTS
7221*4882a593Smuzhiyun 	LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
7222*4882a593Smuzhiyun 	LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
7223*4882a593Smuzhiyun 	LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
7224*4882a593Smuzhiyun 	LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
7225*4882a593Smuzhiyun #endif
7226*4882a593Smuzhiyun 
7227*4882a593Smuzhiyun 	/*
7228*4882a593Smuzhiyun 	 * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE
7229*4882a593Smuzhiyun 	 */
7230*4882a593Smuzhiyun 	LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
7231*4882a593Smuzhiyun 	LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
7232*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
7233*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_add_mnt_opt, selinux_add_mnt_opt),
7234*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_NETWORK_XFRM
7235*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
7236*4882a593Smuzhiyun #endif
7237*4882a593Smuzhiyun 
7238*4882a593Smuzhiyun 	/*
7239*4882a593Smuzhiyun 	 * PUT "ALLOCATING" HOOKS HERE
7240*4882a593Smuzhiyun 	 */
7241*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
7242*4882a593Smuzhiyun 	LSM_HOOK_INIT(msg_queue_alloc_security,
7243*4882a593Smuzhiyun 		      selinux_msg_queue_alloc_security),
7244*4882a593Smuzhiyun 	LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
7245*4882a593Smuzhiyun 	LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
7246*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
7247*4882a593Smuzhiyun 	LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
7248*4882a593Smuzhiyun 	LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
7249*4882a593Smuzhiyun 	LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
7250*4882a593Smuzhiyun 	LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
7251*4882a593Smuzhiyun 	LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
7252*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_INFINIBAND
7253*4882a593Smuzhiyun 	LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
7254*4882a593Smuzhiyun #endif
7255*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_NETWORK_XFRM
7256*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
7257*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
7258*4882a593Smuzhiyun 	LSM_HOOK_INIT(xfrm_state_alloc_acquire,
7259*4882a593Smuzhiyun 		      selinux_xfrm_state_alloc_acquire),
7260*4882a593Smuzhiyun #endif
7261*4882a593Smuzhiyun #ifdef CONFIG_KEYS
7262*4882a593Smuzhiyun 	LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
7263*4882a593Smuzhiyun #endif
7264*4882a593Smuzhiyun #ifdef CONFIG_AUDIT
7265*4882a593Smuzhiyun 	LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
7266*4882a593Smuzhiyun #endif
7267*4882a593Smuzhiyun #ifdef CONFIG_BPF_SYSCALL
7268*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
7269*4882a593Smuzhiyun 	LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
7270*4882a593Smuzhiyun #endif
7271*4882a593Smuzhiyun #ifdef CONFIG_PERF_EVENTS
7272*4882a593Smuzhiyun 	LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
7273*4882a593Smuzhiyun #endif
7274*4882a593Smuzhiyun };
7275*4882a593Smuzhiyun 
selinux_init(void)7276*4882a593Smuzhiyun static __init int selinux_init(void)
7277*4882a593Smuzhiyun {
7278*4882a593Smuzhiyun 	pr_info("SELinux:  Initializing.\n");
7279*4882a593Smuzhiyun 
7280*4882a593Smuzhiyun 	memset(&selinux_state, 0, sizeof(selinux_state));
7281*4882a593Smuzhiyun 	enforcing_set(&selinux_state, selinux_enforcing_boot);
7282*4882a593Smuzhiyun 	checkreqprot_set(&selinux_state, selinux_checkreqprot_boot);
7283*4882a593Smuzhiyun 	selinux_avc_init(&selinux_state.avc);
7284*4882a593Smuzhiyun 	mutex_init(&selinux_state.status_lock);
7285*4882a593Smuzhiyun 	mutex_init(&selinux_state.policy_mutex);
7286*4882a593Smuzhiyun 
7287*4882a593Smuzhiyun 	/* Set the security state for the initial task. */
7288*4882a593Smuzhiyun 	cred_init_security();
7289*4882a593Smuzhiyun 
7290*4882a593Smuzhiyun 	default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
7291*4882a593Smuzhiyun 
7292*4882a593Smuzhiyun 	avc_init();
7293*4882a593Smuzhiyun 
7294*4882a593Smuzhiyun 	avtab_cache_init();
7295*4882a593Smuzhiyun 
7296*4882a593Smuzhiyun 	ebitmap_cache_init();
7297*4882a593Smuzhiyun 
7298*4882a593Smuzhiyun 	hashtab_cache_init();
7299*4882a593Smuzhiyun 
7300*4882a593Smuzhiyun 	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
7301*4882a593Smuzhiyun 
7302*4882a593Smuzhiyun 	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
7303*4882a593Smuzhiyun 		panic("SELinux: Unable to register AVC netcache callback\n");
7304*4882a593Smuzhiyun 
7305*4882a593Smuzhiyun 	if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
7306*4882a593Smuzhiyun 		panic("SELinux: Unable to register AVC LSM notifier callback\n");
7307*4882a593Smuzhiyun 
7308*4882a593Smuzhiyun 	if (selinux_enforcing_boot)
7309*4882a593Smuzhiyun 		pr_debug("SELinux:  Starting in enforcing mode\n");
7310*4882a593Smuzhiyun 	else
7311*4882a593Smuzhiyun 		pr_debug("SELinux:  Starting in permissive mode\n");
7312*4882a593Smuzhiyun 
7313*4882a593Smuzhiyun 	fs_validate_description("selinux", selinux_fs_parameters);
7314*4882a593Smuzhiyun 
7315*4882a593Smuzhiyun 	return 0;
7316*4882a593Smuzhiyun }
7317*4882a593Smuzhiyun 
delayed_superblock_init(struct super_block * sb,void * unused)7318*4882a593Smuzhiyun static void delayed_superblock_init(struct super_block *sb, void *unused)
7319*4882a593Smuzhiyun {
7320*4882a593Smuzhiyun 	selinux_set_mnt_opts(sb, NULL, 0, NULL);
7321*4882a593Smuzhiyun }
7322*4882a593Smuzhiyun 
selinux_complete_init(void)7323*4882a593Smuzhiyun void selinux_complete_init(void)
7324*4882a593Smuzhiyun {
7325*4882a593Smuzhiyun 	pr_debug("SELinux:  Completing initialization.\n");
7326*4882a593Smuzhiyun 
7327*4882a593Smuzhiyun 	/* Set up any superblocks initialized prior to the policy load. */
7328*4882a593Smuzhiyun 	pr_debug("SELinux:  Setting up existing superblocks.\n");
7329*4882a593Smuzhiyun 	iterate_supers(delayed_superblock_init, NULL);
7330*4882a593Smuzhiyun }
7331*4882a593Smuzhiyun 
7332*4882a593Smuzhiyun /* SELinux requires early initialization in order to label
7333*4882a593Smuzhiyun    all processes and objects when they are created. */
7334*4882a593Smuzhiyun DEFINE_LSM(selinux) = {
7335*4882a593Smuzhiyun 	.name = "selinux",
7336*4882a593Smuzhiyun 	.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
7337*4882a593Smuzhiyun 	.enabled = &selinux_enabled_boot,
7338*4882a593Smuzhiyun 	.blobs = &selinux_blob_sizes,
7339*4882a593Smuzhiyun 	.init = selinux_init,
7340*4882a593Smuzhiyun };
7341*4882a593Smuzhiyun 
7342*4882a593Smuzhiyun #if defined(CONFIG_NETFILTER)
7343*4882a593Smuzhiyun 
7344*4882a593Smuzhiyun static const struct nf_hook_ops selinux_nf_ops[] = {
7345*4882a593Smuzhiyun 	{
7346*4882a593Smuzhiyun 		.hook =		selinux_ipv4_postroute,
7347*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV4,
7348*4882a593Smuzhiyun 		.hooknum =	NF_INET_POST_ROUTING,
7349*4882a593Smuzhiyun 		.priority =	NF_IP_PRI_SELINUX_LAST,
7350*4882a593Smuzhiyun 	},
7351*4882a593Smuzhiyun 	{
7352*4882a593Smuzhiyun 		.hook =		selinux_ipv4_forward,
7353*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV4,
7354*4882a593Smuzhiyun 		.hooknum =	NF_INET_FORWARD,
7355*4882a593Smuzhiyun 		.priority =	NF_IP_PRI_SELINUX_FIRST,
7356*4882a593Smuzhiyun 	},
7357*4882a593Smuzhiyun 	{
7358*4882a593Smuzhiyun 		.hook =		selinux_ipv4_output,
7359*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV4,
7360*4882a593Smuzhiyun 		.hooknum =	NF_INET_LOCAL_OUT,
7361*4882a593Smuzhiyun 		.priority =	NF_IP_PRI_SELINUX_FIRST,
7362*4882a593Smuzhiyun 	},
7363*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
7364*4882a593Smuzhiyun 	{
7365*4882a593Smuzhiyun 		.hook =		selinux_ipv6_postroute,
7366*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV6,
7367*4882a593Smuzhiyun 		.hooknum =	NF_INET_POST_ROUTING,
7368*4882a593Smuzhiyun 		.priority =	NF_IP6_PRI_SELINUX_LAST,
7369*4882a593Smuzhiyun 	},
7370*4882a593Smuzhiyun 	{
7371*4882a593Smuzhiyun 		.hook =		selinux_ipv6_forward,
7372*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV6,
7373*4882a593Smuzhiyun 		.hooknum =	NF_INET_FORWARD,
7374*4882a593Smuzhiyun 		.priority =	NF_IP6_PRI_SELINUX_FIRST,
7375*4882a593Smuzhiyun 	},
7376*4882a593Smuzhiyun 	{
7377*4882a593Smuzhiyun 		.hook =		selinux_ipv6_output,
7378*4882a593Smuzhiyun 		.pf =		NFPROTO_IPV6,
7379*4882a593Smuzhiyun 		.hooknum =	NF_INET_LOCAL_OUT,
7380*4882a593Smuzhiyun 		.priority =	NF_IP6_PRI_SELINUX_FIRST,
7381*4882a593Smuzhiyun 	},
7382*4882a593Smuzhiyun #endif	/* IPV6 */
7383*4882a593Smuzhiyun };
7384*4882a593Smuzhiyun 
selinux_nf_register(struct net * net)7385*4882a593Smuzhiyun static int __net_init selinux_nf_register(struct net *net)
7386*4882a593Smuzhiyun {
7387*4882a593Smuzhiyun 	return nf_register_net_hooks(net, selinux_nf_ops,
7388*4882a593Smuzhiyun 				     ARRAY_SIZE(selinux_nf_ops));
7389*4882a593Smuzhiyun }
7390*4882a593Smuzhiyun 
selinux_nf_unregister(struct net * net)7391*4882a593Smuzhiyun static void __net_exit selinux_nf_unregister(struct net *net)
7392*4882a593Smuzhiyun {
7393*4882a593Smuzhiyun 	nf_unregister_net_hooks(net, selinux_nf_ops,
7394*4882a593Smuzhiyun 				ARRAY_SIZE(selinux_nf_ops));
7395*4882a593Smuzhiyun }
7396*4882a593Smuzhiyun 
7397*4882a593Smuzhiyun static struct pernet_operations selinux_net_ops = {
7398*4882a593Smuzhiyun 	.init = selinux_nf_register,
7399*4882a593Smuzhiyun 	.exit = selinux_nf_unregister,
7400*4882a593Smuzhiyun };
7401*4882a593Smuzhiyun 
selinux_nf_ip_init(void)7402*4882a593Smuzhiyun static int __init selinux_nf_ip_init(void)
7403*4882a593Smuzhiyun {
7404*4882a593Smuzhiyun 	int err;
7405*4882a593Smuzhiyun 
7406*4882a593Smuzhiyun 	if (!selinux_enabled_boot)
7407*4882a593Smuzhiyun 		return 0;
7408*4882a593Smuzhiyun 
7409*4882a593Smuzhiyun 	pr_debug("SELinux:  Registering netfilter hooks\n");
7410*4882a593Smuzhiyun 
7411*4882a593Smuzhiyun 	err = register_pernet_subsys(&selinux_net_ops);
7412*4882a593Smuzhiyun 	if (err)
7413*4882a593Smuzhiyun 		panic("SELinux: register_pernet_subsys: error %d\n", err);
7414*4882a593Smuzhiyun 
7415*4882a593Smuzhiyun 	return 0;
7416*4882a593Smuzhiyun }
7417*4882a593Smuzhiyun __initcall(selinux_nf_ip_init);
7418*4882a593Smuzhiyun 
7419*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_SELINUX_DISABLE
selinux_nf_ip_exit(void)7420*4882a593Smuzhiyun static void selinux_nf_ip_exit(void)
7421*4882a593Smuzhiyun {
7422*4882a593Smuzhiyun 	pr_debug("SELinux:  Unregistering netfilter hooks\n");
7423*4882a593Smuzhiyun 
7424*4882a593Smuzhiyun 	unregister_pernet_subsys(&selinux_net_ops);
7425*4882a593Smuzhiyun }
7426*4882a593Smuzhiyun #endif
7427*4882a593Smuzhiyun 
7428*4882a593Smuzhiyun #else /* CONFIG_NETFILTER */
7429*4882a593Smuzhiyun 
7430*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_SELINUX_DISABLE
7431*4882a593Smuzhiyun #define selinux_nf_ip_exit()
7432*4882a593Smuzhiyun #endif
7433*4882a593Smuzhiyun 
7434*4882a593Smuzhiyun #endif /* CONFIG_NETFILTER */
7435*4882a593Smuzhiyun 
7436*4882a593Smuzhiyun #ifdef CONFIG_SECURITY_SELINUX_DISABLE
selinux_disable(struct selinux_state * state)7437*4882a593Smuzhiyun int selinux_disable(struct selinux_state *state)
7438*4882a593Smuzhiyun {
7439*4882a593Smuzhiyun 	if (selinux_initialized(state)) {
7440*4882a593Smuzhiyun 		/* Not permitted after initial policy load. */
7441*4882a593Smuzhiyun 		return -EINVAL;
7442*4882a593Smuzhiyun 	}
7443*4882a593Smuzhiyun 
7444*4882a593Smuzhiyun 	if (selinux_disabled(state)) {
7445*4882a593Smuzhiyun 		/* Only do this once. */
7446*4882a593Smuzhiyun 		return -EINVAL;
7447*4882a593Smuzhiyun 	}
7448*4882a593Smuzhiyun 
7449*4882a593Smuzhiyun 	selinux_mark_disabled(state);
7450*4882a593Smuzhiyun 
7451*4882a593Smuzhiyun 	pr_info("SELinux:  Disabled at runtime.\n");
7452*4882a593Smuzhiyun 
7453*4882a593Smuzhiyun 	/*
7454*4882a593Smuzhiyun 	 * Unregister netfilter hooks.
7455*4882a593Smuzhiyun 	 * Must be done before security_delete_hooks() to avoid breaking
7456*4882a593Smuzhiyun 	 * runtime disable.
7457*4882a593Smuzhiyun 	 */
7458*4882a593Smuzhiyun 	selinux_nf_ip_exit();
7459*4882a593Smuzhiyun 
7460*4882a593Smuzhiyun 	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
7461*4882a593Smuzhiyun 
7462*4882a593Smuzhiyun 	/* Try to destroy the avc node cache */
7463*4882a593Smuzhiyun 	avc_disable();
7464*4882a593Smuzhiyun 
7465*4882a593Smuzhiyun 	/* Unregister selinuxfs. */
7466*4882a593Smuzhiyun 	exit_sel_fs();
7467*4882a593Smuzhiyun 
7468*4882a593Smuzhiyun 	return 0;
7469*4882a593Smuzhiyun }
7470*4882a593Smuzhiyun #endif
7471