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(¤t->sighand->siglock);
2546*4882a593Smuzhiyun if (!fatal_signal_pending(current)) {
2547*4882a593Smuzhiyun flush_sigqueue(¤t->pending);
2548*4882a593Smuzhiyun flush_sigqueue(¤t->signal->shared_pending);
2549*4882a593Smuzhiyun flush_signal_handlers(current, 1);
2550*4882a593Smuzhiyun sigemptyset(¤t->blocked);
2551*4882a593Smuzhiyun recalc_sigpending();
2552*4882a593Smuzhiyun }
2553*4882a593Smuzhiyun spin_unlock_irq(¤t->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