blob: f2b272c9eaf389889304c2e0d68339871fb11a0b [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * NSA Security-Enhanced Linux (SELinux) security module
4 *
5 * This file contains the SELinux hook function implementations.
6 *
Stephen Smalley7efbb602017-08-17 13:32:36 -04007 * Authors: Stephen Smalley, <sds@tycho.nsa.gov>
Eric Paris828dfe12008-04-17 13:17:49 -04008 * Chris Vance, <cvance@nai.com>
9 * Wayne Salamon, <wsalamon@nai.com>
10 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
12 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100013 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
14 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040016 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040017 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000018 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090019 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040020 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Daniel Jurgens3a976fa2017-05-19 15:48:56 +030021 * Copyright (C) 2016 Mellanox Technologies
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050025#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/kernel.h>
Scott Brandenb89999d02020-10-02 10:38:15 -070027#include <linux/kernel_read_file.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070028#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/errno.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010030#include <linux/sched/signal.h>
Ingo Molnar29930022017-02-08 18:51:36 +010031#include <linux/sched/task.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
David Howells442155c2018-11-01 23:07:24 +000049#include <linux/fs_context.h>
50#include <linux/fs_parser.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/netfilter_ipv4.h>
52#include <linux/netfilter_ipv6.h>
53#include <linux/tty.h>
54#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070055#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050057#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050058#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050059#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040060#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070062#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#include <linux/bitops.h>
64#include <linux/interrupt.h>
65#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000066#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include <linux/tcp.h>
68#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080069#include <linux/dccp.h>
Richard Hainesd4529302018-02-13 20:57:18 +000070#include <linux/sctp.h>
71#include <net/sctp/structs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#include <linux/quota.h>
73#include <linux/un.h> /* for Unix socket types */
74#include <net/af_unix.h> /* for Unix socket types */
75#include <linux/parser.h>
76#include <linux/nfs_mount.h>
77#include <net/ipv6.h>
78#include <linux/hugetlb.h>
79#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070081#include <linux/string.h>
Eric Paris23970742006-09-25 23:32:01 -070082#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070083#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080084#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070085#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040086#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000087#include <linux/msg.h>
88#include <linux/shm.h>
Chenbo Fengec27c352017-10-18 13:00:25 -070089#include <linux/bpf.h>
Ondrej Mosnacekec882da2019-02-22 15:57:17 +010090#include <linux/kernfs.h>
91#include <linux/stringhash.h> /* for hashlen_string() */
David Howellse262e32d2018-11-01 23:07:23 +000092#include <uapi/linux/mount.h>
Aaron Goidelac5656d2019-08-12 11:20:00 -040093#include <linux/fsnotify.h>
94#include <linux/fanotify.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
96#include "avc.h"
97#include "objsec.h"
98#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050099#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -0400100#include "netport.h"
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300101#include "ibpkey.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -0800102#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -0500103#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +0200104#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +1000105#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500107struct selinux_state selinux_state;
108
Paul Moored621d352008-01-29 08:43:36 -0500109/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000110static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500113static int selinux_enforcing_boot __initdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
115static int __init enforcing_setup(char *str)
116{
Eric Parisf5269712008-05-14 11:27:45 -0400117 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900118 if (!kstrtoul(str, 0, &enforcing))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500119 selinux_enforcing_boot = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 return 1;
121}
122__setup("enforcing=", enforcing_setup);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500123#else
124#define selinux_enforcing_boot 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#endif
126
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500127int selinux_enabled_boot __initdata = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129static int __init selinux_enabled_setup(char *str)
130{
Eric Parisf5269712008-05-14 11:27:45 -0400131 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900132 if (!kstrtoul(str, 0, &enabled))
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500133 selinux_enabled_boot = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 return 1;
135}
136__setup("selinux=", selinux_enabled_setup);
137#endif
138
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500139static unsigned int selinux_checkreqprot_boot =
140 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
141
142static int __init checkreqprot_setup(char *str)
143{
144 unsigned long checkreqprot;
145
Stephen Smalleye9c38f92020-01-08 11:24:47 -0500146 if (!kstrtoul(str, 0, &checkreqprot)) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500147 selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
Stephen Smalleye9c38f92020-01-08 11:24:47 -0500148 if (checkreqprot)
149 pr_warn("SELinux: checkreqprot set to 1 via kernel parameter. This is deprecated and will be rejected in a future kernel release.\n");
150 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500151 return 1;
152}
153__setup("checkreqprot=", checkreqprot_setup);
154
Paul Moored621d352008-01-29 08:43:36 -0500155/**
156 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
157 *
158 * Description:
159 * This function checks the SECMARK reference counter to see if any SECMARK
160 * targets are currently configured, if the reference counter is greater than
161 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400162 * enabled, false (0) if SECMARK is disabled. If the always_check_network
163 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500164 *
165 */
166static int selinux_secmark_enabled(void)
167{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500168 return (selinux_policycap_alwaysnetwork() ||
169 atomic_read(&selinux_secmark_refcount));
Chris PeBenito2be4d742013-05-03 09:05:39 -0400170}
171
172/**
173 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
174 *
175 * Description:
176 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
177 * (1) if any are enabled or false (0) if neither are enabled. If the
178 * always_check_network policy capability is enabled, peer labeling
179 * is always considered enabled.
180 *
181 */
182static int selinux_peerlbl_enabled(void)
183{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500184 return (selinux_policycap_alwaysnetwork() ||
185 netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500186}
187
Paul Moore615e51f2014-06-26 14:33:56 -0400188static int selinux_netcache_avc_callback(u32 event)
189{
190 if (event == AVC_CALLBACK_RESET) {
191 sel_netif_flush();
192 sel_netnode_flush();
193 sel_netport_flush();
194 synchronize_net();
195 }
196 return 0;
197}
198
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300199static int selinux_lsm_notifier_avc_callback(u32 event)
200{
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300201 if (event == AVC_CALLBACK_RESET) {
202 sel_ib_pkey_flush();
Janne Karhunen42df7442019-06-14 15:20:14 +0300203 call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300204 }
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300205
206 return 0;
207}
208
David Howellsd84f4f92008-11-14 10:39:23 +1100209/*
210 * initialise the security for the init task
211 */
212static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213{
David Howells3b11a1d2008-11-14 10:39:26 +1100214 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 struct task_security_struct *tsec;
216
Casey Schauflerbbd36622018-11-12 09:30:56 -0800217 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +1100218 tsec->osid = tsec->sid = SECINITSID_KERNEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219}
220
David Howells275bb412008-11-14 10:39:19 +1100221/*
David Howells88e67f32008-11-14 10:39:21 +1100222 * get the security ID of a set of credentials
223 */
224static inline u32 cred_sid(const struct cred *cred)
225{
226 const struct task_security_struct *tsec;
227
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700228 tsec = selinux_cred(cred);
David Howells88e67f32008-11-14 10:39:21 +1100229 return tsec->sid;
230}
231
232/*
David Howells3b11a1d2008-11-14 10:39:26 +1100233 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100234 */
235static inline u32 task_sid(const struct task_struct *task)
236{
David Howells275bb412008-11-14 10:39:19 +1100237 u32 sid;
238
239 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100240 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100241 rcu_read_unlock();
242 return sid;
243}
244
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500245static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
246
247/*
248 * Try reloading inode security labels that have been marked as invalid. The
249 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100250 * allowed; when set to false, returns -ECHILD when the label is
Al Viroe9193282018-04-24 21:31:02 -0400251 * invalid. The @dentry parameter should be set to a dentry of the inode.
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500252 */
253static int __inode_security_revalidate(struct inode *inode,
Al Viroe9193282018-04-24 21:31:02 -0400254 struct dentry *dentry,
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500255 bool may_sleep)
256{
Casey Schaufler80788c22018-09-21 17:19:11 -0700257 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500258
259 might_sleep_if(may_sleep);
260
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100261 if (selinux_initialized(&selinux_state) &&
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500262 isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500263 if (!may_sleep)
264 return -ECHILD;
265
266 /*
267 * Try reloading the inode security label. This will fail if
268 * @opt_dentry is NULL and no dentry for this inode can be
269 * found; in that case, continue using the old label.
270 */
Al Viroe9193282018-04-24 21:31:02 -0400271 inode_doinit_with_dentry(inode, dentry);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500272 }
273 return 0;
274}
275
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500276static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
277{
Casey Schaufler80788c22018-09-21 17:19:11 -0700278 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500279}
280
281static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
282{
283 int error;
284
285 error = __inode_security_revalidate(inode, NULL, !rcu);
286 if (error)
287 return ERR_PTR(error);
Casey Schaufler80788c22018-09-21 17:19:11 -0700288 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500289}
290
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500291/*
292 * Get the security label of an inode.
293 */
294static struct inode_security_struct *inode_security(struct inode *inode)
295{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500296 __inode_security_revalidate(inode, NULL, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700297 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500298}
299
Paul Moore2c971652016-04-19 16:36:28 -0400300static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
301{
302 struct inode *inode = d_backing_inode(dentry);
303
Casey Schaufler80788c22018-09-21 17:19:11 -0700304 return selinux_inode(inode);
Paul Moore2c971652016-04-19 16:36:28 -0400305}
306
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500307/*
308 * Get the security label of a dentry's backing inode.
309 */
310static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
311{
312 struct inode *inode = d_backing_inode(dentry);
313
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500314 __inode_security_revalidate(inode, dentry, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700315 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500316}
317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318static void inode_free_security(struct inode *inode)
319{
Casey Schaufler80788c22018-09-21 17:19:11 -0700320 struct inode_security_struct *isec = selinux_inode(inode);
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700321 struct superblock_security_struct *sbsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700323 if (!isec)
324 return;
325 sbsec = inode->i_sb->s_security;
Waiman Long9629d042015-07-10 17:19:56 -0400326 /*
327 * As not all inode security structures are in a list, we check for
328 * empty list outside of the lock to make sure that we won't waste
329 * time taking a lock doing nothing.
330 *
331 * The list_del_init() function can be safely called more than once.
332 * It should not be possible for this function to be called with
333 * concurrent list_add(), but for better safety against future changes
334 * in the code, we use list_empty_careful() here.
335 */
336 if (!list_empty_careful(&isec->list)) {
337 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400339 spin_unlock(&sbsec->isec_lock);
340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341}
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343static void superblock_free_security(struct super_block *sb)
344{
345 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 sb->s_security = NULL;
347 kfree(sbsec);
348}
349
Al Virobd323652018-12-13 15:04:59 -0500350struct selinux_mnt_opts {
351 const char *fscontext, *context, *rootcontext, *defcontext;
352};
353
Al Viro204cc0c2018-12-13 13:41:47 -0500354static void selinux_free_mnt_opts(void *mnt_opts)
355{
Al Virobd323652018-12-13 15:04:59 -0500356 struct selinux_mnt_opts *opts = mnt_opts;
357 kfree(opts->fscontext);
358 kfree(opts->context);
359 kfree(opts->rootcontext);
360 kfree(opts->defcontext);
Al Viro204cc0c2018-12-13 13:41:47 -0500361 kfree(opts);
362}
363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364enum {
Eric Paris31e87932007-09-19 17:19:12 -0400365 Opt_error = -1,
David Howells442155c2018-11-01 23:07:24 +0000366 Opt_context = 0,
367 Opt_defcontext = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 Opt_fscontext = 2,
David Howells442155c2018-11-01 23:07:24 +0000369 Opt_rootcontext = 3,
370 Opt_seclabel = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371};
372
Al Viroda3d76a2018-12-17 10:14:16 -0500373#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
Al Viro169d68efb2018-12-14 22:44:50 -0500374static struct {
375 const char *name;
376 int len;
377 int opt;
378 bool has_arg;
379} tokens[] = {
Al Viroda3d76a2018-12-17 10:14:16 -0500380 A(context, true),
381 A(fscontext, true),
382 A(defcontext, true),
383 A(rootcontext, true),
384 A(seclabel, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385};
Al Viro169d68efb2018-12-14 22:44:50 -0500386#undef A
387
388static int match_opt_prefix(char *s, int l, char **arg)
389{
390 int i;
391
392 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
393 size_t len = tokens[i].len;
394 if (len > l || memcmp(s, tokens[i].name, len))
395 continue;
396 if (tokens[i].has_arg) {
397 if (len == l || s[len] != '=')
398 continue;
399 *arg = s + len + 1;
400 } else if (len != l)
401 continue;
402 return tokens[i].opt;
403 }
404 return Opt_error;
405}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
408
Eric Parisc312feb2006-07-10 04:43:53 -0700409static int may_context_mount_sb_relabel(u32 sid,
410 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100411 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700412{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700413 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Parisc312feb2006-07-10 04:43:53 -0700414 int rc;
415
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500416 rc = avc_has_perm(&selinux_state,
417 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700418 FILESYSTEM__RELABELFROM, NULL);
419 if (rc)
420 return rc;
421
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500422 rc = avc_has_perm(&selinux_state,
423 tsec->sid, sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700424 FILESYSTEM__RELABELTO, NULL);
425 return rc;
426}
427
Eric Paris08089252006-07-10 04:43:55 -0700428static int may_context_mount_inode_relabel(u32 sid,
429 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100430 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700431{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700432 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Paris08089252006-07-10 04:43:55 -0700433 int rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500434 rc = avc_has_perm(&selinux_state,
435 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700436 FILESYSTEM__RELABELFROM, NULL);
437 if (rc)
438 return rc;
439
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500440 rc = avc_has_perm(&selinux_state,
441 sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700442 FILESYSTEM__ASSOCIATE, NULL);
443 return rc;
444}
445
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100446static int selinux_is_genfs_special_handling(struct super_block *sb)
Eric Parisb43e7252012-10-10 14:27:35 -0400447{
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100448 /* Special handling. Genfs but also in-core setxattr handler */
449 return !strcmp(sb->s_type->name, "sysfs") ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500450 !strcmp(sb->s_type->name, "pstore") ||
451 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500452 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500453 !strcmp(sb->s_type->name, "rootfs") ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500454 (selinux_policycap_cgroupseclabel() &&
Stephen Smalley2651225b2017-02-28 10:35:56 -0500455 (!strcmp(sb->s_type->name, "cgroup") ||
456 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400457}
458
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100459static int selinux_is_sblabel_mnt(struct super_block *sb)
460{
461 struct superblock_security_struct *sbsec = sb->s_security;
462
463 /*
464 * IMPORTANT: Double-check logic in this function when adding a new
465 * SECURITY_FS_USE_* definition!
466 */
467 BUILD_BUG_ON(SECURITY_FS_USE_MAX != 7);
468
469 switch (sbsec->behavior) {
470 case SECURITY_FS_USE_XATTR:
471 case SECURITY_FS_USE_TRANS:
472 case SECURITY_FS_USE_TASK:
473 case SECURITY_FS_USE_NATIVE:
474 return 1;
475
476 case SECURITY_FS_USE_GENFS:
477 return selinux_is_genfs_special_handling(sb);
478
479 /* Never allow relabeling on context mounts */
480 case SECURITY_FS_USE_MNTPOINT:
481 case SECURITY_FS_USE_NONE:
482 default:
483 return 0;
484 }
485}
486
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100487static int sb_check_xattr_support(struct super_block *sb)
488{
489 struct superblock_security_struct *sbsec = sb->s_security;
490 struct dentry *root = sb->s_root;
491 struct inode *root_inode = d_backing_inode(root);
492 u32 sid;
493 int rc;
494
495 /*
496 * Make sure that the xattr handler exists and that no
497 * error other than -ENODATA is returned by getxattr on
498 * the root directory. -ENODATA is ok, as this may be
499 * the first boot of the SELinux kernel before we have
500 * assigned xattr values to the filesystem.
501 */
502 if (!(root_inode->i_opflags & IOP_XATTR)) {
503 pr_warn("SELinux: (dev %s, type %s) has no xattr support\n",
504 sb->s_id, sb->s_type->name);
505 goto fallback;
506 }
507
508 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
509 if (rc < 0 && rc != -ENODATA) {
510 if (rc == -EOPNOTSUPP) {
511 pr_warn("SELinux: (dev %s, type %s) has no security xattr handler\n",
512 sb->s_id, sb->s_type->name);
513 goto fallback;
514 } else {
515 pr_warn("SELinux: (dev %s, type %s) getxattr errno %d\n",
516 sb->s_id, sb->s_type->name, -rc);
517 return rc;
518 }
519 }
520 return 0;
521
522fallback:
523 /* No xattr support - try to fallback to genfs if possible. */
524 rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/",
525 SECCLASS_DIR, &sid);
526 if (rc)
527 return -EOPNOTSUPP;
528
529 pr_warn("SELinux: (dev %s, type %s) falling back to genfs\n",
530 sb->s_id, sb->s_type->name);
531 sbsec->behavior = SECURITY_FS_USE_GENFS;
532 sbsec->sid = sid;
533 return 0;
534}
535
Eric Parisc9180a52007-11-30 13:00:35 -0500536static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537{
538 struct superblock_security_struct *sbsec = sb->s_security;
539 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000540 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 int rc = 0;
542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100544 rc = sb_check_xattr_support(sb);
545 if (rc)
546 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
548
Eric Pariseadcabc2012-08-24 15:59:14 -0400549 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400550
551 /*
552 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
553 * leave the flag untouched because sb_clone_mnt_opts might be handing
554 * us a superblock that needs the flag to be cleared.
555 */
Eric Parisb43e7252012-10-10 14:27:35 -0400556 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400557 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400558 else
559 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500562 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
564 /* Initialize any other inodes associated with the superblock, e.g.
565 inodes created prior to initial policy load or inodes created
566 during get_sb by a pseudo filesystem that directly
567 populates itself. */
568 spin_lock(&sbsec->isec_lock);
Al Viro8d641242018-12-10 15:34:12 -0500569 while (!list_empty(&sbsec->isec_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 struct inode_security_struct *isec =
Al Viro8d641242018-12-10 15:34:12 -0500571 list_first_entry(&sbsec->isec_head,
Eric Parisc9180a52007-11-30 13:00:35 -0500572 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400574 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 spin_unlock(&sbsec->isec_lock);
576 inode = igrab(inode);
577 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500578 if (!IS_PRIVATE(inode))
Paul Moorecb89e242020-01-10 16:32:10 -0500579 inode_doinit_with_dentry(inode, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 iput(inode);
581 }
582 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 }
584 spin_unlock(&sbsec->isec_lock);
Eric Parisc9180a52007-11-30 13:00:35 -0500585 return rc;
586}
587
Eric Parisc9180a52007-11-30 13:00:35 -0500588static int bad_option(struct superblock_security_struct *sbsec, char flag,
589 u32 old_sid, u32 new_sid)
590{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500591 char mnt_flags = sbsec->flags & SE_MNTMASK;
592
Eric Parisc9180a52007-11-30 13:00:35 -0500593 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500594 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500595 if (!(sbsec->flags & flag) ||
596 (old_sid != new_sid))
597 return 1;
598
599 /* check if we were passed the same options twice,
600 * aka someone passed context=a,context=b
601 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500602 if (!(sbsec->flags & SE_SBINITIALIZED))
603 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500604 return 1;
605 return 0;
606}
Eric Parise0007522008-03-05 10:31:54 -0500607
Al Virobd323652018-12-13 15:04:59 -0500608static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
609{
610 int rc = security_context_str_to_sid(&selinux_state, s,
611 sid, GFP_KERNEL);
612 if (rc)
613 pr_warn("SELinux: security_context_str_to_sid"
614 "(%s) failed for (dev %s, type %s) errno=%d\n",
615 s, sb->s_id, sb->s_type->name, rc);
616 return rc;
617}
618
Eric Parisc9180a52007-11-30 13:00:35 -0500619/*
620 * Allow filesystems with binary mount data to explicitly set mount point
621 * labeling information.
622 */
Eric Parise0007522008-03-05 10:31:54 -0500623static int selinux_set_mnt_opts(struct super_block *sb,
Al Viro204cc0c2018-12-13 13:41:47 -0500624 void *mnt_opts,
David Quigley649f6e72013-05-22 12:50:36 -0400625 unsigned long kern_flags,
626 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500627{
David Howells275bb412008-11-14 10:39:19 +1100628 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500629 struct superblock_security_struct *sbsec = sb->s_security;
Ondrej Mosnacekb159e862020-11-04 13:01:10 +0100630 struct dentry *root = sb->s_root;
Al Virobd323652018-12-13 15:04:59 -0500631 struct selinux_mnt_opts *opts = mnt_opts;
Paul Moore2c971652016-04-19 16:36:28 -0400632 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500633 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
634 u32 defcontext_sid = 0;
Al Virobd323652018-12-13 15:04:59 -0500635 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500636
637 mutex_lock(&sbsec->lock);
638
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100639 if (!selinux_initialized(&selinux_state)) {
Al Virobd323652018-12-13 15:04:59 -0500640 if (!opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500641 /* Defer initialization until selinux_complete_init,
642 after the initial policy is loaded and the security
643 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500644 goto out;
645 }
646 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200647 pr_warn("SELinux: Unable to set superblock options "
Eric Paris744ba352008-04-17 11:52:44 -0400648 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500649 goto out;
650 }
David Quigley649f6e72013-05-22 12:50:36 -0400651 if (kern_flags && !set_kern_flags) {
652 /* Specifying internal flags without providing a place to
653 * place the results is not allowed */
654 rc = -EINVAL;
655 goto out;
656 }
Eric Parisc9180a52007-11-30 13:00:35 -0500657
658 /*
Eric Parise0007522008-03-05 10:31:54 -0500659 * Binary mount data FS will come through this function twice. Once
660 * from an explicit call and once from the generic calls from the vfs.
661 * Since the generic VFS calls will not contain any security mount data
662 * we need to skip the double mount verification.
663 *
664 * This does open a hole in which we will not notice if the first
665 * mount using this sb set explict options and a second mount using
666 * this sb does not set any security options. (The first options
667 * will be used for both mounts)
668 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500669 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Al Virobd323652018-12-13 15:04:59 -0500670 && !opts)
Eric Parisf5269712008-05-14 11:27:45 -0400671 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500672
Paul Moore2c971652016-04-19 16:36:28 -0400673 root_isec = backing_inode_security_novalidate(root);
674
Eric Parise0007522008-03-05 10:31:54 -0500675 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500676 * parse the mount options, check if they are valid sids.
677 * also check if someone is trying to mount the same sb more
678 * than once with different security options.
679 */
Al Virobd323652018-12-13 15:04:59 -0500680 if (opts) {
681 if (opts->fscontext) {
682 rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
683 if (rc)
684 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500685 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
686 fscontext_sid))
687 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500688 sbsec->flags |= FSCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500689 }
690 if (opts->context) {
691 rc = parse_sid(sb, opts->context, &context_sid);
692 if (rc)
693 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500694 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
695 context_sid))
696 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500697 sbsec->flags |= CONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500698 }
699 if (opts->rootcontext) {
700 rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
701 if (rc)
702 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500703 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
704 rootcontext_sid))
705 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500706 sbsec->flags |= ROOTCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500707 }
708 if (opts->defcontext) {
709 rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
710 if (rc)
711 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500712 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
713 defcontext_sid))
714 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500715 sbsec->flags |= DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500716 }
717 }
718
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500719 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500720 /* previously mounted with options, but not on this attempt? */
Al Virobd323652018-12-13 15:04:59 -0500721 if ((sbsec->flags & SE_MNTMASK) && !opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500722 goto out_double_mount;
723 rc = 0;
724 goto out;
725 }
726
James Morris089be432008-07-15 18:32:49 +1000727 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400728 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
729
Stephen Smalley8e014722015-06-04 16:22:17 -0400730 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700731 !strcmp(sb->s_type->name, "tracefs") ||
Hridya Valsarajua20456a2020-02-01 17:46:23 -0800732 !strcmp(sb->s_type->name, "binder") ||
Connor O'Brien4ca54d32020-02-07 10:01:49 -0800733 !strcmp(sb->s_type->name, "bpf") ||
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100734 !strcmp(sb->s_type->name, "pstore"))
735 sbsec->flags |= SE_SBGENFS;
736
737 if (!strcmp(sb->s_type->name, "sysfs") ||
Antonio Murdaca901ef842017-02-09 17:02:42 +0100738 !strcmp(sb->s_type->name, "cgroup") ||
739 !strcmp(sb->s_type->name, "cgroup2"))
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100740 sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR;
Eric Parisc9180a52007-11-30 13:00:35 -0500741
David Quigleyeb9ae682013-05-22 12:50:37 -0400742 if (!sbsec->behavior) {
743 /*
744 * Determine the labeling behavior to use for this
745 * filesystem type.
746 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500747 rc = security_fs_use(&selinux_state, sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400748 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +0200749 pr_warn("%s: security_fs_use(%s) returned %d\n",
David Quigleyeb9ae682013-05-22 12:50:37 -0400750 __func__, sb->s_type->name, rc);
751 goto out;
752 }
Eric Parisc9180a52007-11-30 13:00:35 -0500753 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500754
755 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500756 * If this is a user namespace mount and the filesystem type is not
757 * explicitly whitelisted, then no contexts are allowed on the command
758 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500759 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500760 if (sb->s_user_ns != &init_user_ns &&
761 strcmp(sb->s_type->name, "tmpfs") &&
762 strcmp(sb->s_type->name, "ramfs") &&
763 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500764 if (context_sid || fscontext_sid || rootcontext_sid ||
765 defcontext_sid) {
766 rc = -EACCES;
767 goto out;
768 }
769 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
770 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500771 rc = security_transition_sid(&selinux_state,
772 current_sid(),
773 current_sid(),
Seth Forsheeaad82892016-04-26 14:36:20 -0500774 SECCLASS_FILE, NULL,
775 &sbsec->mntpoint_sid);
776 if (rc)
777 goto out;
778 }
779 goto out_set_opts;
780 }
781
Eric Parisc9180a52007-11-30 13:00:35 -0500782 /* sets the context of the superblock for the fs being mounted. */
783 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100784 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500785 if (rc)
786 goto out;
787
788 sbsec->sid = fscontext_sid;
789 }
790
791 /*
792 * Switch to using mount point labeling behavior.
793 * sets the label used on all file below the mountpoint, and will set
794 * the superblock context if not already set.
795 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400796 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
797 sbsec->behavior = SECURITY_FS_USE_NATIVE;
798 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
799 }
800
Eric Parisc9180a52007-11-30 13:00:35 -0500801 if (context_sid) {
802 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100803 rc = may_context_mount_sb_relabel(context_sid, sbsec,
804 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500805 if (rc)
806 goto out;
807 sbsec->sid = context_sid;
808 } else {
David Howells275bb412008-11-14 10:39:19 +1100809 rc = may_context_mount_inode_relabel(context_sid, sbsec,
810 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500811 if (rc)
812 goto out;
813 }
814 if (!rootcontext_sid)
815 rootcontext_sid = context_sid;
816
817 sbsec->mntpoint_sid = context_sid;
818 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
819 }
820
821 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100822 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
823 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500824 if (rc)
825 goto out;
826
827 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500828 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500829 }
830
831 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400832 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
833 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500834 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200835 pr_warn("SELinux: defcontext option is "
Eric Parisc9180a52007-11-30 13:00:35 -0500836 "invalid for this filesystem type\n");
837 goto out;
838 }
839
840 if (defcontext_sid != sbsec->def_sid) {
841 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100842 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500843 if (rc)
844 goto out;
845 }
846
847 sbsec->def_sid = defcontext_sid;
848 }
849
Seth Forsheeaad82892016-04-26 14:36:20 -0500850out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500851 rc = sb_finish_set_opts(sb);
852out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700853 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500855out_double_mount:
856 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200857 pr_warn("SELinux: mount invalid. Same superblock, different "
Al Virobd323652018-12-13 15:04:59 -0500858 "security settings for (dev %s, type %s)\n", sb->s_id,
859 sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500860 goto out;
861}
862
Jeff Layton094f7b62013-04-01 08:14:24 -0400863static int selinux_cmp_sb_context(const struct super_block *oldsb,
864 const struct super_block *newsb)
865{
866 struct superblock_security_struct *old = oldsb->s_security;
867 struct superblock_security_struct *new = newsb->s_security;
868 char oldflags = old->flags & SE_MNTMASK;
869 char newflags = new->flags & SE_MNTMASK;
870
871 if (oldflags != newflags)
872 goto mismatch;
873 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
874 goto mismatch;
875 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
876 goto mismatch;
877 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
878 goto mismatch;
879 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500880 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
881 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400882 if (oldroot->sid != newroot->sid)
883 goto mismatch;
884 }
885 return 0;
886mismatch:
peter enderborgc103a912018-06-12 10:09:03 +0200887 pr_warn("SELinux: mount invalid. Same superblock, "
Jeff Layton094f7b62013-04-01 08:14:24 -0400888 "different security settings for (dev %s, "
889 "type %s)\n", newsb->s_id, newsb->s_type->name);
890 return -EBUSY;
891}
892
893static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400894 struct super_block *newsb,
895 unsigned long kern_flags,
896 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500897{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400898 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500899 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
900 struct superblock_security_struct *newsbsec = newsb->s_security;
901
902 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
903 int set_context = (oldsbsec->flags & CONTEXT_MNT);
904 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
905
Eric Paris0f5e6422008-04-21 16:24:11 -0400906 /*
907 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400908 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400909 */
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100910 if (!selinux_initialized(&selinux_state))
Jeff Layton094f7b62013-04-01 08:14:24 -0400911 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500912
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400913 /*
914 * Specifying internal flags without providing a place to
915 * place the results is not allowed.
916 */
917 if (kern_flags && !set_kern_flags)
918 return -EINVAL;
919
Eric Parisc9180a52007-11-30 13:00:35 -0500920 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500921 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500922
Jeff Layton094f7b62013-04-01 08:14:24 -0400923 /* if fs is reusing a sb, make sure that the contexts match */
J. Bruce Fields3815a242019-03-05 16:17:58 -0500924 if (newsbsec->flags & SE_SBINITIALIZED) {
925 if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
926 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
Jeff Layton094f7b62013-04-01 08:14:24 -0400927 return selinux_cmp_sb_context(oldsb, newsb);
J. Bruce Fields3815a242019-03-05 16:17:58 -0500928 }
Eric Paris5a552612008-04-09 14:08:35 -0400929
Eric Parisc9180a52007-11-30 13:00:35 -0500930 mutex_lock(&newsbsec->lock);
931
932 newsbsec->flags = oldsbsec->flags;
933
934 newsbsec->sid = oldsbsec->sid;
935 newsbsec->def_sid = oldsbsec->def_sid;
936 newsbsec->behavior = oldsbsec->behavior;
937
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400938 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
939 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500940 rc = security_fs_use(&selinux_state, newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400941 if (rc)
942 goto out;
943 }
944
945 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
946 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
947 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
948 }
949
Eric Parisc9180a52007-11-30 13:00:35 -0500950 if (set_context) {
951 u32 sid = oldsbsec->mntpoint_sid;
952
953 if (!set_fscontext)
954 newsbsec->sid = sid;
955 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500956 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500957 newisec->sid = sid;
958 }
959 newsbsec->mntpoint_sid = sid;
960 }
961 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500962 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
963 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500964
965 newisec->sid = oldisec->sid;
966 }
967
968 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400969out:
Eric Parisc9180a52007-11-30 13:00:35 -0500970 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400971 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500972}
973
Al Viroba641862018-12-14 20:28:15 -0500974static int selinux_add_opt(int token, const char *s, void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500975{
Al Viroba641862018-12-14 20:28:15 -0500976 struct selinux_mnt_opts *opts = *mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500977
Al Viroda3d76a2018-12-17 10:14:16 -0500978 if (token == Opt_seclabel) /* eaten and completely ignored */
Al Viro169d68efb2018-12-14 22:44:50 -0500979 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500980
Al Viroba641862018-12-14 20:28:15 -0500981 if (!opts) {
982 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
983 if (!opts)
984 return -ENOMEM;
985 *mnt_opts = opts;
986 }
987 if (!s)
988 return -ENOMEM;
989 switch (token) {
990 case Opt_context:
991 if (opts->context || opts->defcontext)
992 goto Einval;
993 opts->context = s;
994 break;
995 case Opt_fscontext:
996 if (opts->fscontext)
997 goto Einval;
998 opts->fscontext = s;
999 break;
1000 case Opt_rootcontext:
1001 if (opts->rootcontext)
1002 goto Einval;
1003 opts->rootcontext = s;
1004 break;
1005 case Opt_defcontext:
1006 if (opts->context || opts->defcontext)
1007 goto Einval;
1008 opts->defcontext = s;
1009 break;
1010 }
1011 return 0;
1012Einval:
1013 pr_warn(SEL_MOUNT_FAIL_MSG);
Al Viroba641862018-12-14 20:28:15 -05001014 return -EINVAL;
1015}
Eric Parisc9180a52007-11-30 13:00:35 -05001016
Al Viro757cbe52018-12-14 23:42:21 -05001017static int selinux_add_mnt_opt(const char *option, const char *val, int len,
1018 void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001019{
Al Viro757cbe52018-12-14 23:42:21 -05001020 int token = Opt_error;
1021 int rc, i;
Eric Parisc9180a52007-11-30 13:00:35 -05001022
Al Viro757cbe52018-12-14 23:42:21 -05001023 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
1024 if (strcmp(option, tokens[i].name) == 0) {
1025 token = tokens[i].opt;
Eric Parisc9180a52007-11-30 13:00:35 -05001026 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001027 }
1028 }
1029
Al Viro757cbe52018-12-14 23:42:21 -05001030 if (token == Opt_error)
1031 return -EINVAL;
Eric Parise0007522008-03-05 10:31:54 -05001032
Gen Zhange2e0e092019-06-12 21:28:21 +08001033 if (token != Opt_seclabel) {
Al Viro757cbe52018-12-14 23:42:21 -05001034 val = kmemdup_nul(val, len, GFP_KERNEL);
Gen Zhange2e0e092019-06-12 21:28:21 +08001035 if (!val) {
1036 rc = -ENOMEM;
1037 goto free_opt;
1038 }
1039 }
Al Viro757cbe52018-12-14 23:42:21 -05001040 rc = selinux_add_opt(token, val, mnt_opts);
1041 if (unlikely(rc)) {
1042 kfree(val);
Gen Zhange2e0e092019-06-12 21:28:21 +08001043 goto free_opt;
1044 }
1045 return rc;
1046
1047free_opt:
1048 if (*mnt_opts) {
1049 selinux_free_mnt_opts(*mnt_opts);
1050 *mnt_opts = NULL;
Al Viro757cbe52018-12-14 23:42:21 -05001051 }
1052 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Al Viroe3489f82018-12-13 00:24:36 -05001055static int show_sid(struct seq_file *m, u32 sid)
Eric Paris2069f452008-07-04 09:47:13 +10001056{
Al Viroe3489f82018-12-13 00:24:36 -05001057 char *context = NULL;
1058 u32 len;
1059 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Al Viroe3489f82018-12-13 00:24:36 -05001061 rc = security_sid_to_context(&selinux_state, sid,
1062 &context, &len);
1063 if (!rc) {
1064 bool has_comma = context && strchr(context, ',');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
David Howells442155c2018-11-01 23:07:24 +00001066 seq_putc(m, '=');
Eric Paris2069f452008-07-04 09:47:13 +10001067 if (has_comma)
1068 seq_putc(m, '\"');
Al Viroe3489f82018-12-13 00:24:36 -05001069 seq_escape(m, context, "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001070 if (has_comma)
1071 seq_putc(m, '\"');
1072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return rc;
1075}
Eric Paris2069f452008-07-04 09:47:13 +10001076
1077static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1078{
Al Viroe3489f82018-12-13 00:24:36 -05001079 struct superblock_security_struct *sbsec = sb->s_security;
Eric Paris2069f452008-07-04 09:47:13 +10001080 int rc;
1081
Al Viroe3489f82018-12-13 00:24:36 -05001082 if (!(sbsec->flags & SE_SBINITIALIZED))
1083 return 0;
1084
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01001085 if (!selinux_initialized(&selinux_state))
Al Viroe3489f82018-12-13 00:24:36 -05001086 return 0;
1087
1088 if (sbsec->flags & FSCONTEXT_MNT) {
1089 seq_putc(m, ',');
1090 seq_puts(m, FSCONTEXT_STR);
1091 rc = show_sid(m, sbsec->sid);
1092 if (rc)
1093 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001094 }
Al Viroe3489f82018-12-13 00:24:36 -05001095 if (sbsec->flags & CONTEXT_MNT) {
1096 seq_putc(m, ',');
1097 seq_puts(m, CONTEXT_STR);
1098 rc = show_sid(m, sbsec->mntpoint_sid);
1099 if (rc)
1100 return rc;
1101 }
1102 if (sbsec->flags & DEFCONTEXT_MNT) {
1103 seq_putc(m, ',');
1104 seq_puts(m, DEFCONTEXT_STR);
1105 rc = show_sid(m, sbsec->def_sid);
1106 if (rc)
1107 return rc;
1108 }
1109 if (sbsec->flags & ROOTCONTEXT_MNT) {
Ondrej Mosnacekb159e862020-11-04 13:01:10 +01001110 struct dentry *root = sb->s_root;
Al Viroe3489f82018-12-13 00:24:36 -05001111 struct inode_security_struct *isec = backing_inode_security(root);
1112 seq_putc(m, ',');
1113 seq_puts(m, ROOTCONTEXT_STR);
1114 rc = show_sid(m, isec->sid);
1115 if (rc)
1116 return rc;
1117 }
1118 if (sbsec->flags & SBLABEL_MNT) {
1119 seq_putc(m, ',');
David Howells442155c2018-11-01 23:07:24 +00001120 seq_puts(m, SECLABEL_STR);
Al Viroe3489f82018-12-13 00:24:36 -05001121 }
1122 return 0;
Eric Paris2069f452008-07-04 09:47:13 +10001123}
1124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125static inline u16 inode_mode_to_security_class(umode_t mode)
1126{
1127 switch (mode & S_IFMT) {
1128 case S_IFSOCK:
1129 return SECCLASS_SOCK_FILE;
1130 case S_IFLNK:
1131 return SECCLASS_LNK_FILE;
1132 case S_IFREG:
1133 return SECCLASS_FILE;
1134 case S_IFBLK:
1135 return SECCLASS_BLK_FILE;
1136 case S_IFDIR:
1137 return SECCLASS_DIR;
1138 case S_IFCHR:
1139 return SECCLASS_CHR_FILE;
1140 case S_IFIFO:
1141 return SECCLASS_FIFO_FILE;
1142
1143 }
1144
1145 return SECCLASS_FILE;
1146}
1147
James Morris13402582005-09-30 14:24:34 -04001148static inline int default_protocol_stream(int protocol)
1149{
Paolo Abeni95ca9072020-12-16 12:55:27 +01001150 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP ||
1151 protocol == IPPROTO_MPTCP);
James Morris13402582005-09-30 14:24:34 -04001152}
1153
1154static inline int default_protocol_dgram(int protocol)
1155{
1156 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1157}
1158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1160{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001161 int extsockclass = selinux_policycap_extsockclass();
Stephen Smalleyda69a532017-01-09 10:07:30 -05001162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 switch (family) {
1164 case PF_UNIX:
1165 switch (type) {
1166 case SOCK_STREAM:
1167 case SOCK_SEQPACKET:
1168 return SECCLASS_UNIX_STREAM_SOCKET;
1169 case SOCK_DGRAM:
Luis Ressel2a764b52017-07-25 15:13:41 -04001170 case SOCK_RAW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 return SECCLASS_UNIX_DGRAM_SOCKET;
1172 }
1173 break;
1174 case PF_INET:
1175 case PF_INET6:
1176 switch (type) {
1177 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001178 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001179 if (default_protocol_stream(protocol))
1180 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001181 else if (extsockclass && protocol == IPPROTO_SCTP)
1182 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001183 else
1184 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001186 if (default_protocol_dgram(protocol))
1187 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001188 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1189 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001190 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001191 else
1192 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001193 case SOCK_DCCP:
1194 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001195 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 return SECCLASS_RAWIP_SOCKET;
1197 }
1198 break;
1199 case PF_NETLINK:
1200 switch (protocol) {
1201 case NETLINK_ROUTE:
1202 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001203 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1205 case NETLINK_NFLOG:
1206 return SECCLASS_NETLINK_NFLOG_SOCKET;
1207 case NETLINK_XFRM:
1208 return SECCLASS_NETLINK_XFRM_SOCKET;
1209 case NETLINK_SELINUX:
1210 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001211 case NETLINK_ISCSI:
1212 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 case NETLINK_AUDIT:
1214 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001215 case NETLINK_FIB_LOOKUP:
1216 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1217 case NETLINK_CONNECTOR:
1218 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1219 case NETLINK_NETFILTER:
1220 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 case NETLINK_DNRTMSG:
1222 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001223 case NETLINK_KOBJECT_UEVENT:
1224 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001225 case NETLINK_GENERIC:
1226 return SECCLASS_NETLINK_GENERIC_SOCKET;
1227 case NETLINK_SCSITRANSPORT:
1228 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1229 case NETLINK_RDMA:
1230 return SECCLASS_NETLINK_RDMA_SOCKET;
1231 case NETLINK_CRYPTO:
1232 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 default:
1234 return SECCLASS_NETLINK_SOCKET;
1235 }
1236 case PF_PACKET:
1237 return SECCLASS_PACKET_SOCKET;
1238 case PF_KEY:
1239 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001240 case PF_APPLETALK:
1241 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 }
1243
Stephen Smalleyda69a532017-01-09 10:07:30 -05001244 if (extsockclass) {
1245 switch (family) {
1246 case PF_AX25:
1247 return SECCLASS_AX25_SOCKET;
1248 case PF_IPX:
1249 return SECCLASS_IPX_SOCKET;
1250 case PF_NETROM:
1251 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001252 case PF_ATMPVC:
1253 return SECCLASS_ATMPVC_SOCKET;
1254 case PF_X25:
1255 return SECCLASS_X25_SOCKET;
1256 case PF_ROSE:
1257 return SECCLASS_ROSE_SOCKET;
1258 case PF_DECnet:
1259 return SECCLASS_DECNET_SOCKET;
1260 case PF_ATMSVC:
1261 return SECCLASS_ATMSVC_SOCKET;
1262 case PF_RDS:
1263 return SECCLASS_RDS_SOCKET;
1264 case PF_IRDA:
1265 return SECCLASS_IRDA_SOCKET;
1266 case PF_PPPOX:
1267 return SECCLASS_PPPOX_SOCKET;
1268 case PF_LLC:
1269 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001270 case PF_CAN:
1271 return SECCLASS_CAN_SOCKET;
1272 case PF_TIPC:
1273 return SECCLASS_TIPC_SOCKET;
1274 case PF_BLUETOOTH:
1275 return SECCLASS_BLUETOOTH_SOCKET;
1276 case PF_IUCV:
1277 return SECCLASS_IUCV_SOCKET;
1278 case PF_RXRPC:
1279 return SECCLASS_RXRPC_SOCKET;
1280 case PF_ISDN:
1281 return SECCLASS_ISDN_SOCKET;
1282 case PF_PHONET:
1283 return SECCLASS_PHONET_SOCKET;
1284 case PF_IEEE802154:
1285 return SECCLASS_IEEE802154_SOCKET;
1286 case PF_CAIF:
1287 return SECCLASS_CAIF_SOCKET;
1288 case PF_ALG:
1289 return SECCLASS_ALG_SOCKET;
1290 case PF_NFC:
1291 return SECCLASS_NFC_SOCKET;
1292 case PF_VSOCK:
1293 return SECCLASS_VSOCK_SOCKET;
1294 case PF_KCM:
1295 return SECCLASS_KCM_SOCKET;
1296 case PF_QIPCRTR:
1297 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001298 case PF_SMC:
1299 return SECCLASS_SMC_SOCKET;
Björn Töpel68e8b842018-05-02 13:01:22 +02001300 case PF_XDP:
1301 return SECCLASS_XDP_SOCKET;
1302#if PF_MAX > 45
Stephen Smalleyda69a532017-01-09 10:07:30 -05001303#error New address family defined, please update this function.
1304#endif
1305 }
1306 }
1307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 return SECCLASS_SOCKET;
1309}
1310
Stephen Smalley134509d2015-06-04 16:22:17 -04001311static int selinux_genfs_get_sid(struct dentry *dentry,
1312 u16 tclass,
1313 u16 flags,
1314 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001316 int rc;
Al Virofc640052016-04-10 01:33:30 -04001317 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001318 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Eric Paris828dfe12008-04-17 13:17:49 -04001320 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 if (!buffer)
1322 return -ENOMEM;
1323
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001324 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1325 if (IS_ERR(path))
1326 rc = PTR_ERR(path);
1327 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001328 if (flags & SE_SBPROC) {
1329 /* each process gets a /proc/PID/ entry. Strip off the
1330 * PID part to get a valid selinux labeling.
1331 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1332 while (path[1] >= '0' && path[1] <= '9') {
1333 path[1] = '/';
1334 path++;
1335 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001336 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001337 rc = security_genfs_sid(&selinux_state, sb->s_type->name,
1338 path, tclass, sid);
Stephen Smalley7bb185e2018-09-04 16:51:36 -04001339 if (rc == -ENOENT) {
1340 /* No match in policy, mark as unlabeled. */
1341 *sid = SECINITSID_UNLABELED;
1342 rc = 0;
1343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 free_page((unsigned long)buffer);
1346 return rc;
1347}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001349static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
1350 u32 def_sid, u32 *sid)
1351{
1352#define INITCONTEXTLEN 255
1353 char *context;
1354 unsigned int len;
1355 int rc;
1356
1357 len = INITCONTEXTLEN;
1358 context = kmalloc(len + 1, GFP_NOFS);
1359 if (!context)
1360 return -ENOMEM;
1361
1362 context[len] = '\0';
1363 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1364 if (rc == -ERANGE) {
1365 kfree(context);
1366
1367 /* Need a larger buffer. Query for the right size. */
1368 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
1369 if (rc < 0)
1370 return rc;
1371
1372 len = rc;
1373 context = kmalloc(len + 1, GFP_NOFS);
1374 if (!context)
1375 return -ENOMEM;
1376
1377 context[len] = '\0';
1378 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
1379 context, len);
1380 }
1381 if (rc < 0) {
1382 kfree(context);
1383 if (rc != -ENODATA) {
1384 pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n",
1385 __func__, -rc, inode->i_sb->s_id, inode->i_ino);
1386 return rc;
1387 }
1388 *sid = def_sid;
1389 return 0;
1390 }
1391
1392 rc = security_context_to_sid_default(&selinux_state, context, rc, sid,
1393 def_sid, GFP_NOFS);
1394 if (rc) {
1395 char *dev = inode->i_sb->s_id;
1396 unsigned long ino = inode->i_ino;
1397
1398 if (rc == -EINVAL) {
1399 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",
1400 ino, dev, context);
1401 } else {
1402 pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n",
1403 __func__, context, -rc, dev, ino);
1404 }
1405 }
1406 kfree(context);
1407 return 0;
1408}
1409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410/* The inode's security attributes must be initialized before first use. */
1411static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1412{
1413 struct superblock_security_struct *sbsec = NULL;
Casey Schaufler80788c22018-09-21 17:19:11 -07001414 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001415 u32 task_sid, sid = 0;
1416 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 struct dentry *dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001420 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001421 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001423 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001424 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001425 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001427 if (isec->sclass == SECCLASS_FILE)
1428 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1429
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001431 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 /* Defer initialization until selinux_complete_init,
1433 after the initial policy is loaded and the security
1434 server is ready to handle calls. */
1435 spin_lock(&sbsec->isec_lock);
1436 if (list_empty(&isec->list))
1437 list_add(&isec->list, &sbsec->isec_head);
1438 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001439 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 }
1441
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001442 sclass = isec->sclass;
1443 task_sid = isec->task_sid;
1444 sid = isec->sid;
1445 isec->initialized = LABEL_PENDING;
1446 spin_unlock(&isec->lock);
1447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001449 case SECURITY_FS_USE_NATIVE:
1450 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001452 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001453 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 break;
1455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 /* Need a dentry, since the xattr API requires one.
1457 Life would be simpler if we could just pass the inode. */
1458 if (opt_dentry) {
1459 /* Called from d_instantiate or d_splice_alias. */
1460 dentry = dget(opt_dentry);
1461 } else {
Al Virob1271252018-04-25 10:28:38 -04001462 /*
1463 * Called from selinux_complete_init, try to find a dentry.
1464 * Some filesystems really want a connected one, so try
1465 * that first. We could split SECURITY_FS_USE_XATTR in
1466 * two, depending upon that...
1467 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001469 if (!dentry)
1470 dentry = d_find_any_alias(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 }
1472 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001473 /*
1474 * this is can be hit on boot when a file is accessed
1475 * before the policy is loaded. When we load policy we
1476 * may find inodes that have no dentry on the
1477 * sbsec->isec_head list. No reason to complain as these
1478 * will get fixed up the next time we go through
1479 * inode_doinit with a dentry, before these inodes could
1480 * be used again by userspace.
1481 */
Paul Moore200ea5a2020-11-03 11:49:38 -05001482 goto out_invalid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 }
1484
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001485 rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
1486 &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 dput(dentry);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001488 if (rc)
1489 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 break;
1491 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001492 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 break;
1494 case SECURITY_FS_USE_TRANS:
1495 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001496 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
1498 /* Try to obtain a transition SID. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001499 rc = security_transition_sid(&selinux_state, task_sid, sid,
1500 sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001502 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001504 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001505 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001506 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001508 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001509 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
Christian Göttsche7470d0d12020-01-28 20:16:48 +01001511 if ((sbsec->flags & SE_SBGENFS) &&
1512 (!S_ISLNK(inode->i_mode) ||
1513 selinux_policycap_genfs_seclabel_symlinks())) {
Paul Mooref64410e2014-03-19 16:46:18 -04001514 /* We must have a dentry to determine the label on
1515 * procfs inodes */
Al Virob1271252018-04-25 10:28:38 -04001516 if (opt_dentry) {
Paul Mooref64410e2014-03-19 16:46:18 -04001517 /* Called from d_instantiate or
1518 * d_splice_alias. */
1519 dentry = dget(opt_dentry);
Al Virob1271252018-04-25 10:28:38 -04001520 } else {
Paul Mooref64410e2014-03-19 16:46:18 -04001521 /* Called from selinux_complete_init, try to
Al Virob1271252018-04-25 10:28:38 -04001522 * find a dentry. Some filesystems really want
1523 * a connected one, so try that first.
1524 */
Paul Mooref64410e2014-03-19 16:46:18 -04001525 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001526 if (!dentry)
1527 dentry = d_find_any_alias(inode);
1528 }
Paul Mooref64410e2014-03-19 16:46:18 -04001529 /*
1530 * This can be hit on boot when a file is accessed
1531 * before the policy is loaded. When we load policy we
1532 * may find inodes that have no dentry on the
1533 * sbsec->isec_head list. No reason to complain as
1534 * these will get fixed up the next time we go through
1535 * inode_doinit() with a dentry, before these inodes
1536 * could be used again by userspace.
1537 */
1538 if (!dentry)
Paul Moore200ea5a2020-11-03 11:49:38 -05001539 goto out_invalid;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001540 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001541 sbsec->flags, &sid);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001542 if (rc) {
1543 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001544 goto out;
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001545 }
1546
1547 if ((sbsec->flags & SE_SBGENFS_XATTR) &&
1548 (inode->i_opflags & IOP_XATTR)) {
1549 rc = inode_doinit_use_xattr(inode, dentry,
1550 sid, &sid);
1551 if (rc) {
1552 dput(dentry);
1553 goto out;
1554 }
1555 }
1556 dput(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 }
1558 break;
1559 }
1560
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001561out:
1562 spin_lock(&isec->lock);
1563 if (isec->initialized == LABEL_PENDING) {
Paul Moore200ea5a2020-11-03 11:49:38 -05001564 if (rc) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001565 isec->initialized = LABEL_INVALID;
1566 goto out_unlock;
1567 }
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001568 isec->initialized = LABEL_INITIALIZED;
1569 isec->sid = sid;
1570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Eric Paris23970742006-09-25 23:32:01 -07001572out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001573 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 return rc;
Paul Moore200ea5a2020-11-03 11:49:38 -05001575
1576out_invalid:
1577 spin_lock(&isec->lock);
1578 if (isec->initialized == LABEL_PENDING) {
1579 isec->initialized = LABEL_INVALID;
1580 isec->sid = sid;
1581 }
1582 spin_unlock(&isec->lock);
1583 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585
1586/* Convert a Linux signal to an access vector. */
1587static inline u32 signal_to_av(int sig)
1588{
1589 u32 perm = 0;
1590
1591 switch (sig) {
1592 case SIGCHLD:
1593 /* Commonly granted from child to parent. */
1594 perm = PROCESS__SIGCHLD;
1595 break;
1596 case SIGKILL:
1597 /* Cannot be caught or ignored */
1598 perm = PROCESS__SIGKILL;
1599 break;
1600 case SIGSTOP:
1601 /* Cannot be caught or ignored */
1602 perm = PROCESS__SIGSTOP;
1603 break;
1604 default:
1605 /* All other signals. */
1606 perm = PROCESS__SIGNAL;
1607 break;
1608 }
1609
1610 return perm;
1611}
1612
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001613#if CAP_LAST_CAP > 63
1614#error Fix SELinux to handle capabilities > 63.
1615#endif
1616
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001618static int cred_has_capability(const struct cred *cred,
Micah Mortonc1a85a02019-01-07 16:10:53 -08001619 int cap, unsigned int opts, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
Thomas Liu2bf49692009-07-14 12:14:09 -04001621 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001622 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001623 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001624 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001625 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001626 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Eric Paris50c205f2012-04-04 15:01:43 -04001628 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 ad.u.cap = cap;
1630
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001631 switch (CAP_TO_INDEX(cap)) {
1632 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001633 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001634 break;
1635 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001636 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001637 break;
1638 default:
peter enderborgc103a912018-06-12 10:09:03 +02001639 pr_err("SELinux: out of range capability %d\n", cap);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001640 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001641 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001642 }
Eric Paris06112162008-11-11 22:02:50 +11001643
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001644 rc = avc_has_perm_noaudit(&selinux_state,
1645 sid, sid, sclass, av, 0, &avd);
Micah Mortonc1a85a02019-01-07 16:10:53 -08001646 if (!(opts & CAP_OPT_NOAUDIT)) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001647 int rc2 = avc_audit(&selinux_state,
1648 sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001649 if (rc2)
1650 return rc2;
1651 }
Eric Paris06112162008-11-11 22:02:50 +11001652 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653}
1654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655/* Check whether a task has a particular permission to an inode.
1656 The 'adp' parameter is optional and allows other audit
1657 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001658static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 struct inode *inode,
1660 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001661 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001664 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
David Howellse0e81732009-09-02 09:13:40 +01001666 validate_creds(cred);
1667
Eric Paris828dfe12008-04-17 13:17:49 -04001668 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001669 return 0;
1670
David Howells88e67f32008-11-14 10:39:21 +11001671 sid = cred_sid(cred);
Casey Schaufler80788c22018-09-21 17:19:11 -07001672 isec = selinux_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001674 return avc_has_perm(&selinux_state,
1675 sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676}
1677
1678/* Same as inode_has_perm, but pass explicit audit data containing
1679 the dentry to help the auditing code to more easily generate the
1680 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001681static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 struct dentry *dentry,
1683 u32 av)
1684{
David Howellsc6f493d2015-03-17 22:26:22 +00001685 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001686 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001687
Eric Paris50c205f2012-04-04 15:01:43 -04001688 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001689 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001690 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001691 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001692}
1693
1694/* Same as inode_has_perm, but pass explicit audit data containing
1695 the path to help the auditing code to more easily generate the
1696 pathname if needed. */
1697static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001698 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001699 u32 av)
1700{
David Howellsc6f493d2015-03-17 22:26:22 +00001701 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001702 struct common_audit_data ad;
1703
Eric Paris50c205f2012-04-04 15:01:43 -04001704 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001705 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001706 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001707 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708}
1709
David Howells13f8e982013-06-13 23:37:55 +01001710/* Same as path_has_perm, but uses the inode from the file struct. */
1711static inline int file_path_has_perm(const struct cred *cred,
1712 struct file *file,
1713 u32 av)
1714{
1715 struct common_audit_data ad;
1716
Vivek Goyal43af5de2016-09-09 11:37:49 -04001717 ad.type = LSM_AUDIT_DATA_FILE;
1718 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001719 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001720}
1721
Chenbo Fengf66e4482017-10-18 13:00:26 -07001722#ifdef CONFIG_BPF_SYSCALL
1723static int bpf_fd_pass(struct file *file, u32 sid);
1724#endif
1725
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726/* Check whether a task can use an open file descriptor to
1727 access an inode in a given way. Check access to the
1728 descriptor itself, and then use dentry_has_perm to
1729 check a particular permission to the file.
1730 Access to the descriptor is implicitly granted if it
1731 has the same SID as the process. If av is zero, then
1732 access to the file is not checked, e.g. for cases
1733 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001734static int file_has_perm(const struct cred *cred,
1735 struct file *file,
1736 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737{
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07001738 struct file_security_struct *fsec = selinux_file(file);
Al Viro496ad9a2013-01-23 17:07:38 -05001739 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001740 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001741 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 int rc;
1743
Vivek Goyal43af5de2016-09-09 11:37:49 -04001744 ad.type = LSM_AUDIT_DATA_FILE;
1745 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
David Howells275bb412008-11-14 10:39:19 +11001747 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001748 rc = avc_has_perm(&selinux_state,
1749 sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 SECCLASS_FD,
1751 FD__USE,
1752 &ad);
1753 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001754 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 }
1756
Chenbo Fengf66e4482017-10-18 13:00:26 -07001757#ifdef CONFIG_BPF_SYSCALL
1758 rc = bpf_fd_pass(file, cred_sid(cred));
1759 if (rc)
1760 return rc;
1761#endif
1762
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001764 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001766 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
David Howells88e67f32008-11-14 10:39:21 +11001768out:
1769 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
David Howellsc3c188b2015-07-10 17:19:58 -04001772/*
1773 * Determine the label for an inode that might be unioned.
1774 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001775static int
1776selinux_determine_inode_label(const struct task_security_struct *tsec,
1777 struct inode *dir,
1778 const struct qstr *name, u16 tclass,
1779 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001780{
1781 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001782
1783 if ((sbsec->flags & SE_SBINITIALIZED) &&
1784 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1785 *_new_isid = sbsec->mntpoint_sid;
1786 } else if ((sbsec->flags & SBLABEL_MNT) &&
1787 tsec->create_sid) {
1788 *_new_isid = tsec->create_sid;
1789 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001790 const struct inode_security_struct *dsec = inode_security(dir);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001791 return security_transition_sid(&selinux_state, tsec->sid,
1792 dsec->sid, tclass,
David Howellsc3c188b2015-07-10 17:19:58 -04001793 name, _new_isid);
1794 }
1795
1796 return 0;
1797}
1798
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799/* Check whether a task can create a file. */
1800static int may_create(struct inode *dir,
1801 struct dentry *dentry,
1802 u16 tclass)
1803{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07001804 const struct task_security_struct *tsec = selinux_cred(current_cred());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 struct inode_security_struct *dsec;
1806 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001807 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001808 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 int rc;
1810
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001811 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 sbsec = dir->i_sb->s_security;
1813
David Howells275bb412008-11-14 10:39:19 +11001814 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001815
Eric Paris50c205f2012-04-04 15:01:43 -04001816 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001817 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001819 rc = avc_has_perm(&selinux_state,
1820 sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 DIR__ADD_NAME | DIR__SEARCH,
1822 &ad);
1823 if (rc)
1824 return rc;
1825
Yang Guo210a2922019-12-12 10:02:24 +08001826 rc = selinux_determine_inode_label(tsec, dir, &dentry->d_name, tclass,
1827 &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001828 if (rc)
1829 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001831 rc = avc_has_perm(&selinux_state,
1832 sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 if (rc)
1834 return rc;
1835
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001836 return avc_has_perm(&selinux_state,
1837 newsid, sbsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 SECCLASS_FILESYSTEM,
1839 FILESYSTEM__ASSOCIATE, &ad);
1840}
1841
Eric Paris828dfe12008-04-17 13:17:49 -04001842#define MAY_LINK 0
1843#define MAY_UNLINK 1
1844#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846/* Check whether a task can link, unlink, or rmdir a file/directory. */
1847static int may_link(struct inode *dir,
1848 struct dentry *dentry,
1849 int kind)
1850
1851{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001853 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001854 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 u32 av;
1856 int rc;
1857
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001858 dsec = inode_security(dir);
1859 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Eric Paris50c205f2012-04-04 15:01:43 -04001861 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001862 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 av = DIR__SEARCH;
1865 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001866 rc = avc_has_perm(&selinux_state,
1867 sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 if (rc)
1869 return rc;
1870
1871 switch (kind) {
1872 case MAY_LINK:
1873 av = FILE__LINK;
1874 break;
1875 case MAY_UNLINK:
1876 av = FILE__UNLINK;
1877 break;
1878 case MAY_RMDIR:
1879 av = DIR__RMDIR;
1880 break;
1881 default:
peter enderborgc103a912018-06-12 10:09:03 +02001882 pr_warn("SELinux: %s: unrecognized kind %d\n",
Eric Paris744ba352008-04-17 11:52:44 -04001883 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 return 0;
1885 }
1886
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001887 rc = avc_has_perm(&selinux_state,
1888 sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 return rc;
1890}
1891
1892static inline int may_rename(struct inode *old_dir,
1893 struct dentry *old_dentry,
1894 struct inode *new_dir,
1895 struct dentry *new_dentry)
1896{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001898 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001899 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 u32 av;
1901 int old_is_dir, new_is_dir;
1902 int rc;
1903
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001904 old_dsec = inode_security(old_dir);
1905 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001906 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001907 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Eric Paris50c205f2012-04-04 15:01:43 -04001909 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
Eric Parisa2694342011-04-25 13:10:27 -04001911 ad.u.dentry = old_dentry;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001912 rc = avc_has_perm(&selinux_state,
1913 sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1915 if (rc)
1916 return rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001917 rc = avc_has_perm(&selinux_state,
1918 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 old_isec->sclass, FILE__RENAME, &ad);
1920 if (rc)
1921 return rc;
1922 if (old_is_dir && new_dir != old_dir) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001923 rc = avc_has_perm(&selinux_state,
1924 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 old_isec->sclass, DIR__REPARENT, &ad);
1926 if (rc)
1927 return rc;
1928 }
1929
Eric Parisa2694342011-04-25 13:10:27 -04001930 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001932 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 av |= DIR__REMOVE_NAME;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001934 rc = avc_has_perm(&selinux_state,
1935 sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 if (rc)
1937 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001938 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001939 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001940 new_is_dir = d_is_dir(new_dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001941 rc = avc_has_perm(&selinux_state,
1942 sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 new_isec->sclass,
1944 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1945 if (rc)
1946 return rc;
1947 }
1948
1949 return 0;
1950}
1951
1952/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001953static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 struct super_block *sb,
1955 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001956 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001959 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 sbsec = sb->s_security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001962 return avc_has_perm(&selinux_state,
1963 sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964}
1965
1966/* Convert a Linux mode and permission mask to an access vector. */
1967static inline u32 file_mask_to_av(int mode, int mask)
1968{
1969 u32 av = 0;
1970
Al Virodba19c62011-07-25 20:49:29 -04001971 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 if (mask & MAY_EXEC)
1973 av |= FILE__EXECUTE;
1974 if (mask & MAY_READ)
1975 av |= FILE__READ;
1976
1977 if (mask & MAY_APPEND)
1978 av |= FILE__APPEND;
1979 else if (mask & MAY_WRITE)
1980 av |= FILE__WRITE;
1981
1982 } else {
1983 if (mask & MAY_EXEC)
1984 av |= DIR__SEARCH;
1985 if (mask & MAY_WRITE)
1986 av |= DIR__WRITE;
1987 if (mask & MAY_READ)
1988 av |= DIR__READ;
1989 }
1990
1991 return av;
1992}
1993
1994/* Convert a Linux file to an access vector. */
1995static inline u32 file_to_av(struct file *file)
1996{
1997 u32 av = 0;
1998
1999 if (file->f_mode & FMODE_READ)
2000 av |= FILE__READ;
2001 if (file->f_mode & FMODE_WRITE) {
2002 if (file->f_flags & O_APPEND)
2003 av |= FILE__APPEND;
2004 else
2005 av |= FILE__WRITE;
2006 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002007 if (!av) {
2008 /*
2009 * Special file opened with flags 3 for ioctl-only use.
2010 */
2011 av = FILE__IOCTL;
2012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
2014 return av;
2015}
2016
Eric Paris8b6a5a32008-10-29 17:06:46 -04002017/*
Randy Dunlapc76a2f92020-08-07 09:51:34 -07002018 * Convert a file to an access vector and include the correct
Eric Paris8b6a5a32008-10-29 17:06:46 -04002019 * open permission.
2020 */
2021static inline u32 open_file_to_av(struct file *file)
2022{
2023 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04002024 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002025
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002026 if (selinux_policycap_openperm() &&
2027 inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002028 av |= FILE__OPEN;
2029
Eric Paris8b6a5a32008-10-29 17:06:46 -04002030 return av;
2031}
2032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033/* Hook functions begin here. */
2034
Stephen Smalley79af7302015-01-21 10:54:10 -05002035static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2036{
2037 u32 mysid = current_sid();
2038 u32 mgrsid = task_sid(mgr);
2039
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002040 return avc_has_perm(&selinux_state,
2041 mysid, mgrsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002042 BINDER__SET_CONTEXT_MGR, NULL);
2043}
2044
2045static int selinux_binder_transaction(struct task_struct *from,
2046 struct task_struct *to)
2047{
2048 u32 mysid = current_sid();
2049 u32 fromsid = task_sid(from);
2050 u32 tosid = task_sid(to);
2051 int rc;
2052
2053 if (mysid != fromsid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002054 rc = avc_has_perm(&selinux_state,
2055 mysid, fromsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002056 BINDER__IMPERSONATE, NULL);
2057 if (rc)
2058 return rc;
2059 }
2060
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002061 return avc_has_perm(&selinux_state,
2062 fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
Stephen Smalley79af7302015-01-21 10:54:10 -05002063 NULL);
2064}
2065
2066static int selinux_binder_transfer_binder(struct task_struct *from,
2067 struct task_struct *to)
2068{
2069 u32 fromsid = task_sid(from);
2070 u32 tosid = task_sid(to);
2071
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002072 return avc_has_perm(&selinux_state,
2073 fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002074 NULL);
2075}
2076
2077static int selinux_binder_transfer_file(struct task_struct *from,
2078 struct task_struct *to,
2079 struct file *file)
2080{
2081 u32 sid = task_sid(to);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07002082 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002083 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002084 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002085 struct common_audit_data ad;
2086 int rc;
2087
2088 ad.type = LSM_AUDIT_DATA_PATH;
2089 ad.u.path = file->f_path;
2090
2091 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002092 rc = avc_has_perm(&selinux_state,
2093 sid, fsec->sid,
Stephen Smalley79af7302015-01-21 10:54:10 -05002094 SECCLASS_FD,
2095 FD__USE,
2096 &ad);
2097 if (rc)
2098 return rc;
2099 }
2100
Chenbo Fengf66e4482017-10-18 13:00:26 -07002101#ifdef CONFIG_BPF_SYSCALL
2102 rc = bpf_fd_pass(file, sid);
2103 if (rc)
2104 return rc;
2105#endif
2106
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002107 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002108 return 0;
2109
Paul Moore20cdef82016-04-04 14:14:42 -04002110 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002111 return avc_has_perm(&selinux_state,
2112 sid, isec->sid, isec->sclass, file_to_av(file),
Stephen Smalley79af7302015-01-21 10:54:10 -05002113 &ad);
2114}
2115
Ingo Molnar9e488582009-05-07 19:26:19 +10002116static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002117 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002119 u32 sid = current_sid();
2120 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002121
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002122 if (mode & PTRACE_MODE_READ)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002123 return avc_has_perm(&selinux_state,
2124 sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002125
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002126 return avc_has_perm(&selinux_state,
2127 sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002128}
2129
2130static int selinux_ptrace_traceme(struct task_struct *parent)
2131{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002132 return avc_has_perm(&selinux_state,
2133 task_sid(parent), current_sid(), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002134 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135}
2136
2137static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002138 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002140 return avc_has_perm(&selinux_state,
2141 current_sid(), task_sid(target), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002142 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143}
2144
David Howellsd84f4f92008-11-14 10:39:23 +11002145static int selinux_capset(struct cred *new, const struct cred *old,
2146 const kernel_cap_t *effective,
2147 const kernel_cap_t *inheritable,
2148 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002150 return avc_has_perm(&selinux_state,
2151 cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002152 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
James Morris5626d3e2009-01-30 10:05:06 +11002155/*
2156 * (This comment used to live with the selinux_task_setuid hook,
2157 * which was removed).
2158 *
2159 * Since setuid only affects the current process, and since the SELinux
2160 * controls are not based on the Linux identity attributes, SELinux does not
2161 * need to control this operation. However, SELinux does control the use of
2162 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2163 */
2164
Eric Paris6a9de492012-01-03 12:25:14 -05002165static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002166 int cap, unsigned int opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
Micah Mortonc1a85a02019-01-07 16:10:53 -08002168 return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169}
2170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2172{
David Howells88e67f32008-11-14 10:39:21 +11002173 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 int rc = 0;
2175
2176 if (!sb)
2177 return 0;
2178
2179 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002180 case Q_SYNC:
2181 case Q_QUOTAON:
2182 case Q_QUOTAOFF:
2183 case Q_SETINFO:
2184 case Q_SETQUOTA:
Richard Hainese4cfa052020-02-20 15:32:34 +00002185 case Q_XQUOTAOFF:
2186 case Q_XQUOTAON:
2187 case Q_XSETQLIM:
David Howells88e67f32008-11-14 10:39:21 +11002188 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002189 break;
2190 case Q_GETFMT:
2191 case Q_GETINFO:
2192 case Q_GETQUOTA:
Richard Hainese4cfa052020-02-20 15:32:34 +00002193 case Q_XGETQUOTA:
2194 case Q_XGETQSTAT:
2195 case Q_XGETQSTATV:
2196 case Q_XGETNEXTQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002197 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002198 break;
2199 default:
2200 rc = 0; /* let the kernel handle invalid cmds */
2201 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 }
2203 return rc;
2204}
2205
2206static int selinux_quota_on(struct dentry *dentry)
2207{
David Howells88e67f32008-11-14 10:39:21 +11002208 const struct cred *cred = current_cred();
2209
Eric Paris2875fa02011-04-28 16:04:24 -04002210 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211}
2212
Eric Paris12b30522010-11-15 18:36:29 -05002213static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002216 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2217 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002218 return avc_has_perm(&selinux_state,
2219 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002220 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002221 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2222 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2223 /* Set level of messages printed to console */
2224 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002225 return avc_has_perm(&selinux_state,
2226 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002227 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2228 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002230 /* All other syslog types */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002231 return avc_has_perm(&selinux_state,
2232 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002233 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234}
2235
2236/*
2237 * Check that a process has enough memory to allocate a new virtual
2238 * mapping. 0 means there is enough memory for the allocation to
2239 * succeed and -ENOMEM implies there is not.
2240 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 * Do not audit the selinux permission check, as this is applied to all
2242 * processes that allocate mappings.
2243 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002244static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245{
2246 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002248 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002249 CAP_OPT_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 if (rc == 0)
2251 cap_sys_admin = 1;
2252
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002253 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254}
2255
2256/* binprm security operations */
2257
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002258static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002259{
2260 u32 sid = 0;
2261 struct task_struct *tracer;
2262
2263 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002264 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002265 if (tracer)
2266 sid = task_sid(tracer);
2267 rcu_read_unlock();
2268
2269 return sid;
2270}
2271
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002272static int check_nnp_nosuid(const struct linux_binprm *bprm,
2273 const struct task_security_struct *old_tsec,
2274 const struct task_security_struct *new_tsec)
2275{
2276 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002277 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002278 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002279 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002280
2281 if (!nnp && !nosuid)
2282 return 0; /* neither NNP nor nosuid */
2283
2284 if (new_tsec->sid == old_tsec->sid)
2285 return 0; /* No change in credentials */
2286
2287 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002288 * If the policy enables the nnp_nosuid_transition policy capability,
2289 * then we permit transitions under NNP or nosuid if the
2290 * policy allows the corresponding permission between
2291 * the old and new contexts.
2292 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002293 if (selinux_policycap_nnp_nosuid_transition()) {
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002294 av = 0;
2295 if (nnp)
2296 av |= PROCESS2__NNP_TRANSITION;
2297 if (nosuid)
2298 av |= PROCESS2__NOSUID_TRANSITION;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002299 rc = avc_has_perm(&selinux_state,
2300 old_tsec->sid, new_tsec->sid,
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002301 SECCLASS_PROCESS2, av, NULL);
2302 if (!rc)
2303 return 0;
2304 }
2305
2306 /*
2307 * We also permit NNP or nosuid transitions to bounded SIDs,
2308 * i.e. SIDs that are guaranteed to only be allowed a subset
2309 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002310 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002311 rc = security_bounded_transition(&selinux_state, old_tsec->sid,
2312 new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002313 if (!rc)
2314 return 0;
2315
2316 /*
2317 * On failure, preserve the errno values for NNP vs nosuid.
2318 * NNP: Operation not permitted for caller.
2319 * nosuid: Permission denied to file.
2320 */
2321 if (nnp)
2322 return -EPERM;
2323 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002324}
2325
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05002326static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327{
David Howellsa6f76f22008-11-14 10:39:24 +11002328 const struct task_security_struct *old_tsec;
2329 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002331 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002332 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 int rc;
2334
David Howellsa6f76f22008-11-14 10:39:24 +11002335 /* SELinux context only depends on initial program or script and not
2336 * the script interpreter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002338 old_tsec = selinux_cred(current_cred());
2339 new_tsec = selinux_cred(bprm->cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002340 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
2342 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002343 new_tsec->sid = old_tsec->sid;
2344 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
Michael LeMay28eba5b2006-06-27 02:53:42 -07002346 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002347 new_tsec->create_sid = 0;
2348 new_tsec->keycreate_sid = 0;
2349 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350
David Howellsa6f76f22008-11-14 10:39:24 +11002351 if (old_tsec->exec_sid) {
2352 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002354 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002355
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002356 /* Fail on NNP or nosuid if not an allowed transition. */
2357 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2358 if (rc)
2359 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 } else {
2361 /* Check for a default transition on this program. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002362 rc = security_transition_sid(&selinux_state, old_tsec->sid,
2363 isec->sid, SECCLASS_PROCESS, NULL,
Eric Paris652bb9b2011-02-01 11:05:40 -05002364 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 if (rc)
2366 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002367
2368 /*
2369 * Fallback to old SID on NNP or nosuid if not an allowed
2370 * transition.
2371 */
2372 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2373 if (rc)
2374 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 }
2376
Vivek Goyal43af5de2016-09-09 11:37:49 -04002377 ad.type = LSM_AUDIT_DATA_FILE;
2378 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
David Howellsa6f76f22008-11-14 10:39:24 +11002380 if (new_tsec->sid == old_tsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002381 rc = avc_has_perm(&selinux_state,
2382 old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2384 if (rc)
2385 return rc;
2386 } else {
2387 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002388 rc = avc_has_perm(&selinux_state,
2389 old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2391 if (rc)
2392 return rc;
2393
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002394 rc = avc_has_perm(&selinux_state,
2395 new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2397 if (rc)
2398 return rc;
2399
David Howellsa6f76f22008-11-14 10:39:24 +11002400 /* Check for shared state */
2401 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002402 rc = avc_has_perm(&selinux_state,
2403 old_tsec->sid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002404 SECCLASS_PROCESS, PROCESS__SHARE,
2405 NULL);
2406 if (rc)
2407 return -EPERM;
2408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
David Howellsa6f76f22008-11-14 10:39:24 +11002410 /* Make sure that anyone attempting to ptrace over a task that
2411 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002412 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002413 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002414 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002415 rc = avc_has_perm(&selinux_state,
2416 ptsid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002417 SECCLASS_PROCESS,
2418 PROCESS__PTRACE, NULL);
2419 if (rc)
2420 return -EPERM;
2421 }
2422 }
2423
2424 /* Clear any possibly unsafe personality bits on exec: */
2425 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 /* Enable secure mode for SIDs transitions unless
2428 the noatsecure permission is granted between
2429 the two SIDs, i.e. ahp returns 0. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002430 rc = avc_has_perm(&selinux_state,
2431 old_tsec->sid, new_tsec->sid,
Kees Cook62874c32017-07-18 15:25:25 -07002432 SECCLASS_PROCESS, PROCESS__NOATSECURE,
2433 NULL);
2434 bprm->secureexec |= !!rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 }
2436
Kees Cook62874c32017-07-18 15:25:25 -07002437 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438}
2439
Al Viroc3c073f2012-08-21 22:32:06 -04002440static int match_file(const void *p, struct file *file, unsigned fd)
2441{
2442 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2443}
2444
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002446static inline void flush_unauthorized_files(const struct cred *cred,
2447 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002450 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002451 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002452 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002454 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002456 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002457 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002458 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002459
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002461 Use file_path_has_perm on the tty path directly
2462 rather than using file_has_perm, as this particular
2463 open file may belong to another process and we are
2464 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002465 file_priv = list_first_entry(&tty->tty_files,
2466 struct tty_file_private, list);
2467 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002468 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002469 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
Peter Hurley4a510962016-01-09 21:35:23 -08002471 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002472 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002474 /* Reset controlling tty. */
2475 if (drop_tty)
2476 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
2478 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002479 n = iterate_fd(files, 0, match_file, cred);
2480 if (!n) /* none found? */
2481 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Al Viroc3c073f2012-08-21 22:32:06 -04002483 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002484 if (IS_ERR(devnull))
2485 devnull = NULL;
2486 /* replace all the matching ones with this */
2487 do {
2488 replace_fd(n - 1, devnull, 0);
2489 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2490 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002491 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492}
2493
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494/*
David Howellsa6f76f22008-11-14 10:39:24 +11002495 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 */
David Howellsa6f76f22008-11-14 10:39:24 +11002497static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498{
David Howellsa6f76f22008-11-14 10:39:24 +11002499 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 int rc, i;
2502
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002503 new_tsec = selinux_cred(bprm->cred);
David Howellsa6f76f22008-11-14 10:39:24 +11002504 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 return;
2506
2507 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002508 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
David Howellsa6f76f22008-11-14 10:39:24 +11002510 /* Always clear parent death signal on SID transitions. */
2511 current->pdeath_signal = 0;
2512
2513 /* Check whether the new SID can inherit resource limits from the old
2514 * SID. If not, reset all soft limits to the lower of the current
2515 * task's hard limit and the init task's soft limit.
2516 *
2517 * Note that the setting of hard limits (even to lower them) can be
2518 * controlled by the setrlimit check. The inclusion of the init task's
2519 * soft limit into the computation is to avoid resetting soft limits
2520 * higher than the default soft limit for cases where the default is
2521 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2522 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002523 rc = avc_has_perm(&selinux_state,
2524 new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
David Howellsa6f76f22008-11-14 10:39:24 +11002525 PROCESS__RLIMITINH, NULL);
2526 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002527 /* protect against do_prlimit() */
2528 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002529 for (i = 0; i < RLIM_NLIMITS; i++) {
2530 rlim = current->signal->rlim + i;
2531 initrlim = init_task.signal->rlim + i;
2532 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2533 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002534 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002535 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2536 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002537 }
2538}
2539
2540/*
2541 * Clean up the process immediately after the installation of new credentials
2542 * due to exec
2543 */
2544static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2545{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002546 const struct task_security_struct *tsec = selinux_cred(current_cred());
David Howellsa6f76f22008-11-14 10:39:24 +11002547 u32 osid, sid;
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002548 int rc;
David Howellsa6f76f22008-11-14 10:39:24 +11002549
David Howellsa6f76f22008-11-14 10:39:24 +11002550 osid = tsec->osid;
2551 sid = tsec->sid;
2552
2553 if (sid == osid)
2554 return;
2555
2556 /* Check whether the new SID can inherit signal state from the old SID.
2557 * If not, clear itimers to avoid subsequent signal generation and
2558 * flush and unblock signals.
2559 *
2560 * This must occur _after_ the task SID has been updated so that any
2561 * kill done after the flush will be checked against the new SID.
2562 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002563 rc = avc_has_perm(&selinux_state,
2564 osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 if (rc) {
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002566 clear_itimer();
2567
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002569 if (!fatal_signal_pending(current)) {
2570 flush_sigqueue(&current->pending);
2571 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002572 flush_signal_handlers(current, 1);
2573 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002574 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 spin_unlock_irq(&current->sighand->siglock);
2577 }
2578
David Howellsa6f76f22008-11-14 10:39:24 +11002579 /* Wake up the parent if it is waiting so that it can recheck
2580 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002581 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002582 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002583 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584}
2585
2586/* superblock security operations */
2587
2588static int selinux_sb_alloc_security(struct super_block *sb)
2589{
Paul Moorecb89e242020-01-10 16:32:10 -05002590 struct superblock_security_struct *sbsec;
2591
2592 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
2593 if (!sbsec)
2594 return -ENOMEM;
2595
2596 mutex_init(&sbsec->lock);
2597 INIT_LIST_HEAD(&sbsec->isec_head);
2598 spin_lock_init(&sbsec->isec_lock);
Paul Moorecb89e242020-01-10 16:32:10 -05002599 sbsec->sid = SECINITSID_UNLABELED;
2600 sbsec->def_sid = SECINITSID_FILE;
2601 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
2602 sb->s_security = sbsec;
2603
2604 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605}
2606
2607static void selinux_sb_free_security(struct super_block *sb)
2608{
2609 superblock_free_security(sb);
2610}
2611
Al Viro99dbbb52018-12-14 21:56:23 -05002612static inline int opt_len(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613{
Al Viro99dbbb52018-12-14 21:56:23 -05002614 bool open_quote = false;
2615 int len;
2616 char c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Al Viro99dbbb52018-12-14 21:56:23 -05002618 for (len = 0; (c = s[len]) != '\0'; len++) {
2619 if (c == '"')
Cory Olmo3528a952006-09-29 01:58:44 -07002620 open_quote = !open_quote;
Al Viro99dbbb52018-12-14 21:56:23 -05002621 if (c == ',' && !open_quote)
2622 break;
2623 }
2624 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625}
2626
Al Viro204cc0c2018-12-13 13:41:47 -05002627static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002628{
Al Viro99dbbb52018-12-14 21:56:23 -05002629 char *from = options;
2630 char *to = options;
2631 bool first = true;
Gen Zhangfec63752019-06-12 21:55:38 +08002632 int rc;
Al Viro5b400232018-12-12 20:13:29 -05002633
Al Viro99dbbb52018-12-14 21:56:23 -05002634 while (1) {
2635 int len = opt_len(from);
Gen Zhangfec63752019-06-12 21:55:38 +08002636 int token;
Al Viro99dbbb52018-12-14 21:56:23 -05002637 char *arg = NULL;
2638
2639 token = match_opt_prefix(from, len, &arg);
2640
2641 if (token != Opt_error) {
2642 char *p, *q;
2643
2644 /* strip quotes */
2645 if (arg) {
2646 for (p = q = arg; p < from + len; p++) {
2647 char c = *p;
2648 if (c != '"')
2649 *q++ = c;
2650 }
2651 arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
Gen Zhangfec63752019-06-12 21:55:38 +08002652 if (!arg) {
2653 rc = -ENOMEM;
2654 goto free_opt;
2655 }
Al Viro99dbbb52018-12-14 21:56:23 -05002656 }
2657 rc = selinux_add_opt(token, arg, mnt_opts);
2658 if (unlikely(rc)) {
2659 kfree(arg);
Gen Zhangfec63752019-06-12 21:55:38 +08002660 goto free_opt;
Al Viro99dbbb52018-12-14 21:56:23 -05002661 }
2662 } else {
2663 if (!first) { // copy with preceding comma
2664 from--;
2665 len++;
2666 }
2667 if (to != from)
2668 memmove(to, from, len);
2669 to += len;
2670 first = false;
2671 }
2672 if (!from[len])
2673 break;
2674 from += len + 1;
2675 }
2676 *to = '\0';
2677 return 0;
Gen Zhangfec63752019-06-12 21:55:38 +08002678
2679free_opt:
2680 if (*mnt_opts) {
2681 selinux_free_mnt_opts(*mnt_opts);
2682 *mnt_opts = NULL;
2683 }
2684 return rc;
Al Viro5b400232018-12-12 20:13:29 -05002685}
2686
Al Viro204cc0c2018-12-13 13:41:47 -05002687static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002688{
Al Virobd323652018-12-13 15:04:59 -05002689 struct selinux_mnt_opts *opts = mnt_opts;
Eric Paris026eb162011-03-03 16:09:14 -05002690 struct superblock_security_struct *sbsec = sb->s_security;
Al Virobd323652018-12-13 15:04:59 -05002691 u32 sid;
2692 int rc;
Eric Paris026eb162011-03-03 16:09:14 -05002693
2694 if (!(sbsec->flags & SE_SBINITIALIZED))
2695 return 0;
2696
Al Viro204cc0c2018-12-13 13:41:47 -05002697 if (!opts)
Eric Paris026eb162011-03-03 16:09:14 -05002698 return 0;
2699
Al Virobd323652018-12-13 15:04:59 -05002700 if (opts->fscontext) {
2701 rc = parse_sid(sb, opts->fscontext, &sid);
2702 if (rc)
Al Viroc039bc32018-12-01 23:06:57 -05002703 return rc;
Al Virobd323652018-12-13 15:04:59 -05002704 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2705 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002706 }
Al Virobd323652018-12-13 15:04:59 -05002707 if (opts->context) {
2708 rc = parse_sid(sb, opts->context, &sid);
2709 if (rc)
2710 return rc;
2711 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2712 goto out_bad_option;
2713 }
2714 if (opts->rootcontext) {
2715 struct inode_security_struct *root_isec;
2716 root_isec = backing_inode_security(sb->s_root);
2717 rc = parse_sid(sb, opts->rootcontext, &sid);
2718 if (rc)
2719 return rc;
2720 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2721 goto out_bad_option;
2722 }
2723 if (opts->defcontext) {
2724 rc = parse_sid(sb, opts->defcontext, &sid);
2725 if (rc)
2726 return rc;
2727 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2728 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002729 }
Al Viroc039bc32018-12-01 23:06:57 -05002730 return 0;
Eric Paris026eb162011-03-03 16:09:14 -05002731
Eric Paris026eb162011-03-03 16:09:14 -05002732out_bad_option:
peter enderborgc103a912018-06-12 10:09:03 +02002733 pr_warn("SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002734 "during remount (dev %s, type=%s)\n", sb->s_id,
2735 sb->s_type->name);
Al Viroc039bc32018-12-01 23:06:57 -05002736 return -EINVAL;
Eric Paris026eb162011-03-03 16:09:14 -05002737}
2738
Al Viroa10d7c22018-12-05 11:58:35 -05002739static int selinux_sb_kern_mount(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740{
David Howells88e67f32008-11-14 10:39:21 +11002741 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002742 struct common_audit_data ad;
James Morris74192242008-12-19 11:41:10 +11002743
Eric Paris50c205f2012-04-04 15:01:43 -04002744 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002745 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002746 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747}
2748
David Howells726c3342006-06-23 02:02:58 -07002749static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750{
David Howells88e67f32008-11-14 10:39:21 +11002751 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002752 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
Eric Paris50c205f2012-04-04 15:01:43 -04002754 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002755 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002756 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757}
2758
Al Viro808d4e32012-10-11 11:42:01 -04002759static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002760 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002761 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002762 unsigned long flags,
2763 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764{
David Howells88e67f32008-11-14 10:39:21 +11002765 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766
2767 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002768 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002769 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 else
Eric Paris2875fa02011-04-28 16:04:24 -04002771 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772}
2773
Stephen Smalley98aa0032020-01-17 15:24:07 -05002774static int selinux_move_mount(const struct path *from_path,
2775 const struct path *to_path)
2776{
2777 const struct cred *cred = current_cred();
2778
2779 return path_has_perm(cred, to_path, FILE__MOUNTON);
2780}
2781
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782static int selinux_umount(struct vfsmount *mnt, int flags)
2783{
David Howells88e67f32008-11-14 10:39:21 +11002784 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785
David Howells88e67f32008-11-14 10:39:21 +11002786 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002787 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788}
2789
Al Viro0b520752018-12-23 16:02:47 -05002790static int selinux_fs_context_dup(struct fs_context *fc,
2791 struct fs_context *src_fc)
2792{
2793 const struct selinux_mnt_opts *src = src_fc->security;
2794 struct selinux_mnt_opts *opts;
2795
2796 if (!src)
2797 return 0;
2798
2799 fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
2800 if (!fc->security)
2801 return -ENOMEM;
2802
2803 opts = fc->security;
2804
2805 if (src->fscontext) {
2806 opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
2807 if (!opts->fscontext)
2808 return -ENOMEM;
2809 }
2810 if (src->context) {
2811 opts->context = kstrdup(src->context, GFP_KERNEL);
2812 if (!opts->context)
2813 return -ENOMEM;
2814 }
2815 if (src->rootcontext) {
2816 opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
2817 if (!opts->rootcontext)
2818 return -ENOMEM;
2819 }
2820 if (src->defcontext) {
2821 opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
2822 if (!opts->defcontext)
2823 return -ENOMEM;
2824 }
2825 return 0;
2826}
2827
Al Virod7167b12019-09-07 07:23:15 -04002828static const struct fs_parameter_spec selinux_fs_parameters[] = {
David Howells442155c2018-11-01 23:07:24 +00002829 fsparam_string(CONTEXT_STR, Opt_context),
2830 fsparam_string(DEFCONTEXT_STR, Opt_defcontext),
2831 fsparam_string(FSCONTEXT_STR, Opt_fscontext),
2832 fsparam_string(ROOTCONTEXT_STR, Opt_rootcontext),
2833 fsparam_flag (SECLABEL_STR, Opt_seclabel),
2834 {}
2835};
2836
David Howells442155c2018-11-01 23:07:24 +00002837static int selinux_fs_context_parse_param(struct fs_context *fc,
2838 struct fs_parameter *param)
2839{
2840 struct fs_parse_result result;
2841 int opt, rc;
2842
Al Virod7167b12019-09-07 07:23:15 -04002843 opt = fs_parse(fc, selinux_fs_parameters, param, &result);
David Howells442155c2018-11-01 23:07:24 +00002844 if (opt < 0)
2845 return opt;
2846
2847 rc = selinux_add_opt(opt, param->string, &fc->security);
2848 if (!rc) {
2849 param->string = NULL;
2850 rc = 1;
2851 }
2852 return rc;
2853}
2854
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855/* inode security operations */
2856
2857static int selinux_inode_alloc_security(struct inode *inode)
2858{
Paul Moorecb89e242020-01-10 16:32:10 -05002859 struct inode_security_struct *isec = selinux_inode(inode);
2860 u32 sid = current_sid();
2861
2862 spin_lock_init(&isec->lock);
2863 INIT_LIST_HEAD(&isec->list);
2864 isec->inode = inode;
2865 isec->sid = SECINITSID_UNLABELED;
2866 isec->sclass = SECCLASS_FILE;
2867 isec->task_sid = sid;
2868 isec->initialized = LABEL_INVALID;
2869
2870 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871}
2872
2873static void selinux_inode_free_security(struct inode *inode)
2874{
2875 inode_free_security(inode);
2876}
2877
David Quigleyd47be3d2013-05-22 12:50:34 -04002878static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002879 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002880 u32 *ctxlen)
2881{
David Quigleyd47be3d2013-05-22 12:50:34 -04002882 u32 newsid;
2883 int rc;
2884
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002885 rc = selinux_determine_inode_label(selinux_cred(current_cred()),
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002886 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002887 inode_mode_to_security_class(mode),
2888 &newsid);
2889 if (rc)
2890 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002891
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002892 return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
2893 ctxlen);
David Quigleyd47be3d2013-05-22 12:50:34 -04002894}
2895
Vivek Goyala518b0a2016-07-13 10:44:53 -04002896static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2897 struct qstr *name,
2898 const struct cred *old,
2899 struct cred *new)
2900{
2901 u32 newsid;
2902 int rc;
2903 struct task_security_struct *tsec;
2904
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002905 rc = selinux_determine_inode_label(selinux_cred(old),
Vivek Goyala518b0a2016-07-13 10:44:53 -04002906 d_inode(dentry->d_parent), name,
2907 inode_mode_to_security_class(mode),
2908 &newsid);
2909 if (rc)
2910 return rc;
2911
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002912 tsec = selinux_cred(new);
Vivek Goyala518b0a2016-07-13 10:44:53 -04002913 tsec->create_sid = newsid;
2914 return 0;
2915}
2916
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002917static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002918 const struct qstr *qstr,
2919 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002920 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002921{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002922 const struct task_security_struct *tsec = selinux_cred(current_cred());
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002923 struct superblock_security_struct *sbsec;
Corentin LABBEc0d4f462017-10-04 20:32:17 +02002924 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002925 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002926 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002927
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002928 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002929
David Howells275bb412008-11-14 10:39:19 +11002930 newsid = tsec->create_sid;
2931
Yang Guo210a2922019-12-12 10:02:24 +08002932 rc = selinux_determine_inode_label(tsec, dir, qstr,
David Howellsc3c188b2015-07-10 17:19:58 -04002933 inode_mode_to_security_class(inode->i_mode),
2934 &newsid);
2935 if (rc)
2936 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002937
Eric Paris296fddf2006-09-25 23:32:00 -07002938 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002939 if (sbsec->flags & SE_SBINITIALIZED) {
Casey Schaufler80788c22018-09-21 17:19:11 -07002940 struct inode_security_struct *isec = selinux_inode(inode);
Eric Paris296fddf2006-09-25 23:32:00 -07002941 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2942 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002943 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002944 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002945
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01002946 if (!selinux_initialized(&selinux_state) ||
2947 !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002948 return -EOPNOTSUPP;
2949
Tetsuo Handa95489062013-07-25 05:44:02 +09002950 if (name)
2951 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002952
2953 if (value && len) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002954 rc = security_sid_to_context_force(&selinux_state, newsid,
2955 &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002956 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002957 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002958 *value = context;
2959 *len = clen;
2960 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002961
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002962 return 0;
2963}
2964
Al Viro4acdaf22011-07-26 01:42:34 -04002965static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966{
2967 return may_create(dir, dentry, SECCLASS_FILE);
2968}
2969
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2971{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 return may_link(dir, old_dentry, MAY_LINK);
2973}
2974
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2976{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return may_link(dir, dentry, MAY_UNLINK);
2978}
2979
2980static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2981{
2982 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2983}
2984
Al Viro18bb1db2011-07-26 01:41:39 -04002985static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986{
2987 return may_create(dir, dentry, SECCLASS_DIR);
2988}
2989
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2991{
2992 return may_link(dir, dentry, MAY_RMDIR);
2993}
2994
Al Viro1a67aaf2011-07-26 01:52:52 -04002995static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2998}
2999
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04003001 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002{
3003 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
3004}
3005
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006static int selinux_inode_readlink(struct dentry *dentry)
3007{
David Howells88e67f32008-11-14 10:39:21 +11003008 const struct cred *cred = current_cred();
3009
Eric Paris2875fa02011-04-28 16:04:24 -04003010 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011}
3012
NeilBrownbda0be72015-03-23 13:37:39 +11003013static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
3014 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015{
David Howells88e67f32008-11-14 10:39:21 +11003016 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11003017 struct common_audit_data ad;
3018 struct inode_security_struct *isec;
3019 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
NeilBrownbda0be72015-03-23 13:37:39 +11003021 validate_creds(cred);
3022
3023 ad.type = LSM_AUDIT_DATA_DENTRY;
3024 ad.u.dentry = dentry;
3025 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003026 isec = inode_security_rcu(inode, rcu);
3027 if (IS_ERR(isec))
3028 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11003029
Stephen Smalley1a370792019-11-22 12:22:44 -05003030 return avc_has_perm_flags(&selinux_state,
3031 sid, isec->sid, isec->sclass, FILE__READ, &ad,
3032 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033}
3034
Eric Parisd4cf970d2012-04-04 15:01:42 -04003035static noinline int audit_inode_permission(struct inode *inode,
3036 u32 perms, u32 audited, u32 denied,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003037 int result)
Eric Parisd4cf970d2012-04-04 15:01:42 -04003038{
3039 struct common_audit_data ad;
Casey Schaufler80788c22018-09-21 17:19:11 -07003040 struct inode_security_struct *isec = selinux_inode(inode);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003041 int rc;
3042
Eric Paris50c205f2012-04-04 15:01:43 -04003043 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003044 ad.u.inode = inode;
3045
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003046 rc = slow_avc_audit(&selinux_state,
3047 current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003048 audited, denied, result, &ad);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003049 if (rc)
3050 return rc;
3051 return 0;
3052}
3053
Al Viroe74f71e2011-06-20 19:38:15 -04003054static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055{
David Howells88e67f32008-11-14 10:39:21 +11003056 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003057 u32 perms;
3058 bool from_access;
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003059 bool no_block = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003060 struct inode_security_struct *isec;
3061 u32 sid;
3062 struct av_decision avd;
3063 int rc, rc2;
3064 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Eric Parisb782e0a2010-07-23 11:44:03 -04003066 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003067 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3068
Eric Parisb782e0a2010-07-23 11:44:03 -04003069 /* No permission to check. Existence test. */
3070 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Eric Paris2e334052012-04-04 15:01:42 -04003073 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003074
Eric Paris2e334052012-04-04 15:01:42 -04003075 if (unlikely(IS_PRIVATE(inode)))
3076 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003077
3078 perms = file_mask_to_av(inode->i_mode, mask);
3079
Eric Paris2e334052012-04-04 15:01:42 -04003080 sid = cred_sid(cred);
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003081 isec = inode_security_rcu(inode, no_block);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003082 if (IS_ERR(isec))
3083 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003084
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003085 rc = avc_has_perm_noaudit(&selinux_state,
Stephen Smalley3a28cff2018-12-12 10:10:55 -05003086 sid, isec->sid, isec->sclass, perms,
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003087 no_block ? AVC_NONBLOCKING : 0,
Stephen Smalley3a28cff2018-12-12 10:10:55 -05003088 &avd);
Eric Paris2e334052012-04-04 15:01:42 -04003089 audited = avc_audit_required(perms, &avd, rc,
3090 from_access ? FILE__AUDIT_ACCESS : 0,
3091 &denied);
3092 if (likely(!audited))
3093 return rc;
3094
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003095 /* fall back to ref-walk if we have to generate audit */
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003096 if (no_block)
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003097 return -ECHILD;
3098
3099 rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
Eric Paris2e334052012-04-04 15:01:42 -04003100 if (rc2)
3101 return rc2;
3102 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103}
3104
3105static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3106{
David Howells88e67f32008-11-14 10:39:21 +11003107 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003108 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003109 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003110 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003112 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3113 if (ia_valid & ATTR_FORCE) {
3114 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3115 ATTR_FORCE);
3116 if (!ia_valid)
3117 return 0;
3118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003120 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3121 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003122 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003124 if (selinux_policycap_openperm() &&
Stephen Smalleyccb54472017-05-12 12:41:24 -04003125 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3126 (ia_valid & ATTR_SIZE) &&
3127 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003128 av |= FILE__OPEN;
3129
3130 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131}
3132
Al Viro3f7036a2015-03-08 19:28:30 -04003133static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134{
Al Viro3f7036a2015-03-08 19:28:30 -04003135 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136}
3137
Stephen Smalleydb590002017-04-20 11:31:30 -04003138static bool has_cap_mac_admin(bool audit)
3139{
3140 const struct cred *cred = current_cred();
Micah Mortonc1a85a02019-01-07 16:10:53 -08003141 unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
Stephen Smalleydb590002017-04-20 11:31:30 -04003142
Micah Mortonc1a85a02019-01-07 16:10:53 -08003143 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
Stephen Smalleydb590002017-04-20 11:31:30 -04003144 return false;
Micah Mortonc1a85a02019-01-07 16:10:53 -08003145 if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
Stephen Smalleydb590002017-04-20 11:31:30 -04003146 return false;
3147 return true;
3148}
3149
David Howells8f0cfa52008-04-29 00:59:41 -07003150static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3151 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152{
David Howellsc6f493d2015-03-17 22:26:22 +00003153 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003154 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003156 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003157 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 int rc = 0;
3159
Eric W. Biederman6b240302017-10-02 09:38:20 -05003160 if (strcmp(name, XATTR_NAME_SELINUX)) {
3161 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3162 if (rc)
3163 return rc;
3164
3165 /* Not an attribute we recognize, so just check the
3166 ordinary setattr permission. */
3167 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01003170 if (!selinux_initialized(&selinux_state))
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003171 return (inode_owner_or_capable(inode) ? 0 : -EPERM);
3172
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003174 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 return -EOPNOTSUPP;
3176
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003177 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 return -EPERM;
3179
Eric Paris50c205f2012-04-04 15:01:43 -04003180 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003181 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
Paul Moore20cdef82016-04-04 14:14:42 -04003183 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003184 rc = avc_has_perm(&selinux_state,
3185 sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 FILE__RELABELFROM, &ad);
3187 if (rc)
3188 return rc;
3189
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003190 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3191 GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003192 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003193 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003194 struct audit_buffer *ab;
3195 size_t audit_size;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003196
3197 /* We strip a nul only if it is at the end, otherwise the
3198 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003199 if (value) {
Colin Ian Kingadd24372017-10-14 13:46:55 +01003200 const char *str = value;
3201
Al Viroe3fea3f2012-06-09 08:15:16 +01003202 if (str[size - 1] == '\0')
3203 audit_size = size - 1;
3204 else
3205 audit_size = size;
3206 } else {
Al Viroe3fea3f2012-06-09 08:15:16 +01003207 audit_size = 0;
3208 }
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04003209 ab = audit_log_start(audit_context(),
3210 GFP_ATOMIC, AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04003211 audit_log_format(ab, "op=setxattr invalid_context=");
3212 audit_log_n_untrustedstring(ab, value, audit_size);
3213 audit_log_end(ab);
3214
Stephen Smalley12b29f32008-05-07 13:03:20 -04003215 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003216 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003217 rc = security_context_to_sid_force(&selinux_state, value,
3218 size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 if (rc)
3221 return rc;
3222
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003223 rc = avc_has_perm(&selinux_state,
3224 sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 FILE__RELABELTO, &ad);
3226 if (rc)
3227 return rc;
3228
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003229 rc = security_validate_transition(&selinux_state, isec->sid, newsid,
3230 sid, isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 if (rc)
3232 return rc;
3233
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003234 return avc_has_perm(&selinux_state,
3235 newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 sbsec->sid,
3237 SECCLASS_FILESYSTEM,
3238 FILESYSTEM__ASSOCIATE,
3239 &ad);
3240}
3241
David Howells8f0cfa52008-04-29 00:59:41 -07003242static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003243 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003244 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245{
David Howellsc6f493d2015-03-17 22:26:22 +00003246 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003247 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 u32 newsid;
3249 int rc;
3250
3251 if (strcmp(name, XATTR_NAME_SELINUX)) {
3252 /* Not an attribute we recognize, so nothing to do. */
3253 return;
3254 }
3255
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01003256 if (!selinux_initialized(&selinux_state)) {
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003257 /* If we haven't even been initialized, then we can't validate
3258 * against a policy, so leave the label as invalid. It may
3259 * resolve to a valid label on the next revalidation try if
3260 * we've since initialized.
3261 */
3262 return;
3263 }
3264
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003265 rc = security_context_to_sid_force(&selinux_state, value, size,
3266 &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +02003268 pr_err("SELinux: unable to map context to SID"
Stephen Smalley12b29f32008-05-07 13:03:20 -04003269 "for (%s, %lu), rc=%d\n",
3270 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271 return;
3272 }
3273
Paul Moore20cdef82016-04-04 14:14:42 -04003274 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003275 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003276 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003278 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003279 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003280
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 return;
3282}
3283
David Howells8f0cfa52008-04-29 00:59:41 -07003284static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285{
David Howells88e67f32008-11-14 10:39:21 +11003286 const struct cred *cred = current_cred();
3287
Eric Paris2875fa02011-04-28 16:04:24 -04003288 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289}
3290
Eric Paris828dfe12008-04-17 13:17:49 -04003291static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292{
David Howells88e67f32008-11-14 10:39:21 +11003293 const struct cred *cred = current_cred();
3294
Eric Paris2875fa02011-04-28 16:04:24 -04003295 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296}
3297
David Howells8f0cfa52008-04-29 00:59:41 -07003298static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
Eric W. Biederman6b240302017-10-02 09:38:20 -05003300 if (strcmp(name, XATTR_NAME_SELINUX)) {
3301 int rc = cap_inode_removexattr(dentry, name);
3302 if (rc)
3303 return rc;
3304
3305 /* Not an attribute we recognize, so just check the
3306 ordinary setattr permission. */
3307 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Stephen Smalley9530a3e2020-08-20 13:00:40 -04003310 if (!selinux_initialized(&selinux_state))
3311 return 0;
3312
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 /* No one is allowed to remove a SELinux security label.
3314 You can change the label, but all data must be labeled. */
3315 return -EACCES;
3316}
3317
Aaron Goidelac5656d2019-08-12 11:20:00 -04003318static int selinux_path_notify(const struct path *path, u64 mask,
3319 unsigned int obj_type)
3320{
3321 int ret;
3322 u32 perm;
3323
3324 struct common_audit_data ad;
3325
3326 ad.type = LSM_AUDIT_DATA_PATH;
3327 ad.u.path = *path;
3328
3329 /*
3330 * Set permission needed based on the type of mark being set.
3331 * Performs an additional check for sb watches.
3332 */
3333 switch (obj_type) {
3334 case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
3335 perm = FILE__WATCH_MOUNT;
3336 break;
3337 case FSNOTIFY_OBJ_TYPE_SB:
3338 perm = FILE__WATCH_SB;
3339 ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
3340 FILESYSTEM__WATCH, &ad);
3341 if (ret)
3342 return ret;
3343 break;
3344 case FSNOTIFY_OBJ_TYPE_INODE:
3345 perm = FILE__WATCH;
3346 break;
3347 default:
3348 return -EINVAL;
3349 }
3350
3351 /* blocking watches require the file:watch_with_perm permission */
3352 if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
3353 perm |= FILE__WATCH_WITH_PERM;
3354
3355 /* watches on read-like events need the file:watch_reads permission */
3356 if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3357 perm |= FILE__WATCH_READS;
3358
3359 return path_has_perm(current_cred(), path, perm);
3360}
3361
James Morrisd381d8a2005-10-30 14:59:22 -08003362/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003363 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003364 *
3365 * Permission check is handled by selinux_inode_getxattr hook.
3366 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003367static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
David P. Quigley42492592008-02-04 22:29:39 -08003369 u32 size;
3370 int error;
3371 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003372 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Jonathan Lebonc8e22262020-05-28 10:39:40 -04003374 /*
3375 * If we're not initialized yet, then we can't validate contexts, so
3376 * just let vfs_getxattr fall back to using the on-disk xattr.
3377 */
3378 if (!selinux_initialized(&selinux_state) ||
3379 strcmp(name, XATTR_SELINUX_SUFFIX))
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003380 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003382 /*
3383 * If the caller has CAP_MAC_ADMIN, then get the raw context
3384 * value even if it is not defined by current policy; otherwise,
3385 * use the in-core value under current policy.
3386 * Use the non-auditing forms of the permission checks since
3387 * getxattr may be called by unprivileged processes commonly
3388 * and lack of permission just means that we fall back to the
3389 * in-core context value, not a denial.
3390 */
Paul Moore20cdef82016-04-04 14:14:42 -04003391 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003392 if (has_cap_mac_admin(false))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003393 error = security_sid_to_context_force(&selinux_state,
3394 isec->sid, &context,
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003395 &size);
3396 else
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003397 error = security_sid_to_context(&selinux_state, isec->sid,
3398 &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003399 if (error)
3400 return error;
3401 error = size;
3402 if (alloc) {
3403 *buffer = context;
3404 goto out_nofree;
3405 }
3406 kfree(context);
3407out_nofree:
3408 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409}
3410
3411static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003412 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413{
Paul Moore2c971652016-04-19 16:36:28 -04003414 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01003415 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 u32 newsid;
3417 int rc;
3418
3419 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3420 return -EOPNOTSUPP;
3421
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01003422 if (!(sbsec->flags & SBLABEL_MNT))
3423 return -EOPNOTSUPP;
3424
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 if (!value || !size)
3426 return -EACCES;
3427
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003428 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3429 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 if (rc)
3431 return rc;
3432
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003433 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003434 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003436 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003437 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 return 0;
3439}
3440
3441static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3442{
3443 const int len = sizeof(XATTR_NAME_SELINUX);
Amir Goldsteina9ffe682020-12-19 12:05:27 +02003444
3445 if (!selinux_initialized(&selinux_state))
3446 return 0;
3447
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 if (buffer && len <= buffer_size)
3449 memcpy(buffer, XATTR_NAME_SELINUX, len);
3450 return len;
3451}
3452
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003453static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003454{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003455 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003456 *secid = isec->sid;
3457}
3458
Vivek Goyal56909eb2016-07-13 10:44:48 -04003459static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3460{
3461 u32 sid;
3462 struct task_security_struct *tsec;
3463 struct cred *new_creds = *new;
3464
3465 if (new_creds == NULL) {
3466 new_creds = prepare_creds();
3467 if (!new_creds)
3468 return -ENOMEM;
3469 }
3470
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003471 tsec = selinux_cred(new_creds);
Vivek Goyal56909eb2016-07-13 10:44:48 -04003472 /* Get label from overlay inode and set it in create_sid */
3473 selinux_inode_getsecid(d_inode(src), &sid);
3474 tsec->create_sid = sid;
3475 *new = new_creds;
3476 return 0;
3477}
3478
Vivek Goyal19472b62016-07-13 10:44:50 -04003479static int selinux_inode_copy_up_xattr(const char *name)
3480{
3481 /* The copy_up hook above sets the initial context on an inode, but we
3482 * don't then want to overwrite it by blindly copying all the lower
3483 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3484 */
3485 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3486 return 1; /* Discard */
3487 /*
3488 * Any other attribute apart from SELINUX is not claimed, supported
3489 * by selinux.
3490 */
3491 return -EOPNOTSUPP;
3492}
3493
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003494/* kernfs node operations */
3495
YueHaibingc72c4cd2019-03-22 22:04:00 +08003496static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
3497 struct kernfs_node *kn)
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003498{
Stephen Smalley169ce0c2019-09-04 10:32:48 -04003499 const struct task_security_struct *tsec = selinux_cred(current_cred());
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003500 u32 parent_sid, newsid, clen;
3501 int rc;
3502 char *context;
3503
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003504 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003505 if (rc == -ENODATA)
3506 return 0;
3507 else if (rc < 0)
3508 return rc;
3509
3510 clen = (u32)rc;
3511 context = kmalloc(clen, GFP_KERNEL);
3512 if (!context)
3513 return -ENOMEM;
3514
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003515 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, context, clen);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003516 if (rc < 0) {
3517 kfree(context);
3518 return rc;
3519 }
3520
3521 rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid,
3522 GFP_KERNEL);
3523 kfree(context);
3524 if (rc)
3525 return rc;
3526
3527 if (tsec->create_sid) {
3528 newsid = tsec->create_sid;
3529 } else {
3530 u16 secclass = inode_mode_to_security_class(kn->mode);
3531 struct qstr q;
3532
3533 q.name = kn->name;
3534 q.hash_len = hashlen_string(kn_dir, kn->name);
3535
3536 rc = security_transition_sid(&selinux_state, tsec->sid,
3537 parent_sid, secclass, &q,
3538 &newsid);
3539 if (rc)
3540 return rc;
3541 }
3542
3543 rc = security_sid_to_context_force(&selinux_state, newsid,
3544 &context, &clen);
3545 if (rc)
3546 return rc;
3547
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003548 rc = kernfs_xattr_set(kn, XATTR_NAME_SELINUX, context, clen,
3549 XATTR_CREATE);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003550 kfree(context);
3551 return rc;
3552}
3553
3554
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555/* file security operations */
3556
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003557static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558{
David Howells88e67f32008-11-14 10:39:21 +11003559 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003560 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3563 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3564 mask |= MAY_APPEND;
3565
Paul Moore389fb8002009-03-27 17:10:34 -04003566 return file_has_perm(cred, file,
3567 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568}
3569
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003570static int selinux_file_permission(struct file *file, int mask)
3571{
Al Viro496ad9a2013-01-23 17:07:38 -05003572 struct inode *inode = file_inode(file);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003573 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003574 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003575 u32 sid = current_sid();
3576
Paul Moore389fb8002009-03-27 17:10:34 -04003577 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003578 /* No permission to check. Existence test. */
3579 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003580
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003581 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003582 if (sid == fsec->sid && fsec->isid == isec->sid &&
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003583 fsec->pseqno == avc_policy_seqno(&selinux_state))
Eric Paris83d49852012-04-04 13:45:40 -04003584 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003585 return 0;
3586
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003587 return selinux_revalidate_file_permission(file, mask);
3588}
3589
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590static int selinux_file_alloc_security(struct file *file)
3591{
Paul Moorecb89e242020-01-10 16:32:10 -05003592 struct file_security_struct *fsec = selinux_file(file);
3593 u32 sid = current_sid();
3594
3595 fsec->sid = sid;
3596 fsec->fown_sid = sid;
3597
3598 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599}
3600
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003601/*
3602 * Check whether a task has the ioctl permission and cmd
3603 * operation to an inode.
3604 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003605static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003606 u32 requested, u16 cmd)
3607{
3608 struct common_audit_data ad;
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003609 struct file_security_struct *fsec = selinux_file(file);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003610 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003611 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003612 struct lsm_ioctlop_audit ioctl;
3613 u32 ssid = cred_sid(cred);
3614 int rc;
3615 u8 driver = cmd >> 8;
3616 u8 xperm = cmd & 0xff;
3617
3618 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3619 ad.u.op = &ioctl;
3620 ad.u.op->cmd = cmd;
3621 ad.u.op->path = file->f_path;
3622
3623 if (ssid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003624 rc = avc_has_perm(&selinux_state,
3625 ssid, fsec->sid,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003626 SECCLASS_FD,
3627 FD__USE,
3628 &ad);
3629 if (rc)
3630 goto out;
3631 }
3632
3633 if (unlikely(IS_PRIVATE(inode)))
3634 return 0;
3635
Paul Moore20cdef82016-04-04 14:14:42 -04003636 isec = inode_security(inode);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003637 rc = avc_has_extended_perms(&selinux_state,
3638 ssid, isec->sid, isec->sclass,
3639 requested, driver, xperm, &ad);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003640out:
3641 return rc;
3642}
3643
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3645 unsigned long arg)
3646{
David Howells88e67f32008-11-14 10:39:21 +11003647 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003648 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
Eric Paris0b24dcb2011-02-25 15:39:20 -05003650 switch (cmd) {
3651 case FIONREAD:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003652 case FIBMAP:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003653 case FIGETBSZ:
Al Viro2f99c362012-03-23 16:04:05 -04003654 case FS_IOC_GETFLAGS:
Al Viro2f99c362012-03-23 16:04:05 -04003655 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003656 error = file_has_perm(cred, file, FILE__GETATTR);
3657 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
Al Viro2f99c362012-03-23 16:04:05 -04003659 case FS_IOC_SETFLAGS:
Al Viro2f99c362012-03-23 16:04:05 -04003660 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003661 error = file_has_perm(cred, file, FILE__SETATTR);
3662 break;
3663
3664 /* sys_ioctl() checks */
3665 case FIONBIO:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003666 case FIOASYNC:
3667 error = file_has_perm(cred, file, 0);
3668 break;
3669
3670 case KDSKBENT:
3671 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003672 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Micah Mortonc1a85a02019-01-07 16:10:53 -08003673 CAP_OPT_NONE, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003674 break;
3675
3676 /* default case assumes that the command will go
3677 * to the file's ioctl() function.
3678 */
3679 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003680 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003681 }
3682 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683}
3684
Stephen Smalleyb78b7d52020-01-08 12:23:56 -05003685static int default_noexec __ro_after_init;
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003686
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3688{
David Howells88e67f32008-11-14 10:39:21 +11003689 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003690 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003691 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003692
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003693 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003694 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3695 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 /*
3697 * We are making executable an anonymous mapping or a
3698 * private file mapping that will also be writable.
3699 * This has an additional check.
3700 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003701 rc = avc_has_perm(&selinux_state,
3702 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003703 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003705 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
3708 if (file) {
3709 /* read access is always possible with a mapping */
3710 u32 av = FILE__READ;
3711
3712 /* write access only matters if the mapping is shared */
3713 if (shared && (prot & PROT_WRITE))
3714 av |= FILE__WRITE;
3715
3716 if (prot & PROT_EXEC)
3717 av |= FILE__EXECUTE;
3718
David Howells88e67f32008-11-14 10:39:21 +11003719 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 }
David Howellsd84f4f92008-11-14 10:39:23 +11003721
3722error:
3723 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724}
3725
Al Viroe5467852012-05-30 13:30:51 -04003726static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003728 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003729
3730 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3731 u32 sid = current_sid();
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003732 rc = avc_has_perm(&selinux_state,
3733 sid, sid, SECCLASS_MEMPROTECT,
Paul Moore98883bf2014-03-19 16:46:11 -04003734 MEMPROTECT__MMAP_ZERO, NULL);
3735 }
3736
3737 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003738}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
Al Viroe5467852012-05-30 13:30:51 -04003740static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3741 unsigned long prot, unsigned long flags)
3742{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003743 struct common_audit_data ad;
3744 int rc;
3745
3746 if (file) {
3747 ad.type = LSM_AUDIT_DATA_FILE;
3748 ad.u.file = file;
3749 rc = inode_has_perm(current_cred(), file_inode(file),
3750 FILE__MAP, &ad);
3751 if (rc)
3752 return rc;
3753 }
3754
Lakshmi Ramasubramanian8861d0a2020-09-14 10:31:57 -07003755 if (checkreqprot_get(&selinux_state))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 prot = reqprot;
3757
3758 return file_map_prot_check(file, prot,
3759 (flags & MAP_TYPE) == MAP_SHARED);
3760}
3761
3762static int selinux_file_mprotect(struct vm_area_struct *vma,
3763 unsigned long reqprot,
3764 unsigned long prot)
3765{
David Howells88e67f32008-11-14 10:39:21 +11003766 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003767 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
Lakshmi Ramasubramanian8861d0a2020-09-14 10:31:57 -07003769 if (checkreqprot_get(&selinux_state))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 prot = reqprot;
3771
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003772 if (default_noexec &&
3773 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003774 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003775 if (vma->vm_start >= vma->vm_mm->start_brk &&
3776 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003777 rc = avc_has_perm(&selinux_state,
3778 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003779 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003780 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003781 ((vma->vm_start <= vma->vm_mm->start_stack &&
3782 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003783 vma_is_stack_for_current(vma))) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003784 rc = avc_has_perm(&selinux_state,
3785 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003786 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003787 } else if (vma->vm_file && vma->anon_vma) {
3788 /*
3789 * We are making executable a file mapping that has
3790 * had some COW done. Since pages might have been
3791 * written, check ability to execute the possibly
3792 * modified content. This typically should only
3793 * occur for text relocations.
3794 */
David Howellsd84f4f92008-11-14 10:39:23 +11003795 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003796 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003797 if (rc)
3798 return rc;
3799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800
3801 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3802}
3803
3804static int selinux_file_lock(struct file *file, unsigned int cmd)
3805{
David Howells88e67f32008-11-14 10:39:21 +11003806 const struct cred *cred = current_cred();
3807
3808 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809}
3810
3811static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3812 unsigned long arg)
3813{
David Howells88e67f32008-11-14 10:39:21 +11003814 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 int err = 0;
3816
3817 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003818 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003819 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003820 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003822 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05003823 fallthrough;
Eric Paris828dfe12008-04-17 13:17:49 -04003824 case F_SETOWN:
3825 case F_SETSIG:
3826 case F_GETFL:
3827 case F_GETOWN:
3828 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003829 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003830 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003831 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003832 break;
3833 case F_GETLK:
3834 case F_SETLK:
3835 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003836 case F_OFD_GETLK:
3837 case F_OFD_SETLK:
3838 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003840 case F_GETLK64:
3841 case F_SETLK64:
3842 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843#endif
David Howells88e67f32008-11-14 10:39:21 +11003844 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003845 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 }
3847
3848 return err;
3849}
3850
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003851static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 struct file_security_struct *fsec;
3854
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003855 fsec = selinux_file(file);
David Howells275bb412008-11-14 10:39:19 +11003856 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857}
3858
3859static int selinux_file_send_sigiotask(struct task_struct *tsk,
3860 struct fown_struct *fown, int signum)
3861{
Eric Paris828dfe12008-04-17 13:17:49 -04003862 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003863 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 struct file_security_struct *fsec;
3866
3867 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003868 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003870 fsec = selinux_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
3872 if (!signum)
3873 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3874 else
3875 perm = signal_to_av(signum);
3876
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003877 return avc_has_perm(&selinux_state,
3878 fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 SECCLASS_PROCESS, perm, NULL);
3880}
3881
3882static int selinux_file_receive(struct file *file)
3883{
David Howells88e67f32008-11-14 10:39:21 +11003884 const struct cred *cred = current_cred();
3885
3886 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887}
3888
Al Viro94817692018-07-10 14:13:18 -04003889static int selinux_file_open(struct file *file)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003890{
3891 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003892 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003893
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003894 fsec = selinux_file(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003895 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003896 /*
3897 * Save inode label and policy sequence number
3898 * at open-time so that selinux_file_permission
3899 * can determine whether revalidation is necessary.
3900 * Task label is already saved in the file security
3901 * struct as its SID.
3902 */
3903 fsec->isid = isec->sid;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003904 fsec->pseqno = avc_policy_seqno(&selinux_state);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003905 /*
3906 * Since the inode label or policy seqno may have changed
3907 * between the selinux_inode_permission check and the saving
3908 * of state above, recheck that access is still permitted.
3909 * Otherwise, access might never be revalidated against the
3910 * new inode label or new policy.
3911 * This check is not redundant - do not remove.
3912 */
Al Viro94817692018-07-10 14:13:18 -04003913 return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003914}
3915
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916/* task security operations */
3917
Tetsuo Handaa79be232017-03-28 23:08:45 +09003918static int selinux_task_alloc(struct task_struct *task,
3919 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003921 u32 sid = current_sid();
3922
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003923 return avc_has_perm(&selinux_state,
3924 sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925}
3926
David Howellsf1752ee2008-11-14 10:39:17 +11003927/*
David Howellsd84f4f92008-11-14 10:39:23 +11003928 * prepare a new set of credentials for modification
3929 */
3930static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3931 gfp_t gfp)
3932{
Casey Schauflerbbd36622018-11-12 09:30:56 -08003933 const struct task_security_struct *old_tsec = selinux_cred(old);
3934 struct task_security_struct *tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11003935
Casey Schauflerbbd36622018-11-12 09:30:56 -08003936 *tsec = *old_tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11003937 return 0;
3938}
3939
3940/*
David Howellsee18d642009-09-02 09:14:21 +01003941 * transfer the SELinux data to a blank set of creds
3942 */
3943static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3944{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003945 const struct task_security_struct *old_tsec = selinux_cred(old);
3946 struct task_security_struct *tsec = selinux_cred(new);
David Howellsee18d642009-09-02 09:14:21 +01003947
3948 *tsec = *old_tsec;
3949}
3950
Matthew Garrett3ec30112018-01-08 13:36:19 -08003951static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3952{
3953 *secid = cred_sid(c);
3954}
3955
David Howellsee18d642009-09-02 09:14:21 +01003956/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003957 * set the security data for a kernel service
3958 * - all the creation contexts are set to unlabelled
3959 */
3960static int selinux_kernel_act_as(struct cred *new, u32 secid)
3961{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003962 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003963 u32 sid = current_sid();
3964 int ret;
3965
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003966 ret = avc_has_perm(&selinux_state,
3967 sid, secid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003968 SECCLASS_KERNEL_SERVICE,
3969 KERNEL_SERVICE__USE_AS_OVERRIDE,
3970 NULL);
3971 if (ret == 0) {
3972 tsec->sid = secid;
3973 tsec->create_sid = 0;
3974 tsec->keycreate_sid = 0;
3975 tsec->sockcreate_sid = 0;
3976 }
3977 return ret;
3978}
3979
3980/*
3981 * set the file creation context in a security record to the same as the
3982 * objective context of the specified inode
3983 */
3984static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3985{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003986 struct inode_security_struct *isec = inode_security(inode);
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003987 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003988 u32 sid = current_sid();
3989 int ret;
3990
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003991 ret = avc_has_perm(&selinux_state,
3992 sid, isec->sid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003993 SECCLASS_KERNEL_SERVICE,
3994 KERNEL_SERVICE__CREATE_FILES_AS,
3995 NULL);
3996
3997 if (ret == 0)
3998 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003999 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11004000}
4001
Eric Parisdd8dbf22009-11-03 16:35:32 +11004002static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04004003{
Eric Parisdd8dbf22009-11-03 16:35:32 +11004004 struct common_audit_data ad;
4005
Eric Paris50c205f2012-04-04 15:01:43 -04004006 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11004007 ad.u.kmod_name = kmod_name;
4008
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004009 return avc_has_perm(&selinux_state,
4010 current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11004011 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04004012}
4013
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004014static int selinux_kernel_module_from_file(struct file *file)
4015{
4016 struct common_audit_data ad;
4017 struct inode_security_struct *isec;
4018 struct file_security_struct *fsec;
4019 u32 sid = current_sid();
4020 int rc;
4021
4022 /* init_module */
4023 if (file == NULL)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004024 return avc_has_perm(&selinux_state,
4025 sid, sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004026 SYSTEM__MODULE_LOAD, NULL);
4027
4028 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04004029
Vivek Goyal43af5de2016-09-09 11:37:49 -04004030 ad.type = LSM_AUDIT_DATA_FILE;
4031 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004032
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07004033 fsec = selinux_file(file);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004034 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004035 rc = avc_has_perm(&selinux_state,
4036 sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004037 if (rc)
4038 return rc;
4039 }
4040
Paul Moore20cdef82016-04-04 14:14:42 -04004041 isec = inode_security(file_inode(file));
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004042 return avc_has_perm(&selinux_state,
4043 sid, isec->sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004044 SYSTEM__MODULE_LOAD, &ad);
4045}
4046
4047static int selinux_kernel_read_file(struct file *file,
Kees Cook2039bda2020-10-02 10:38:23 -07004048 enum kernel_read_file_id id,
4049 bool contents)
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004050{
4051 int rc = 0;
4052
4053 switch (id) {
4054 case READING_MODULE:
Kees Cook2039bda2020-10-02 10:38:23 -07004055 rc = selinux_kernel_module_from_file(contents ? file : NULL);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004056 break;
4057 default:
4058 break;
4059 }
4060
4061 return rc;
4062}
4063
Kees Cookb64fcae2020-10-02 10:38:20 -07004064static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04004065{
4066 int rc = 0;
4067
4068 switch (id) {
4069 case LOADING_MODULE:
4070 rc = selinux_kernel_module_from_file(NULL);
Gustavo A. R. Silvab2d99bc2020-11-20 12:32:26 -06004071 break;
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04004072 default:
4073 break;
4074 }
4075
4076 return rc;
4077}
4078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
4080{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004081 return avc_has_perm(&selinux_state,
4082 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004083 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084}
4085
4086static int selinux_task_getpgid(struct task_struct *p)
4087{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004088 return avc_has_perm(&selinux_state,
4089 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004090 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091}
4092
4093static int selinux_task_getsid(struct task_struct *p)
4094{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004095 return avc_has_perm(&selinux_state,
4096 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004097 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098}
4099
David Quigleyf9008e4c2006-06-30 01:55:46 -07004100static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
4101{
David Howells275bb412008-11-14 10:39:19 +11004102 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07004103}
4104
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105static int selinux_task_setnice(struct task_struct *p, int nice)
4106{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004107 return avc_has_perm(&selinux_state,
4108 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004109 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110}
4111
James Morris03e68062006-06-23 02:03:58 -07004112static int selinux_task_setioprio(struct task_struct *p, int ioprio)
4113{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004114 return avc_has_perm(&selinux_state,
4115 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004116 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07004117}
4118
David Quigleya1836a42006-06-30 01:55:49 -07004119static int selinux_task_getioprio(struct task_struct *p)
4120{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004121 return avc_has_perm(&selinux_state,
4122 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004123 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07004124}
4125
Corentin LABBE42985552017-10-04 20:32:18 +02004126static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
4127 unsigned int flags)
Stephen Smalley791ec492017-02-17 07:57:00 -05004128{
4129 u32 av = 0;
4130
Stephen Smalley84e68852017-02-28 09:35:08 -05004131 if (!flags)
4132 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05004133 if (flags & LSM_PRLIMIT_WRITE)
4134 av |= PROCESS__SETRLIMIT;
4135 if (flags & LSM_PRLIMIT_READ)
4136 av |= PROCESS__GETRLIMIT;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004137 return avc_has_perm(&selinux_state,
4138 cred_sid(cred), cred_sid(tcred),
Stephen Smalley791ec492017-02-17 07:57:00 -05004139 SECCLASS_PROCESS, av, NULL);
4140}
4141
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004142static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
4143 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004145 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
4147 /* Control the ability to change the hard limit (whether
4148 lowering or raising it), so that the hard limit can
4149 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11004150 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004152 return avc_has_perm(&selinux_state,
4153 current_sid(), task_sid(p),
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004154 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
4156 return 0;
4157}
4158
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09004159static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004161 return avc_has_perm(&selinux_state,
4162 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004163 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164}
4165
4166static int selinux_task_getscheduler(struct task_struct *p)
4167{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004168 return avc_has_perm(&selinux_state,
4169 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004170 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171}
4172
David Quigley35601542006-06-23 02:04:01 -07004173static int selinux_task_movememory(struct task_struct *p)
4174{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004175 return avc_has_perm(&selinux_state,
4176 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004177 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07004178}
4179
Eric W. Biedermanae7795b2018-09-25 11:27:20 +02004180static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004181 int sig, const struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182{
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004183 u32 secid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 if (!sig)
4187 perm = PROCESS__SIGNULL; /* null signal; existence test */
4188 else
4189 perm = signal_to_av(sig);
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004190 if (!cred)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004191 secid = current_sid();
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004192 else
4193 secid = cred_sid(cred);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004194 return avc_has_perm(&selinux_state,
4195 secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196}
4197
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198static void selinux_task_to_inode(struct task_struct *p,
4199 struct inode *inode)
4200{
Casey Schaufler80788c22018-09-21 17:19:11 -07004201 struct inode_security_struct *isec = selinux_inode(inode);
David Howells275bb412008-11-14 10:39:19 +11004202 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004204 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004205 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004206 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004207 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004208 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209}
4210
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004212static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004213 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214{
4215 int offset, ihlen, ret = -EINVAL;
4216 struct iphdr _iph, *ih;
4217
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004218 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4220 if (ih == NULL)
4221 goto out;
4222
4223 ihlen = ih->ihl * 4;
4224 if (ihlen < sizeof(_iph))
4225 goto out;
4226
Eric Paris48c62af2012-04-02 13:15:44 -04004227 ad->u.net->v4info.saddr = ih->saddr;
4228 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 ret = 0;
4230
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004231 if (proto)
4232 *proto = ih->protocol;
4233
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004235 case IPPROTO_TCP: {
4236 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
Eric Paris828dfe12008-04-17 13:17:49 -04004238 if (ntohs(ih->frag_off) & IP_OFFSET)
4239 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
4241 offset += ihlen;
4242 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4243 if (th == NULL)
4244 break;
4245
Eric Paris48c62af2012-04-02 13:15:44 -04004246 ad->u.net->sport = th->source;
4247 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Eric Paris828dfe12008-04-17 13:17:49 -04004251 case IPPROTO_UDP: {
4252 struct udphdr _udph, *uh;
4253
4254 if (ntohs(ih->frag_off) & IP_OFFSET)
4255 break;
4256
4257 offset += ihlen;
4258 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4259 if (uh == NULL)
4260 break;
4261
Eric Paris48c62af2012-04-02 13:15:44 -04004262 ad->u.net->sport = uh->source;
4263 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004264 break;
4265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
James Morris2ee92d42006-11-13 16:09:01 -08004267 case IPPROTO_DCCP: {
4268 struct dccp_hdr _dccph, *dh;
4269
4270 if (ntohs(ih->frag_off) & IP_OFFSET)
4271 break;
4272
4273 offset += ihlen;
4274 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4275 if (dh == NULL)
4276 break;
4277
Eric Paris48c62af2012-04-02 13:15:44 -04004278 ad->u.net->sport = dh->dccph_sport;
4279 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004280 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004281 }
James Morris2ee92d42006-11-13 16:09:01 -08004282
Richard Hainesd4529302018-02-13 20:57:18 +00004283#if IS_ENABLED(CONFIG_IP_SCTP)
4284 case IPPROTO_SCTP: {
4285 struct sctphdr _sctph, *sh;
4286
4287 if (ntohs(ih->frag_off) & IP_OFFSET)
4288 break;
4289
4290 offset += ihlen;
4291 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4292 if (sh == NULL)
4293 break;
4294
4295 ad->u.net->sport = sh->source;
4296 ad->u.net->dport = sh->dest;
4297 break;
4298 }
4299#endif
Eric Paris828dfe12008-04-17 13:17:49 -04004300 default:
4301 break;
4302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303out:
4304 return ret;
4305}
4306
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004307#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
4309/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004310static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004311 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312{
4313 u8 nexthdr;
4314 int ret = -EINVAL, offset;
4315 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004316 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004318 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4320 if (ip6 == NULL)
4321 goto out;
4322
Eric Paris48c62af2012-04-02 13:15:44 -04004323 ad->u.net->v6info.saddr = ip6->saddr;
4324 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 ret = 0;
4326
4327 nexthdr = ip6->nexthdr;
4328 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004329 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 if (offset < 0)
4331 goto out;
4332
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004333 if (proto)
4334 *proto = nexthdr;
4335
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 switch (nexthdr) {
4337 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004338 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
4340 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4341 if (th == NULL)
4342 break;
4343
Eric Paris48c62af2012-04-02 13:15:44 -04004344 ad->u.net->sport = th->source;
4345 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 break;
4347 }
4348
4349 case IPPROTO_UDP: {
4350 struct udphdr _udph, *uh;
4351
4352 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4353 if (uh == NULL)
4354 break;
4355
Eric Paris48c62af2012-04-02 13:15:44 -04004356 ad->u.net->sport = uh->source;
4357 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358 break;
4359 }
4360
James Morris2ee92d42006-11-13 16:09:01 -08004361 case IPPROTO_DCCP: {
4362 struct dccp_hdr _dccph, *dh;
4363
4364 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4365 if (dh == NULL)
4366 break;
4367
Eric Paris48c62af2012-04-02 13:15:44 -04004368 ad->u.net->sport = dh->dccph_sport;
4369 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004370 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004371 }
James Morris2ee92d42006-11-13 16:09:01 -08004372
Richard Hainesd4529302018-02-13 20:57:18 +00004373#if IS_ENABLED(CONFIG_IP_SCTP)
4374 case IPPROTO_SCTP: {
4375 struct sctphdr _sctph, *sh;
4376
4377 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4378 if (sh == NULL)
4379 break;
4380
4381 ad->u.net->sport = sh->source;
4382 ad->u.net->dport = sh->dest;
4383 break;
4384 }
4385#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 /* includes fragments */
4387 default:
4388 break;
4389 }
4390out:
4391 return ret;
4392}
4393
4394#endif /* IPV6 */
4395
Thomas Liu2bf49692009-07-14 12:14:09 -04004396static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004397 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398{
David Howellscf9481e2008-07-27 21:31:07 +10004399 char *addrp;
4400 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Eric Paris48c62af2012-04-02 13:15:44 -04004402 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004404 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004405 if (ret)
4406 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004407 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4408 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004409 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004411#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004413 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004414 if (ret)
4415 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004416 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4417 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004418 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419#endif /* IPV6 */
4420 default:
David Howellscf9481e2008-07-27 21:31:07 +10004421 addrp = NULL;
4422 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 }
4424
David Howellscf9481e2008-07-27 21:31:07 +10004425parse_error:
peter enderborgc103a912018-06-12 10:09:03 +02004426 pr_warn(
David Howellscf9481e2008-07-27 21:31:07 +10004427 "SELinux: failure in selinux_parse_skb(),"
4428 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004430
4431okay:
4432 if (_addrp)
4433 *_addrp = addrp;
4434 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435}
4436
Paul Moore4f6a9932007-03-01 14:35:22 -05004437/**
Paul Moore220deb92008-01-29 08:38:23 -05004438 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004439 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004440 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004441 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004442 *
4443 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004444 * Check the various different forms of network peer labeling and determine
4445 * the peer label/SID for the packet; most of the magic actually occurs in
4446 * the security server function security_net_peersid_cmp(). The function
4447 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4448 * or -EACCES if @sid is invalid due to inconsistencies with the different
4449 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004450 *
4451 */
Paul Moore220deb92008-01-29 08:38:23 -05004452static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004453{
Paul Moore71f1cb02008-01-29 08:51:16 -05004454 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004455 u32 xfrm_sid;
4456 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004457 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004458
Paul Moore817eff72013-12-10 14:57:54 -05004459 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004460 if (unlikely(err))
4461 return -EACCES;
4462 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4463 if (unlikely(err))
4464 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004465
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004466 err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
4467 nlbl_type, xfrm_sid, sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004468 if (unlikely(err)) {
peter enderborgc103a912018-06-12 10:09:03 +02004469 pr_warn(
Paul Moore71f1cb02008-01-29 08:51:16 -05004470 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4471 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004472 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004473 }
Paul Moore220deb92008-01-29 08:38:23 -05004474
4475 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004476}
4477
Paul Moore446b8022013-12-04 16:10:51 -05004478/**
4479 * selinux_conn_sid - Determine the child socket label for a connection
4480 * @sk_sid: the parent socket's SID
4481 * @skb_sid: the packet's SID
4482 * @conn_sid: the resulting connection SID
4483 *
4484 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4485 * combined with the MLS information from @skb_sid in order to create
Randy Dunlapc76a2f92020-08-07 09:51:34 -07004486 * @conn_sid. If @skb_sid is not valid then @conn_sid is simply a copy
Paul Moore446b8022013-12-04 16:10:51 -05004487 * of @sk_sid. Returns zero on success, negative values on failure.
4488 *
4489 */
4490static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4491{
4492 int err = 0;
4493
4494 if (skb_sid != SECSID_NULL)
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004495 err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
4496 conn_sid);
Paul Moore446b8022013-12-04 16:10:51 -05004497 else
4498 *conn_sid = sk_sid;
4499
4500 return err;
4501}
4502
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004504
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004505static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4506 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004507{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004508 if (tsec->sockcreate_sid > SECSID_NULL) {
4509 *socksid = tsec->sockcreate_sid;
4510 return 0;
4511 }
4512
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004513 return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
4514 secclass, NULL, socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004515}
4516
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004517static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518{
Paul Moore253bfae2010-04-22 14:46:19 -04004519 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004520 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004521 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522
Paul Moore253bfae2010-04-22 14:46:19 -04004523 if (sksec->sid == SECINITSID_KERNEL)
4524 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Eric Paris50c205f2012-04-04 15:01:43 -04004526 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004527 ad.u.net = &net;
4528 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004530 return avc_has_perm(&selinux_state,
4531 current_sid(), sksec->sid, sksec->sclass, perms,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004532 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533}
4534
4535static int selinux_socket_create(int family, int type,
4536 int protocol, int kern)
4537{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004538 const struct task_security_struct *tsec = selinux_cred(current_cred());
Paul Moored4f2d972010-04-22 14:46:18 -04004539 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004540 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004541 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542
4543 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004544 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545
David Howells275bb412008-11-14 10:39:19 +11004546 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004547 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4548 if (rc)
4549 return rc;
4550
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004551 return avc_has_perm(&selinux_state,
4552 tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553}
4554
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004555static int selinux_socket_post_create(struct socket *sock, int family,
4556 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004558 const struct task_security_struct *tsec = selinux_cred(current_cred());
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004559 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004560 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004561 u16 sclass = socket_type_to_security_class(family, type, protocol);
4562 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004563 int err = 0;
4564
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004565 if (!kern) {
4566 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004567 if (err)
4568 return err;
4569 }
David Howells275bb412008-11-14 10:39:19 +11004570
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004571 isec->sclass = sclass;
4572 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004573 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004575 if (sock->sk) {
4576 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004577 sksec->sclass = sclass;
4578 sksec->sid = sid;
Richard Hainesd4529302018-02-13 20:57:18 +00004579 /* Allows detection of the first association on this socket */
4580 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4581 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4582
Paul Moore389fb8002009-03-27 17:10:34 -04004583 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004584 }
4585
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004586 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587}
4588
David Herrmann0b811db2018-05-04 16:28:21 +02004589static int selinux_socket_socketpair(struct socket *socka,
4590 struct socket *sockb)
4591{
4592 struct sk_security_struct *sksec_a = socka->sk->sk_security;
4593 struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4594
4595 sksec_a->peer_sid = sksec_b->sid;
4596 sksec_b->peer_sid = sksec_a->sid;
4597
4598 return 0;
4599}
4600
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601/* Range of port numbers used to automatically bind.
4602 Need to determine whether we should perform a name_bind
4603 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604
4605static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4606{
Paul Moore253bfae2010-04-22 14:46:19 -04004607 struct sock *sk = sock->sk;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004608 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 u16 family;
4610 int err;
4611
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004612 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 if (err)
4614 goto out;
4615
Richard Hainesd4529302018-02-13 20:57:18 +00004616 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
Paul Moore253bfae2010-04-22 14:46:19 -04004617 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 if (family == PF_INET || family == PF_INET6) {
4619 char *addrp;
Thomas Liu2bf49692009-07-14 12:14:09 -04004620 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004621 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 struct sockaddr_in *addr4 = NULL;
4623 struct sockaddr_in6 *addr6 = NULL;
Tetsuo Handac750e692019-04-12 19:59:34 +09004624 u16 family_sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004626 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627
Richard Hainesd4529302018-02-13 20:57:18 +00004628 /*
4629 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4630 * that validates multiple binding addresses. Because of this
4631 * need to check address->sa_family as it is possible to have
4632 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4633 */
Tetsuo Handac750e692019-04-12 19:59:34 +09004634 if (addrlen < offsetofend(struct sockaddr, sa_family))
4635 return -EINVAL;
4636 family_sa = address->sa_family;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004637 switch (family_sa) {
4638 case AF_UNSPEC:
Richard Haines68741a8a2018-03-02 19:54:34 +00004639 case AF_INET:
4640 if (addrlen < sizeof(struct sockaddr_in))
4641 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642 addr4 = (struct sockaddr_in *)address;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004643 if (family_sa == AF_UNSPEC) {
4644 /* see __inet_bind(), we only want to allow
4645 * AF_UNSPEC if the address is INADDR_ANY
4646 */
4647 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4648 goto err_af;
4649 family_sa = AF_INET;
4650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 addrp = (char *)&addr4->sin_addr.s_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004653 break;
4654 case AF_INET6:
4655 if (addrlen < SIN6_LEN_RFC2133)
4656 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657 addr6 = (struct sockaddr_in6 *)address;
4658 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 addrp = (char *)&addr6->sin6_addr.s6_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004660 break;
4661 default:
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004662 goto err_af;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 }
4664
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004665 ad.type = LSM_AUDIT_DATA_NET;
4666 ad.u.net = &net;
4667 ad.u.net->sport = htons(snum);
4668 ad.u.net->family = family_sa;
4669
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004670 if (snum) {
4671 int low, high;
4672
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004673 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004674
Maciej Żenczykowski82f31eb2019-11-25 15:37:04 -08004675 if (inet_port_requires_bind_service(sock_net(sk), snum) ||
4676 snum < low || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004677 err = sel_netport_sid(sk->sk_protocol,
4678 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004679 if (err)
4680 goto out;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004681 err = avc_has_perm(&selinux_state,
4682 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004683 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004684 SOCKET__NAME_BIND, &ad);
4685 if (err)
4686 goto out;
4687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 }
Eric Paris828dfe12008-04-17 13:17:49 -04004689
Paul Moore253bfae2010-04-22 14:46:19 -04004690 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004691 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692 node_perm = TCP_SOCKET__NODE_BIND;
4693 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004694
James Morris13402582005-09-30 14:24:34 -04004695 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696 node_perm = UDP_SOCKET__NODE_BIND;
4697 break;
James Morris2ee92d42006-11-13 16:09:01 -08004698
4699 case SECCLASS_DCCP_SOCKET:
4700 node_perm = DCCP_SOCKET__NODE_BIND;
4701 break;
4702
Richard Hainesd4529302018-02-13 20:57:18 +00004703 case SECCLASS_SCTP_SOCKET:
4704 node_perm = SCTP_SOCKET__NODE_BIND;
4705 break;
4706
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707 default:
4708 node_perm = RAWIP_SOCKET__NODE_BIND;
4709 break;
4710 }
Eric Paris828dfe12008-04-17 13:17:49 -04004711
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004712 err = sel_netnode_sid(addrp, family_sa, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713 if (err)
4714 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004715
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004716 if (family_sa == AF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004717 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718 else
Eric Paris48c62af2012-04-02 13:15:44 -04004719 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004721 err = avc_has_perm(&selinux_state,
4722 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004723 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724 if (err)
4725 goto out;
4726 }
4727out:
4728 return err;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004729err_af:
4730 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4731 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4732 return -EINVAL;
4733 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734}
4735
Richard Hainesd4529302018-02-13 20:57:18 +00004736/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
Kees Cookd61330c2019-02-17 14:08:36 -08004737 * and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
Richard Hainesd4529302018-02-13 20:57:18 +00004738 */
4739static int selinux_socket_connect_helper(struct socket *sock,
4740 struct sockaddr *address, int addrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741{
Paul Moore014ab192008-10-10 10:16:33 -04004742 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004743 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744 int err;
4745
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004746 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747 if (err)
4748 return err;
Paolo Abeni05174c92019-05-10 19:12:33 +02004749 if (addrlen < offsetofend(struct sockaddr, sa_family))
4750 return -EINVAL;
4751
4752 /* connect(AF_UNSPEC) has special handling, as it is a documented
4753 * way to disconnect the socket
4754 */
4755 if (address->sa_family == AF_UNSPEC)
4756 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757
4758 /*
Richard Hainesd4529302018-02-13 20:57:18 +00004759 * If a TCP, DCCP or SCTP socket, check name_connect permission
4760 * for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761 */
Paul Moore253bfae2010-04-22 14:46:19 -04004762 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004763 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4764 sksec->sclass == SECCLASS_SCTP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004765 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004766 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 struct sockaddr_in *addr4 = NULL;
4768 struct sockaddr_in6 *addr6 = NULL;
4769 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004770 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771
Richard Hainesd4529302018-02-13 20:57:18 +00004772 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4773 * that validates multiple connect addresses. Because of this
4774 * need to check address->sa_family as it is possible to have
4775 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4776 */
Richard Haines68741a8a2018-03-02 19:54:34 +00004777 switch (address->sa_family) {
4778 case AF_INET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004780 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 return -EINVAL;
4782 snum = ntohs(addr4->sin_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004783 break;
4784 case AF_INET6:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004786 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787 return -EINVAL;
4788 snum = ntohs(addr6->sin6_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004789 break;
4790 default:
4791 /* Note that SCTP services expect -EINVAL, whereas
4792 * others expect -EAFNOSUPPORT.
4793 */
4794 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4795 return -EINVAL;
4796 else
4797 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798 }
4799
Paul Moore3e112172008-04-10 10:48:14 -04004800 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004802 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803
Richard Hainesd4529302018-02-13 20:57:18 +00004804 switch (sksec->sclass) {
4805 case SECCLASS_TCP_SOCKET:
4806 perm = TCP_SOCKET__NAME_CONNECT;
4807 break;
4808 case SECCLASS_DCCP_SOCKET:
4809 perm = DCCP_SOCKET__NAME_CONNECT;
4810 break;
4811 case SECCLASS_SCTP_SOCKET:
4812 perm = SCTP_SOCKET__NAME_CONNECT;
4813 break;
4814 }
James Morris2ee92d42006-11-13 16:09:01 -08004815
Eric Paris50c205f2012-04-04 15:01:43 -04004816 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004817 ad.u.net = &net;
4818 ad.u.net->dport = htons(snum);
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004819 ad.u.net->family = address->sa_family;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004820 err = avc_has_perm(&selinux_state,
4821 sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004823 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824 }
4825
Richard Hainesd4529302018-02-13 20:57:18 +00004826 return 0;
4827}
Paul Moore014ab192008-10-10 10:16:33 -04004828
Richard Hainesd4529302018-02-13 20:57:18 +00004829/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4830static int selinux_socket_connect(struct socket *sock,
4831 struct sockaddr *address, int addrlen)
4832{
4833 int err;
4834 struct sock *sk = sock->sk;
4835
4836 err = selinux_socket_connect_helper(sock, address, addrlen);
4837 if (err)
4838 return err;
4839
4840 return selinux_netlbl_socket_connect(sk, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841}
4842
4843static int selinux_socket_listen(struct socket *sock, int backlog)
4844{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004845 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846}
4847
4848static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4849{
4850 int err;
4851 struct inode_security_struct *isec;
4852 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004853 u16 sclass;
4854 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004856 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857 if (err)
4858 return err;
4859
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004860 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004861 spin_lock(&isec->lock);
4862 sclass = isec->sclass;
4863 sid = isec->sid;
4864 spin_unlock(&isec->lock);
4865
4866 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4867 newisec->sclass = sclass;
4868 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004869 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870
4871 return 0;
4872}
4873
4874static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004875 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004877 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878}
4879
4880static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4881 int size, int flags)
4882{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004883 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004884}
4885
4886static int selinux_socket_getsockname(struct socket *sock)
4887{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004888 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889}
4890
4891static int selinux_socket_getpeername(struct socket *sock)
4892{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004893 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894}
4895
Eric Paris828dfe12008-04-17 13:17:49 -04004896static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897{
Paul Mooref8687af2006-10-30 15:22:15 -08004898 int err;
4899
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004900 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004901 if (err)
4902 return err;
4903
4904 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905}
4906
4907static int selinux_socket_getsockopt(struct socket *sock, int level,
4908 int optname)
4909{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004910 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004911}
4912
4913static int selinux_socket_shutdown(struct socket *sock, int how)
4914{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004915 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916}
4917
David S. Miller3610cda2011-01-05 15:38:53 -08004918static int selinux_socket_unix_stream_connect(struct sock *sock,
4919 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 struct sock *newsk)
4921{
David S. Miller3610cda2011-01-05 15:38:53 -08004922 struct sk_security_struct *sksec_sock = sock->sk_security;
4923 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004924 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004925 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004926 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 int err;
4928
Eric Paris50c205f2012-04-04 15:01:43 -04004929 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004930 ad.u.net = &net;
4931 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004933 err = avc_has_perm(&selinux_state,
4934 sksec_sock->sid, sksec_other->sid,
Paul Moore4d1e2452010-04-22 14:46:18 -04004935 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4937 if (err)
4938 return err;
4939
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004941 sksec_new->peer_sid = sksec_sock->sid;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004942 err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
4943 sksec_sock->sid, &sksec_new->sid);
Paul Moore4d1e2452010-04-22 14:46:18 -04004944 if (err)
4945 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004946
Paul Moore4d1e2452010-04-22 14:46:18 -04004947 /* connecting socket */
4948 sksec_sock->peer_sid = sksec_new->sid;
4949
4950 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951}
4952
4953static int selinux_socket_unix_may_send(struct socket *sock,
4954 struct socket *other)
4955{
Paul Moore253bfae2010-04-22 14:46:19 -04004956 struct sk_security_struct *ssec = sock->sk->sk_security;
4957 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004958 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004959 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960
Eric Paris50c205f2012-04-04 15:01:43 -04004961 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004962 ad.u.net = &net;
4963 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004965 return avc_has_perm(&selinux_state,
4966 ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
Paul Moore253bfae2010-04-22 14:46:19 -04004967 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968}
4969
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004970static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4971 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004972 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004973{
4974 int err;
4975 u32 if_sid;
4976 u32 node_sid;
4977
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004978 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004979 if (err)
4980 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004981 err = avc_has_perm(&selinux_state,
4982 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004983 SECCLASS_NETIF, NETIF__INGRESS, ad);
4984 if (err)
4985 return err;
4986
4987 err = sel_netnode_sid(addrp, family, &node_sid);
4988 if (err)
4989 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004990 return avc_has_perm(&selinux_state,
4991 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004992 SECCLASS_NODE, NODE__RECVFROM, ad);
4993}
4994
Paul Moore220deb92008-01-29 08:38:23 -05004995static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004996 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004997{
Paul Moore277d3422008-12-31 12:54:11 -05004998 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004999 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05005000 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005001 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005002 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005003 char *addrp;
5004
Eric Paris50c205f2012-04-04 15:01:43 -04005005 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005006 ad.u.net = &net;
5007 ad.u.net->netif = skb->skb_iif;
5008 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005009 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
5010 if (err)
5011 return err;
Paul Moore220deb92008-01-29 08:38:23 -05005012
Paul Moore58bfbb52009-03-27 17:10:41 -04005013 if (selinux_secmark_enabled()) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005014 err = avc_has_perm(&selinux_state,
5015 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04005016 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04005017 if (err)
5018 return err;
5019 }
Paul Moore220deb92008-01-29 08:38:23 -05005020
Steffen Klassertb9679a72011-02-23 12:55:21 +01005021 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
5022 if (err)
5023 return err;
5024 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005025
James Morris4e5ab4c2006-06-09 00:33:33 -07005026 return err;
5027}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005028
James Morris4e5ab4c2006-06-09 00:33:33 -07005029static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
5030{
Paul Moore220deb92008-01-29 08:38:23 -05005031 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005032 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05005033 u16 family = sk->sk_family;
5034 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005035 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005036 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05005037 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04005038 u8 secmark_active;
5039 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07005040
James Morris4e5ab4c2006-06-09 00:33:33 -07005041 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05005042 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07005043
5044 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00005045 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07005046 family = PF_INET;
5047
Paul Moored8395c82008-10-10 10:16:30 -04005048 /* If any sort of compatibility mode is enabled then handoff processing
5049 * to the selinux_sock_rcv_skb_compat() function to deal with the
5050 * special handling. We do this in an attempt to keep this function
5051 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005052 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005053 return selinux_sock_rcv_skb_compat(sk, skb, family);
5054
5055 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005056 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04005057 if (!secmark_active && !peerlbl_active)
5058 return 0;
5059
Eric Paris50c205f2012-04-04 15:01:43 -04005060 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005061 ad.u.net = &net;
5062 ad.u.net->netif = skb->skb_iif;
5063 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05005064 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07005065 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05005066 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07005067
Paul Moored8395c82008-10-10 10:16:30 -04005068 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05005069 u32 peer_sid;
5070
5071 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
5072 if (err)
5073 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005074 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
5075 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005076 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005077 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005078 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04005079 }
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005080 err = avc_has_perm(&selinux_state,
5081 sk_sid, peer_sid, SECCLASS_PEER,
Paul Moored621d352008-01-29 08:43:36 -05005082 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05005083 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005084 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05005085 return err;
5086 }
Paul Moored621d352008-01-29 08:43:36 -05005087 }
5088
Paul Moored8395c82008-10-10 10:16:30 -04005089 if (secmark_active) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005090 err = avc_has_perm(&selinux_state,
5091 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005092 PACKET__RECV, &ad);
5093 if (err)
5094 return err;
5095 }
5096
Paul Moored621d352008-01-29 08:43:36 -05005097 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098}
5099
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005100static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
5101 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102{
5103 int err = 0;
5104 char *scontext;
5105 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04005106 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05005107 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108
Paul Moore253bfae2010-04-22 14:46:19 -04005109 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00005110 sksec->sclass == SECCLASS_TCP_SOCKET ||
5111 sksec->sclass == SECCLASS_SCTP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04005112 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04005113 if (peer_sid == SECSID_NULL)
5114 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005116 err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
5117 &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04005119 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
5121 if (scontext_len > len) {
5122 err = -ERANGE;
5123 goto out_len;
5124 }
5125
5126 if (copy_to_user(optval, scontext, scontext_len))
5127 err = -EFAULT;
5128
5129out_len:
5130 if (put_user(scontext_len, optlen))
5131 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133 return err;
5134}
5135
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005136static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005137{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005138 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05005139 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04005140 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07005141
Paul Mooreaa862902008-10-10 10:16:29 -04005142 if (skb && skb->protocol == htons(ETH_P_IP))
5143 family = PF_INET;
5144 else if (skb && skb->protocol == htons(ETH_P_IPV6))
5145 family = PF_INET6;
5146 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05005147 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05005148 else
5149 goto out;
5150
Paul Moore899134f2016-03-28 15:19:10 -04005151 if (sock && family == PF_UNIX) {
5152 isec = inode_security_novalidate(SOCK_INODE(sock));
5153 peer_secid = isec->sid;
5154 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05005155 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005156
Paul Moore75e22912008-01-29 08:38:04 -05005157out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005158 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05005159 if (peer_secid == SECSID_NULL)
5160 return -EINVAL;
5161 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005162}
5163
Al Viro7d877f32005-10-21 03:20:43 -04005164static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165{
Paul Moore84914b72010-04-22 14:46:18 -04005166 struct sk_security_struct *sksec;
5167
5168 sksec = kzalloc(sizeof(*sksec), priority);
5169 if (!sksec)
5170 return -ENOMEM;
5171
5172 sksec->peer_sid = SECINITSID_UNLABELED;
5173 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04005174 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04005175 selinux_netlbl_sk_security_reset(sksec);
5176 sk->sk_security = sksec;
5177
5178 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179}
5180
5181static void selinux_sk_free_security(struct sock *sk)
5182{
Paul Moore84914b72010-04-22 14:46:18 -04005183 struct sk_security_struct *sksec = sk->sk_security;
5184
5185 sk->sk_security = NULL;
5186 selinux_netlbl_sk_security_free(sksec);
5187 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188}
5189
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005190static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
5191{
Eric Parisdd3e7832010-04-07 15:08:46 -04005192 struct sk_security_struct *sksec = sk->sk_security;
5193 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005194
Eric Parisdd3e7832010-04-07 15:08:46 -04005195 newsksec->sid = sksec->sid;
5196 newsksec->peer_sid = sksec->peer_sid;
5197 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07005198
Eric Parisdd3e7832010-04-07 15:08:46 -04005199 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005200}
5201
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005202static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005203{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005204 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005205 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005206 else {
5207 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005208
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005209 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005210 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005211}
5212
Eric Paris828dfe12008-04-17 13:17:49 -04005213static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005214{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05005215 struct inode_security_struct *isec =
5216 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005217 struct sk_security_struct *sksec = sk->sk_security;
5218
Paul Moore2873ead2014-07-28 10:42:48 -04005219 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5220 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07005221 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05005222 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005223}
5224
Richard Hainesd4529302018-02-13 20:57:18 +00005225/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5226 * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5227 * already present).
5228 */
5229static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5230 struct sk_buff *skb)
5231{
5232 struct sk_security_struct *sksec = ep->base.sk->sk_security;
5233 struct common_audit_data ad;
5234 struct lsm_network_audit net = {0,};
5235 u8 peerlbl_active;
5236 u32 peer_sid = SECINITSID_UNLABELED;
5237 u32 conn_sid;
5238 int err = 0;
5239
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005240 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005241 return 0;
5242
5243 peerlbl_active = selinux_peerlbl_enabled();
5244
5245 if (peerlbl_active) {
5246 /* This will return peer_sid = SECSID_NULL if there are
5247 * no peer labels, see security_net_peersid_resolve().
5248 */
5249 err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5250 &peer_sid);
5251 if (err)
5252 return err;
5253
5254 if (peer_sid == SECSID_NULL)
5255 peer_sid = SECINITSID_UNLABELED;
5256 }
5257
5258 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5259 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5260
5261 /* Here as first association on socket. As the peer SID
5262 * was allowed by peer recv (and the netif/node checks),
5263 * then it is approved by policy and used as the primary
5264 * peer SID for getpeercon(3).
5265 */
5266 sksec->peer_sid = peer_sid;
5267 } else if (sksec->peer_sid != peer_sid) {
5268 /* Other association peer SIDs are checked to enforce
5269 * consistency among the peer SIDs.
5270 */
5271 ad.type = LSM_AUDIT_DATA_NET;
5272 ad.u.net = &net;
5273 ad.u.net->sk = ep->base.sk;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005274 err = avc_has_perm(&selinux_state,
5275 sksec->peer_sid, peer_sid, sksec->sclass,
Richard Hainesd4529302018-02-13 20:57:18 +00005276 SCTP_SOCKET__ASSOCIATION, &ad);
5277 if (err)
5278 return err;
5279 }
5280
5281 /* Compute the MLS component for the connection and store
5282 * the information in ep. This will be used by SCTP TCP type
5283 * sockets and peeled off connections as they cause a new
5284 * socket to be generated. selinux_sctp_sk_clone() will then
5285 * plug this into the new socket.
5286 */
5287 err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5288 if (err)
5289 return err;
5290
5291 ep->secid = conn_sid;
5292 ep->peer_secid = peer_sid;
5293
5294 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
5295 return selinux_netlbl_sctp_assoc_request(ep, skb);
5296}
5297
5298/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5299 * based on their @optname.
5300 */
5301static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5302 struct sockaddr *address,
5303 int addrlen)
5304{
5305 int len, err = 0, walk_size = 0;
5306 void *addr_buf;
5307 struct sockaddr *addr;
5308 struct socket *sock;
5309
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005310 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005311 return 0;
5312
5313 /* Process one or more addresses that may be IPv4 or IPv6 */
5314 sock = sk->sk_socket;
5315 addr_buf = address;
5316
5317 while (walk_size < addrlen) {
Ondrej Mosnacekc1383252018-11-13 16:16:08 +01005318 if (walk_size + sizeof(sa_family_t) > addrlen)
5319 return -EINVAL;
5320
Richard Hainesd4529302018-02-13 20:57:18 +00005321 addr = addr_buf;
5322 switch (addr->sa_family) {
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005323 case AF_UNSPEC:
Richard Hainesd4529302018-02-13 20:57:18 +00005324 case AF_INET:
5325 len = sizeof(struct sockaddr_in);
5326 break;
5327 case AF_INET6:
5328 len = sizeof(struct sockaddr_in6);
5329 break;
5330 default:
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005331 return -EINVAL;
Richard Hainesd4529302018-02-13 20:57:18 +00005332 }
5333
Xin Long292c9972019-03-09 00:07:34 +08005334 if (walk_size + len > addrlen)
5335 return -EINVAL;
5336
Richard Hainesd4529302018-02-13 20:57:18 +00005337 err = -EINVAL;
5338 switch (optname) {
5339 /* Bind checks */
5340 case SCTP_PRIMARY_ADDR:
5341 case SCTP_SET_PEER_PRIMARY_ADDR:
5342 case SCTP_SOCKOPT_BINDX_ADD:
5343 err = selinux_socket_bind(sock, addr, len);
5344 break;
5345 /* Connect checks */
5346 case SCTP_SOCKOPT_CONNECTX:
5347 case SCTP_PARAM_SET_PRIMARY:
5348 case SCTP_PARAM_ADD_IP:
5349 case SCTP_SENDMSG_CONNECT:
5350 err = selinux_socket_connect_helper(sock, addr, len);
5351 if (err)
5352 return err;
5353
5354 /* As selinux_sctp_bind_connect() is called by the
5355 * SCTP protocol layer, the socket is already locked,
Randy Dunlapc76a2f92020-08-07 09:51:34 -07005356 * therefore selinux_netlbl_socket_connect_locked()
Richard Hainesd4529302018-02-13 20:57:18 +00005357 * is called here. The situations handled are:
5358 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5359 * whenever a new IP address is added or when a new
5360 * primary address is selected.
5361 * Note that an SCTP connect(2) call happens before
5362 * the SCTP protocol layer and is handled via
5363 * selinux_socket_connect().
5364 */
5365 err = selinux_netlbl_socket_connect_locked(sk, addr);
5366 break;
5367 }
5368
5369 if (err)
5370 return err;
5371
5372 addr_buf += len;
5373 walk_size += len;
5374 }
5375
5376 return 0;
5377}
5378
5379/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
5380static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5381 struct sock *newsk)
5382{
5383 struct sk_security_struct *sksec = sk->sk_security;
5384 struct sk_security_struct *newsksec = newsk->sk_security;
5385
5386 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5387 * the non-sctp clone version.
5388 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005389 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005390 return selinux_sk_clone_security(sk, newsk);
5391
5392 newsksec->sid = ep->secid;
5393 newsksec->peer_sid = ep->peer_secid;
5394 newsksec->sclass = sksec->sclass;
5395 selinux_netlbl_sctp_sk_clone(sk, newsk);
5396}
5397
Florian Westphal41dd9592020-11-30 16:36:29 +01005398static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
Adrian Bunk9a673e52006-08-15 00:03:53 -07005399 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005400{
5401 struct sk_security_struct *sksec = sk->sk_security;
5402 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05005403 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05005404 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005405 u32 peersid;
5406
Paul Mooreaa862902008-10-10 10:16:29 -04005407 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05005408 if (err)
5409 return err;
Paul Moore446b8022013-12-04 16:10:51 -05005410 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5411 if (err)
5412 return err;
5413 req->secid = connsid;
5414 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07005415
Paul Moore389fb8002009-03-27 17:10:34 -04005416 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005417}
5418
Adrian Bunk9a673e52006-08-15 00:03:53 -07005419static void selinux_inet_csk_clone(struct sock *newsk,
5420 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005421{
5422 struct sk_security_struct *newsksec = newsk->sk_security;
5423
5424 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005425 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005426 /* NOTE: Ideally, we should also get the isec->sid for the
5427 new socket in sync, but we don't have the isec available yet.
5428 So we will wait until sock_graft to do it, by which
5429 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07005430
Paul Moore9f2ad662006-11-17 17:38:53 -05005431 /* We don't need to take any sort of lock here as we are the only
5432 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04005433 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005434}
5435
Paul Moore014ab192008-10-10 10:16:33 -04005436static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005437{
Paul Mooreaa862902008-10-10 10:16:29 -04005438 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005439 struct sk_security_struct *sksec = sk->sk_security;
5440
Paul Mooreaa862902008-10-10 10:16:29 -04005441 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5442 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5443 family = PF_INET;
5444
5445 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005446}
5447
Eric Paris2606fd12010-10-13 16:24:41 -04005448static int selinux_secmark_relabel_packet(u32 sid)
5449{
5450 const struct task_security_struct *__tsec;
5451 u32 tsid;
5452
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07005453 __tsec = selinux_cred(current_cred());
Eric Paris2606fd12010-10-13 16:24:41 -04005454 tsid = __tsec->sid;
5455
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005456 return avc_has_perm(&selinux_state,
5457 tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
5458 NULL);
Eric Paris2606fd12010-10-13 16:24:41 -04005459}
5460
5461static void selinux_secmark_refcount_inc(void)
5462{
5463 atomic_inc(&selinux_secmark_refcount);
5464}
5465
5466static void selinux_secmark_refcount_dec(void)
5467{
5468 atomic_dec(&selinux_secmark_refcount);
5469}
5470
Adrian Bunk9a673e52006-08-15 00:03:53 -07005471static void selinux_req_classify_flow(const struct request_sock *req,
Paul Moore3df98d72020-09-27 22:38:26 -04005472 struct flowi_common *flic)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005473{
Paul Moore3df98d72020-09-27 22:38:26 -04005474 flic->flowic_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005475}
5476
Paul Moore5dbbaf22013-01-14 07:12:19 +00005477static int selinux_tun_dev_alloc_security(void **security)
5478{
5479 struct tun_security_struct *tunsec;
5480
5481 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5482 if (!tunsec)
5483 return -ENOMEM;
5484 tunsec->sid = current_sid();
5485
5486 *security = tunsec;
5487 return 0;
5488}
5489
5490static void selinux_tun_dev_free_security(void *security)
5491{
5492 kfree(security);
5493}
5494
Paul Mooreed6d76e2009-08-28 18:12:49 -04005495static int selinux_tun_dev_create(void)
5496{
5497 u32 sid = current_sid();
5498
5499 /* we aren't taking into account the "sockcreate" SID since the socket
5500 * that is being created here is not a socket in the traditional sense,
5501 * instead it is a private sock, accessible only to the kernel, and
5502 * representing a wide range of network traffic spanning multiple
5503 * connections unlike traditional sockets - check the TUN driver to
5504 * get a better understanding of why this socket is special */
5505
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005506 return avc_has_perm(&selinux_state,
5507 sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005508 NULL);
5509}
5510
Paul Moore5dbbaf22013-01-14 07:12:19 +00005511static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005512{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005513 struct tun_security_struct *tunsec = security;
5514
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005515 return avc_has_perm(&selinux_state,
5516 current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005517 TUN_SOCKET__ATTACH_QUEUE, NULL);
5518}
5519
5520static int selinux_tun_dev_attach(struct sock *sk, void *security)
5521{
5522 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005523 struct sk_security_struct *sksec = sk->sk_security;
5524
5525 /* we don't currently perform any NetLabel based labeling here and it
5526 * isn't clear that we would want to do so anyway; while we could apply
5527 * labeling without the support of the TUN user the resulting labeled
5528 * traffic from the other end of the connection would almost certainly
5529 * cause confusion to the TUN user that had no idea network labeling
5530 * protocols were being used */
5531
Paul Moore5dbbaf22013-01-14 07:12:19 +00005532 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005533 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005534
5535 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005536}
5537
Paul Moore5dbbaf22013-01-14 07:12:19 +00005538static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005539{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005540 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005541 u32 sid = current_sid();
5542 int err;
5543
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005544 err = avc_has_perm(&selinux_state,
5545 sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005546 TUN_SOCKET__RELABELFROM, NULL);
5547 if (err)
5548 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005549 err = avc_has_perm(&selinux_state,
5550 sid, sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005551 TUN_SOCKET__RELABELTO, NULL);
5552 if (err)
5553 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005554 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005555
5556 return 0;
5557}
5558
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559#ifdef CONFIG_NETFILTER
5560
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005561static unsigned int selinux_ip_forward(struct sk_buff *skb,
5562 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005563 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564{
Paul Mooredfaebe92008-10-10 10:16:31 -04005565 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005566 char *addrp;
5567 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005568 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005569 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005570 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005571 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005572 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005573
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005574 if (!selinux_policycap_netpeer())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005575 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005576
Paul Mooreeffad8d2008-01-29 08:49:27 -05005577 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005578 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005579 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005580 if (!secmark_active && !peerlbl_active)
5581 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005582
Paul Moored8395c82008-10-10 10:16:30 -04005583 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5584 return NF_DROP;
5585
Eric Paris50c205f2012-04-04 15:01:43 -04005586 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005587 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005588 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005589 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005590 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5591 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
Paul Mooredfaebe92008-10-10 10:16:31 -04005593 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005594 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5595 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005596 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005597 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005598 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005599 }
5600 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005601
5602 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005603 if (avc_has_perm(&selinux_state,
5604 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005605 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5606 return NF_DROP;
5607
Paul Moore948bf852008-10-10 10:16:32 -04005608 if (netlbl_active)
5609 /* we do this in the FORWARD path and not the POST_ROUTING
5610 * path because we want to make sure we apply the necessary
5611 * labeling before IPsec is applied so we can leverage AH
5612 * protection */
5613 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5614 return NF_DROP;
5615
Paul Mooreeffad8d2008-01-29 08:49:27 -05005616 return NF_ACCEPT;
5617}
5618
Eric W. Biederman06198b32015-09-18 14:33:06 -05005619static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005620 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005621 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005622{
David S. Miller238e54c2015-04-03 20:32:56 -04005623 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005624}
5625
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005626#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005627static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005628 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005629 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005630{
David S. Miller238e54c2015-04-03 20:32:56 -04005631 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005632}
5633#endif /* IPV6 */
5634
Paul Moore948bf852008-10-10 10:16:32 -04005635static unsigned int selinux_ip_output(struct sk_buff *skb,
5636 u16 family)
5637{
Paul Moore47180062013-12-04 16:10:45 -05005638 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005639 u32 sid;
5640
5641 if (!netlbl_enabled())
5642 return NF_ACCEPT;
5643
5644 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5645 * because we want to make sure we apply the necessary labeling
5646 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005647 sk = skb->sk;
5648 if (sk) {
5649 struct sk_security_struct *sksec;
5650
Eric Dumazete446f9d2015-10-08 05:01:55 -07005651 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005652 /* if the socket is the listening state then this
5653 * packet is a SYN-ACK packet which means it needs to
5654 * be labeled based on the connection/request_sock and
5655 * not the parent socket. unfortunately, we can't
5656 * lookup the request_sock yet as it isn't queued on
5657 * the parent socket until after the SYN-ACK is sent.
5658 * the "solution" is to simply pass the packet as-is
5659 * as any IP option based labeling should be copied
5660 * from the initial connection request (in the IP
5661 * layer). it is far from ideal, but until we get a
5662 * security label in the packet itself this is the
5663 * best we can do. */
5664 return NF_ACCEPT;
5665
5666 /* standard practice, label using the parent socket */
5667 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005668 sid = sksec->sid;
5669 } else
5670 sid = SECINITSID_KERNEL;
5671 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5672 return NF_DROP;
5673
5674 return NF_ACCEPT;
5675}
5676
Eric W. Biederman06198b32015-09-18 14:33:06 -05005677static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005678 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005679 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005680{
5681 return selinux_ip_output(skb, PF_INET);
5682}
5683
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005684#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005685static unsigned int selinux_ipv6_output(void *priv,
5686 struct sk_buff *skb,
5687 const struct nf_hook_state *state)
5688{
5689 return selinux_ip_output(skb, PF_INET6);
5690}
5691#endif /* IPV6 */
5692
Paul Mooreeffad8d2008-01-29 08:49:27 -05005693static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5694 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005695 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005696{
Eric Dumazet54abc682015-11-08 10:54:07 -08005697 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005698 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005699 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005700 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005701 char *addrp;
5702 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005703
Paul Mooreeffad8d2008-01-29 08:49:27 -05005704 if (sk == NULL)
5705 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005706 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005707
Eric Paris50c205f2012-04-04 15:01:43 -04005708 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005709 ad.u.net = &net;
5710 ad.u.net->netif = ifindex;
5711 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005712 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5713 return NF_DROP;
5714
Paul Moore58bfbb52009-03-27 17:10:41 -04005715 if (selinux_secmark_enabled())
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005716 if (avc_has_perm(&selinux_state,
5717 sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005718 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005719 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005720
Steffen Klassertb9679a72011-02-23 12:55:21 +01005721 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5722 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005723
Paul Mooreeffad8d2008-01-29 08:49:27 -05005724 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725}
5726
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005727static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5728 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005729 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005731 u32 secmark_perm;
5732 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005733 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005734 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005735 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005736 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005737 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005738 u8 secmark_active;
5739 u8 peerlbl_active;
5740
Paul Mooreeffad8d2008-01-29 08:49:27 -05005741 /* If any sort of compatibility mode is enabled then handoff processing
5742 * to the selinux_ip_postroute_compat() function to deal with the
5743 * special handling. We do this in an attempt to keep this function
5744 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005745 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005746 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005747
Paul Mooreeffad8d2008-01-29 08:49:27 -05005748 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005749 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005750 if (!secmark_active && !peerlbl_active)
5751 return NF_ACCEPT;
5752
Eric Dumazet54abc682015-11-08 10:54:07 -08005753 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005754
Paul Mooreeffad8d2008-01-29 08:49:27 -05005755#ifdef CONFIG_XFRM
5756 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5757 * packet transformation so allow the packet to pass without any checks
5758 * since we'll have another chance to perform access control checks
5759 * when the packet is on it's final way out.
5760 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005761 * is NULL, in this case go ahead and apply access control.
5762 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5763 * TCP listening state we cannot wait until the XFRM processing
5764 * is done as we will miss out on the SA label if we do;
5765 * unfortunately, this means more work, but it is only once per
5766 * connection. */
5767 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005768 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005769 return NF_ACCEPT;
5770#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005771
Paul Moored8395c82008-10-10 10:16:30 -04005772 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005773 /* Without an associated socket the packet is either coming
5774 * from the kernel or it is being forwarded; check the packet
5775 * to determine which and if the packet is being forwarded
5776 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005777 if (skb->skb_iif) {
5778 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005779 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005780 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005781 } else {
5782 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005783 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005784 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005785 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005786 /* Locally generated packet but the associated socket is in the
5787 * listening state which means this is a SYN-ACK packet. In
5788 * this particular case the correct security label is assigned
5789 * to the connection/request_sock but unfortunately we can't
5790 * query the request_sock as it isn't queued on the parent
5791 * socket until after the SYN-ACK packet is sent; the only
5792 * viable choice is to regenerate the label like we do in
5793 * selinux_inet_conn_request(). See also selinux_ip_output()
5794 * for similar problems. */
5795 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005796 struct sk_security_struct *sksec;
5797
Eric Dumazete446f9d2015-10-08 05:01:55 -07005798 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005799 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5800 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005801 /* At this point, if the returned skb peerlbl is SECSID_NULL
5802 * and the packet has been through at least one XFRM
5803 * transformation then we must be dealing with the "final"
5804 * form of labeled IPsec packet; since we've already applied
5805 * all of our access controls on this packet we can safely
5806 * pass the packet. */
5807 if (skb_sid == SECSID_NULL) {
5808 switch (family) {
5809 case PF_INET:
5810 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5811 return NF_ACCEPT;
5812 break;
5813 case PF_INET6:
5814 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5815 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005816 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005817 default:
5818 return NF_DROP_ERR(-ECONNREFUSED);
5819 }
5820 }
Paul Moore446b8022013-12-04 16:10:51 -05005821 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5822 return NF_DROP;
5823 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005824 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005825 /* Locally generated packet, fetch the security label from the
5826 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005827 struct sk_security_struct *sksec = sk->sk_security;
5828 peer_sid = sksec->sid;
5829 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005830 }
5831
Eric Paris50c205f2012-04-04 15:01:43 -04005832 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005833 ad.u.net = &net;
5834 ad.u.net->netif = ifindex;
5835 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005836 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005837 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005838
Paul Mooreeffad8d2008-01-29 08:49:27 -05005839 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005840 if (avc_has_perm(&selinux_state,
5841 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005842 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005843 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005844
5845 if (peerlbl_active) {
5846 u32 if_sid;
5847 u32 node_sid;
5848
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005849 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005850 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005851 if (avc_has_perm(&selinux_state,
5852 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005853 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005854 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005855
5856 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005857 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005858 if (avc_has_perm(&selinux_state,
5859 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005860 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005861 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005862 }
5863
5864 return NF_ACCEPT;
5865}
5866
Eric W. Biederman06198b32015-09-18 14:33:06 -05005867static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005868 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005869 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005870{
David S. Miller238e54c2015-04-03 20:32:56 -04005871 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872}
5873
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005874#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005875static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005876 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005877 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878{
David S. Miller238e54c2015-04-03 20:32:56 -04005879 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881#endif /* IPV6 */
5882
5883#endif /* CONFIG_NETFILTER */
5884
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5886{
Paul Moorefb739742020-04-28 09:59:02 -04005887 int rc = 0;
5888 unsigned int msg_len;
5889 unsigned int data_len = skb->len;
5890 unsigned char *data = skb->data;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005891 struct nlmsghdr *nlh;
5892 struct sk_security_struct *sksec = sk->sk_security;
Paul Moorefb739742020-04-28 09:59:02 -04005893 u16 sclass = sksec->sclass;
5894 u32 perm;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005895
Paul Moorefb739742020-04-28 09:59:02 -04005896 while (data_len >= nlmsg_total_size(0)) {
5897 nlh = (struct nlmsghdr *)data;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005898
Paul Moorefb739742020-04-28 09:59:02 -04005899 /* NOTE: the nlmsg_len field isn't reliably set by some netlink
5900 * users which means we can't reject skb's with bogus
5901 * length fields; our solution is to follow what
5902 * netlink_rcv_skb() does and simply skip processing at
5903 * messages with length fields that are clearly junk
5904 */
5905 if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
5906 return 0;
5907
5908 rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
5909 if (rc == 0) {
5910 rc = sock_has_perm(sk, perm);
5911 if (rc)
5912 return rc;
5913 } else if (rc == -EINVAL) {
5914 /* -EINVAL is a missing msg/perm mapping */
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005915 pr_warn_ratelimited("SELinux: unrecognized netlink"
Paul Moorefb739742020-04-28 09:59:02 -04005916 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5917 " pid=%d comm=%s\n",
5918 sk->sk_protocol, nlh->nlmsg_type,
5919 secclass_map[sclass - 1].name,
5920 task_pid_nr(current), current->comm);
5921 if (enforcing_enabled(&selinux_state) &&
5922 !security_get_allow_unknown(&selinux_state))
5923 return rc;
5924 rc = 0;
5925 } else if (rc == -ENOENT) {
5926 /* -ENOENT is a missing socket/class mapping, ignore */
5927 rc = 0;
5928 } else {
5929 return rc;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005930 }
5931
Paul Moorefb739742020-04-28 09:59:02 -04005932 /* move to the next message after applying netlink padding */
5933 msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
5934 if (msg_len >= data_len)
5935 return 0;
5936 data_len -= msg_len;
5937 data += msg_len;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005938 }
5939
Paul Moorefb739742020-04-28 09:59:02 -04005940 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941}
5942
Casey Schauflerecd5f822018-11-20 11:55:02 -08005943static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005946 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947}
5948
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005950 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005953 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005954 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955
Casey Schaufler7c653822018-09-21 17:19:45 -07005956 isec = selinux_ipc(ipc_perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Eric Paris50c205f2012-04-04 15:01:43 -04005958 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959 ad.u.ipc_id = ipc_perms->key;
5960
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005961 return avc_has_perm(&selinux_state,
5962 sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963}
5964
5965static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5966{
Huaisheng Yeb82f3f62020-01-10 17:58:56 +08005967 struct msg_security_struct *msec;
5968
5969 msec = selinux_msg_msg(msg);
5970 msec->sid = SECINITSID_UNLABELED;
5971
5972 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973}
5974
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975/* message queue security operations */
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005976static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005979 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005980 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981 int rc;
5982
Casey Schauflerecd5f822018-11-20 11:55:02 -08005983 isec = selinux_ipc(msq);
5984 ipc_init_security(isec, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Eric Paris50c205f2012-04-04 15:01:43 -04005986 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005987 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005989 rc = avc_has_perm(&selinux_state,
5990 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991 MSGQ__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08005992 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993}
5994
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005995static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005998 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005999 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Casey Schaufler7c653822018-09-21 17:19:45 -07006001 isec = selinux_ipc(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Eric Paris50c205f2012-04-04 15:01:43 -04006003 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006004 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006006 return avc_has_perm(&selinux_state,
6007 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008 MSGQ__ASSOCIATE, &ad);
6009}
6010
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006011static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012{
6013 int err;
6014 int perms;
6015
Eric Paris828dfe12008-04-17 13:17:49 -04006016 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017 case IPC_INFO:
6018 case MSG_INFO:
6019 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006020 return avc_has_perm(&selinux_state,
6021 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006022 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023 case IPC_STAT:
6024 case MSG_STAT:
Davidlohr Bueso23c8cec2018-04-10 16:35:30 -07006025 case MSG_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
6027 break;
6028 case IPC_SET:
6029 perms = MSGQ__SETATTR;
6030 break;
6031 case IPC_RMID:
6032 perms = MSGQ__DESTROY;
6033 break;
6034 default:
6035 return 0;
6036 }
6037
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006038 err = ipc_has_perm(msq, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 return err;
6040}
6041
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006042static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044 struct ipc_security_struct *isec;
6045 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006046 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006047 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048 int rc;
6049
Casey Schaufler7c653822018-09-21 17:19:45 -07006050 isec = selinux_ipc(msq);
6051 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
6053 /*
6054 * First time through, need to assign label to the message
6055 */
6056 if (msec->sid == SECINITSID_UNLABELED) {
6057 /*
6058 * Compute new sid based on current process and
6059 * message queue this message will be stored in
6060 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006061 rc = security_transition_sid(&selinux_state, sid, isec->sid,
6062 SECCLASS_MSG, NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063 if (rc)
6064 return rc;
6065 }
6066
Eric Paris50c205f2012-04-04 15:01:43 -04006067 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006068 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
6070 /* Can this process write to the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006071 rc = avc_has_perm(&selinux_state,
6072 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073 MSGQ__WRITE, &ad);
6074 if (!rc)
6075 /* Can this process send the message */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006076 rc = avc_has_perm(&selinux_state,
6077 sid, msec->sid, SECCLASS_MSG,
David Howells275bb412008-11-14 10:39:19 +11006078 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079 if (!rc)
6080 /* Can the message be put in the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006081 rc = avc_has_perm(&selinux_state,
6082 msec->sid, isec->sid, SECCLASS_MSGQ,
David Howells275bb412008-11-14 10:39:19 +11006083 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
6085 return rc;
6086}
6087
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006088static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089 struct task_struct *target,
6090 long type, int mode)
6091{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092 struct ipc_security_struct *isec;
6093 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006094 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006095 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 int rc;
6097
Casey Schaufler7c653822018-09-21 17:19:45 -07006098 isec = selinux_ipc(msq);
6099 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Eric Paris50c205f2012-04-04 15:01:43 -04006101 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006102 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006104 rc = avc_has_perm(&selinux_state,
6105 sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106 SECCLASS_MSGQ, MSGQ__READ, &ad);
6107 if (!rc)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006108 rc = avc_has_perm(&selinux_state,
6109 sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110 SECCLASS_MSG, MSG__RECEIVE, &ad);
6111 return rc;
6112}
6113
6114/* Shared Memory security operations */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006115static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006118 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006119 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120 int rc;
6121
Casey Schauflerecd5f822018-11-20 11:55:02 -08006122 isec = selinux_ipc(shp);
6123 ipc_init_security(isec, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124
Eric Paris50c205f2012-04-04 15:01:43 -04006125 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006126 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006128 rc = avc_has_perm(&selinux_state,
6129 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 SHM__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08006131 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132}
6133
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006134static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006137 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006138 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Casey Schaufler7c653822018-09-21 17:19:45 -07006140 isec = selinux_ipc(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141
Eric Paris50c205f2012-04-04 15:01:43 -04006142 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006143 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006145 return avc_has_perm(&selinux_state,
6146 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147 SHM__ASSOCIATE, &ad);
6148}
6149
6150/* Note, at this point, shp is locked down */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006151static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152{
6153 int perms;
6154 int err;
6155
Eric Paris828dfe12008-04-17 13:17:49 -04006156 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006157 case IPC_INFO:
6158 case SHM_INFO:
6159 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006160 return avc_has_perm(&selinux_state,
6161 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006162 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163 case IPC_STAT:
6164 case SHM_STAT:
Davidlohr Buesoc21a6972018-04-10 16:35:23 -07006165 case SHM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166 perms = SHM__GETATTR | SHM__ASSOCIATE;
6167 break;
6168 case IPC_SET:
6169 perms = SHM__SETATTR;
6170 break;
6171 case SHM_LOCK:
6172 case SHM_UNLOCK:
6173 perms = SHM__LOCK;
6174 break;
6175 case IPC_RMID:
6176 perms = SHM__DESTROY;
6177 break;
6178 default:
6179 return 0;
6180 }
6181
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006182 err = ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183 return err;
6184}
6185
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006186static int selinux_shm_shmat(struct kern_ipc_perm *shp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187 char __user *shmaddr, int shmflg)
6188{
6189 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190
6191 if (shmflg & SHM_RDONLY)
6192 perms = SHM__READ;
6193 else
6194 perms = SHM__READ | SHM__WRITE;
6195
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006196 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197}
6198
6199/* Semaphore security operations */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006200static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006203 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006204 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006205 int rc;
6206
Casey Schauflerecd5f822018-11-20 11:55:02 -08006207 isec = selinux_ipc(sma);
6208 ipc_init_security(isec, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209
Eric Paris50c205f2012-04-04 15:01:43 -04006210 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006211 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006213 rc = avc_has_perm(&selinux_state,
6214 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215 SEM__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08006216 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217}
6218
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006219static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006221 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006222 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006223 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224
Casey Schaufler7c653822018-09-21 17:19:45 -07006225 isec = selinux_ipc(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226
Eric Paris50c205f2012-04-04 15:01:43 -04006227 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006228 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006230 return avc_has_perm(&selinux_state,
6231 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232 SEM__ASSOCIATE, &ad);
6233}
6234
6235/* Note, at this point, sma is locked down */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006236static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237{
6238 int err;
6239 u32 perms;
6240
Eric Paris828dfe12008-04-17 13:17:49 -04006241 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242 case IPC_INFO:
6243 case SEM_INFO:
6244 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006245 return avc_has_perm(&selinux_state,
6246 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006247 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248 case GETPID:
6249 case GETNCNT:
6250 case GETZCNT:
6251 perms = SEM__GETATTR;
6252 break;
6253 case GETVAL:
6254 case GETALL:
6255 perms = SEM__READ;
6256 break;
6257 case SETVAL:
6258 case SETALL:
6259 perms = SEM__WRITE;
6260 break;
6261 case IPC_RMID:
6262 perms = SEM__DESTROY;
6263 break;
6264 case IPC_SET:
6265 perms = SEM__SETATTR;
6266 break;
6267 case IPC_STAT:
6268 case SEM_STAT:
Davidlohr Buesoa280d6d2018-04-10 16:35:26 -07006269 case SEM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270 perms = SEM__GETATTR | SEM__ASSOCIATE;
6271 break;
6272 default:
6273 return 0;
6274 }
6275
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006276 err = ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277 return err;
6278}
6279
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006280static int selinux_sem_semop(struct kern_ipc_perm *sma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281 struct sembuf *sops, unsigned nsops, int alter)
6282{
6283 u32 perms;
6284
6285 if (alter)
6286 perms = SEM__READ | SEM__WRITE;
6287 else
6288 perms = SEM__READ;
6289
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006290 return ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291}
6292
6293static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6294{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006295 u32 av = 0;
6296
Linus Torvalds1da177e2005-04-16 15:20:36 -07006297 av = 0;
6298 if (flag & S_IRUGO)
6299 av |= IPC__UNIX_READ;
6300 if (flag & S_IWUGO)
6301 av |= IPC__UNIX_WRITE;
6302
6303 if (av == 0)
6304 return 0;
6305
Stephen Smalley6af963f2005-05-01 08:58:39 -07006306 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307}
6308
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006309static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6310{
Casey Schaufler7c653822018-09-21 17:19:45 -07006311 struct ipc_security_struct *isec = selinux_ipc(ipcp);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006312 *secid = isec->sid;
6313}
6314
Eric Paris828dfe12008-04-17 13:17:49 -04006315static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316{
6317 if (inode)
6318 inode_doinit_with_dentry(inode, dentry);
6319}
6320
6321static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00006322 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006323{
David Howells275bb412008-11-14 10:39:19 +11006324 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00006325 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006326 int error;
Al Viro04ff9702007-03-12 16:17:58 +00006327 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328
David Howells275bb412008-11-14 10:39:19 +11006329 rcu_read_lock();
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006330 __tsec = selinux_cred(__task_cred(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006331
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006332 if (current != p) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006333 error = avc_has_perm(&selinux_state,
6334 current_sid(), __tsec->sid,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006335 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6336 if (error)
6337 goto bad;
6338 }
6339
Linus Torvalds1da177e2005-04-16 15:20:36 -07006340 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11006341 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006342 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11006343 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006344 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11006345 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11006347 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006348 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11006349 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07006350 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11006351 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006352 else {
6353 error = -EINVAL;
6354 goto bad;
6355 }
David Howells275bb412008-11-14 10:39:19 +11006356 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006357
6358 if (!sid)
6359 return 0;
6360
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006361 error = security_sid_to_context(&selinux_state, sid, value, &len);
Al Viro04ff9702007-03-12 16:17:58 +00006362 if (error)
6363 return error;
6364 return len;
David Howells275bb412008-11-14 10:39:19 +11006365
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006366bad:
David Howells275bb412008-11-14 10:39:19 +11006367 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006368 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006369}
6370
Stephen Smalleyb21507e2017-01-09 10:07:31 -05006371static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006372{
6373 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11006374 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006375 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376 int error;
6377 char *str = value;
6378
Linus Torvalds1da177e2005-04-16 15:20:36 -07006379 /*
6380 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006381 */
6382 if (!strcmp(name, "exec"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006383 error = avc_has_perm(&selinux_state,
6384 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006385 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 else if (!strcmp(name, "fscreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006387 error = avc_has_perm(&selinux_state,
6388 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006389 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006390 else if (!strcmp(name, "keycreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006391 error = avc_has_perm(&selinux_state,
6392 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006393 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07006394 else if (!strcmp(name, "sockcreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006395 error = avc_has_perm(&selinux_state,
6396 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006397 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006398 else if (!strcmp(name, "current"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006399 error = avc_has_perm(&selinux_state,
6400 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006401 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006402 else
6403 error = -EINVAL;
6404 if (error)
6405 return error;
6406
6407 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05006408 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006409 if (str[size-1] == '\n') {
6410 str[size-1] = 0;
6411 size--;
6412 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006413 error = security_context_to_sid(&selinux_state, value, size,
6414 &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006415 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04006416 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04006417 struct audit_buffer *ab;
6418 size_t audit_size;
6419
6420 /* We strip a nul only if it is at the end, otherwise the
6421 * context contains a nul and we should audit that */
6422 if (str[size - 1] == '\0')
6423 audit_size = size - 1;
6424 else
6425 audit_size = size;
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04006426 ab = audit_log_start(audit_context(),
6427 GFP_ATOMIC,
6428 AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04006429 audit_log_format(ab, "op=fscreate invalid_context=");
6430 audit_log_n_untrustedstring(ab, value, audit_size);
6431 audit_log_end(ab);
6432
Stephen Smalley12b29f32008-05-07 13:03:20 -04006433 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006434 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006435 error = security_context_to_sid_force(
6436 &selinux_state,
6437 value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439 if (error)
6440 return error;
6441 }
6442
David Howellsd84f4f92008-11-14 10:39:23 +11006443 new = prepare_creds();
6444 if (!new)
6445 return -ENOMEM;
6446
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447 /* Permission checking based on the specified context is
6448 performed during the actual operation (execve,
6449 open/mkdir/...), when we know the full context of the
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05006450 operation. See selinux_bprm_creds_for_exec for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451 checks and may_create for the file creation checks. The
6452 operation will then fail if the context is not permitted. */
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006453 tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11006454 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006456 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006458 } else if (!strcmp(name, "keycreate")) {
Ondrej Mosnacek464c2582019-06-12 10:12:26 +02006459 if (sid) {
6460 error = avc_has_perm(&selinux_state, mysid, sid,
6461 SECCLASS_KEY, KEY__CREATE, NULL);
6462 if (error)
6463 goto abort_change;
6464 }
Michael LeMay4eb582c2006-06-26 00:24:57 -07006465 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006466 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006467 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006468 } else if (!strcmp(name, "current")) {
6469 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006470 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006471 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006472
David Howellsd84f4f92008-11-14 10:39:23 +11006473 /* Only allow single threaded processes to change context */
6474 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006475 if (!current_is_single_threaded()) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006476 error = security_bounded_transition(&selinux_state,
6477 tsec->sid, sid);
David Howellsd84f4f92008-11-14 10:39:23 +11006478 if (error)
6479 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006481
6482 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006483 error = avc_has_perm(&selinux_state,
6484 tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006485 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006487 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006488
6489 /* Check for ptracing, and update the task SID if ok.
6490 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006491 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006492 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006493 error = avc_has_perm(&selinux_state,
6494 ptsid, sid, SECCLASS_PROCESS,
David Howellsd84f4f92008-11-14 10:39:23 +11006495 PROCESS__PTRACE, NULL);
6496 if (error)
6497 goto abort_change;
6498 }
6499
6500 tsec->sid = sid;
6501 } else {
6502 error = -EINVAL;
6503 goto abort_change;
6504 }
6505
6506 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006507 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006508
6509abort_change:
6510 abort_creds(new);
6511 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512}
6513
David Quigley746df9b2013-05-22 12:50:35 -04006514static int selinux_ismaclabel(const char *name)
6515{
6516 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6517}
6518
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006519static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6520{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006521 return security_sid_to_context(&selinux_state, secid,
6522 secdata, seclen);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006523}
6524
David Howells7bf570d2008-04-29 20:52:51 +01006525static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006526{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006527 return security_context_to_sid(&selinux_state, secdata, seclen,
6528 secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006529}
6530
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006531static void selinux_release_secctx(char *secdata, u32 seclen)
6532{
Paul Moore088999e2007-08-01 11:12:58 -04006533 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006534}
6535
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006536static void selinux_inode_invalidate_secctx(struct inode *inode)
6537{
Casey Schaufler80788c22018-09-21 17:19:11 -07006538 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006539
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006540 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006541 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006542 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006543}
6544
David P. Quigley1ee65e32009-09-03 14:25:57 -04006545/*
6546 * called with inode->i_mutex locked
6547 */
6548static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6549{
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01006550 int rc = selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX,
6551 ctx, ctxlen, 0);
6552 /* Do not return error when suppressing label (SBLABEL_MNT not set). */
6553 return rc == -EOPNOTSUPP ? 0 : rc;
David P. Quigley1ee65e32009-09-03 14:25:57 -04006554}
6555
6556/*
6557 * called with inode->i_mutex locked
6558 */
6559static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6560{
6561 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6562}
6563
6564static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6565{
6566 int len = 0;
6567 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6568 ctx, true);
6569 if (len < 0)
6570 return len;
6571 *ctxlen = len;
6572 return 0;
6573}
Michael LeMayd7200242006-06-22 14:47:17 -07006574#ifdef CONFIG_KEYS
6575
David Howellsd84f4f92008-11-14 10:39:23 +11006576static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006577 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006578{
David Howellsd84f4f92008-11-14 10:39:23 +11006579 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006580 struct key_security_struct *ksec;
6581
6582 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6583 if (!ksec)
6584 return -ENOMEM;
6585
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006586 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11006587 if (tsec->keycreate_sid)
6588 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006589 else
David Howellsd84f4f92008-11-14 10:39:23 +11006590 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006591
David Howells275bb412008-11-14 10:39:19 +11006592 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006593 return 0;
6594}
6595
6596static void selinux_key_free(struct key *k)
6597{
6598 struct key_security_struct *ksec = k->security;
6599
6600 k->security = NULL;
6601 kfree(ksec);
6602}
6603
6604static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006605 const struct cred *cred,
David Howells8c0637e2020-05-12 15:16:29 +01006606 enum key_need_perm need_perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006607{
6608 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006609 struct key_security_struct *ksec;
David Howells8c0637e2020-05-12 15:16:29 +01006610 u32 perm, sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006611
David Howells8c0637e2020-05-12 15:16:29 +01006612 switch (need_perm) {
6613 case KEY_NEED_VIEW:
6614 perm = KEY__VIEW;
6615 break;
6616 case KEY_NEED_READ:
6617 perm = KEY__READ;
6618 break;
6619 case KEY_NEED_WRITE:
6620 perm = KEY__WRITE;
6621 break;
6622 case KEY_NEED_SEARCH:
6623 perm = KEY__SEARCH;
6624 break;
6625 case KEY_NEED_LINK:
6626 perm = KEY__LINK;
6627 break;
6628 case KEY_NEED_SETATTR:
6629 perm = KEY__SETATTR;
6630 break;
6631 case KEY_NEED_UNLINK:
6632 case KEY_SYSADMIN_OVERRIDE:
6633 case KEY_AUTHTOKEN_OVERRIDE:
6634 case KEY_DEFER_PERM_CHECK:
Michael LeMayd7200242006-06-22 14:47:17 -07006635 return 0;
David Howells8c0637e2020-05-12 15:16:29 +01006636 default:
6637 WARN_ON(1);
6638 return -EPERM;
6639
6640 }
Michael LeMayd7200242006-06-22 14:47:17 -07006641
David Howellsd84f4f92008-11-14 10:39:23 +11006642 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006643 key = key_ref_to_ptr(key_ref);
6644 ksec = key->security;
6645
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006646 return avc_has_perm(&selinux_state,
Linus Torvalds028db3e2019-07-10 18:43:43 -07006647 sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006648}
6649
David Howells70a5bb72008-04-29 01:01:26 -07006650static int selinux_key_getsecurity(struct key *key, char **_buffer)
6651{
6652 struct key_security_struct *ksec = key->security;
6653 char *context = NULL;
6654 unsigned len;
6655 int rc;
6656
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006657 rc = security_sid_to_context(&selinux_state, ksec->sid,
6658 &context, &len);
David Howells70a5bb72008-04-29 01:01:26 -07006659 if (!rc)
6660 rc = len;
6661 *_buffer = context;
6662 return rc;
6663}
David Howells3e412cc2020-01-14 17:07:13 +00006664
6665#ifdef CONFIG_KEY_NOTIFICATIONS
6666static int selinux_watch_key(struct key *key)
6667{
6668 struct key_security_struct *ksec = key->security;
6669 u32 sid = current_sid();
6670
6671 return avc_has_perm(&selinux_state,
6672 sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL);
6673}
6674#endif
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006675#endif
David Howells70a5bb72008-04-29 01:01:26 -07006676
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006677#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006678static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6679{
6680 struct common_audit_data ad;
6681 int err;
6682 u32 sid = 0;
6683 struct ib_security_struct *sec = ib_sec;
6684 struct lsm_ibpkey_audit ibpkey;
6685
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006686 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006687 if (err)
6688 return err;
6689
6690 ad.type = LSM_AUDIT_DATA_IBPKEY;
6691 ibpkey.subnet_prefix = subnet_prefix;
6692 ibpkey.pkey = pkey_val;
6693 ad.u.ibpkey = &ibpkey;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006694 return avc_has_perm(&selinux_state,
6695 sec->sid, sid,
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006696 SECCLASS_INFINIBAND_PKEY,
6697 INFINIBAND_PKEY__ACCESS, &ad);
6698}
6699
Daniel Jurgensab861df2017-05-19 15:48:58 +03006700static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6701 u8 port_num)
6702{
6703 struct common_audit_data ad;
6704 int err;
6705 u32 sid = 0;
6706 struct ib_security_struct *sec = ib_sec;
6707 struct lsm_ibendport_audit ibendport;
6708
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006709 err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
6710 &sid);
Daniel Jurgensab861df2017-05-19 15:48:58 +03006711
6712 if (err)
6713 return err;
6714
6715 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6716 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6717 ibendport.port = port_num;
6718 ad.u.ibendport = &ibendport;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006719 return avc_has_perm(&selinux_state,
6720 sec->sid, sid,
Daniel Jurgensab861df2017-05-19 15:48:58 +03006721 SECCLASS_INFINIBAND_ENDPORT,
6722 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6723}
6724
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006725static int selinux_ib_alloc_security(void **ib_sec)
6726{
6727 struct ib_security_struct *sec;
6728
6729 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6730 if (!sec)
6731 return -ENOMEM;
6732 sec->sid = current_sid();
6733
6734 *ib_sec = sec;
6735 return 0;
6736}
6737
6738static void selinux_ib_free_security(void *ib_sec)
6739{
6740 kfree(ib_sec);
6741}
Michael LeMayd7200242006-06-22 14:47:17 -07006742#endif
6743
Chenbo Fengec27c352017-10-18 13:00:25 -07006744#ifdef CONFIG_BPF_SYSCALL
6745static int selinux_bpf(int cmd, union bpf_attr *attr,
6746 unsigned int size)
6747{
6748 u32 sid = current_sid();
6749 int ret;
6750
6751 switch (cmd) {
6752 case BPF_MAP_CREATE:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006753 ret = avc_has_perm(&selinux_state,
6754 sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
Chenbo Fengec27c352017-10-18 13:00:25 -07006755 NULL);
6756 break;
6757 case BPF_PROG_LOAD:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006758 ret = avc_has_perm(&selinux_state,
6759 sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
Chenbo Fengec27c352017-10-18 13:00:25 -07006760 NULL);
6761 break;
6762 default:
6763 ret = 0;
6764 break;
6765 }
6766
6767 return ret;
6768}
6769
6770static u32 bpf_map_fmode_to_av(fmode_t fmode)
6771{
6772 u32 av = 0;
6773
6774 if (fmode & FMODE_READ)
6775 av |= BPF__MAP_READ;
6776 if (fmode & FMODE_WRITE)
6777 av |= BPF__MAP_WRITE;
6778 return av;
6779}
6780
Chenbo Fengf66e4482017-10-18 13:00:26 -07006781/* This function will check the file pass through unix socket or binder to see
6782 * if it is a bpf related object. And apply correspinding checks on the bpf
6783 * object based on the type. The bpf maps and programs, not like other files and
6784 * socket, are using a shared anonymous inode inside the kernel as their inode.
6785 * So checking that inode cannot identify if the process have privilege to
6786 * access the bpf object and that's why we have to add this additional check in
6787 * selinux_file_receive and selinux_binder_transfer_files.
6788 */
6789static int bpf_fd_pass(struct file *file, u32 sid)
6790{
6791 struct bpf_security_struct *bpfsec;
6792 struct bpf_prog *prog;
6793 struct bpf_map *map;
6794 int ret;
6795
6796 if (file->f_op == &bpf_map_fops) {
6797 map = file->private_data;
6798 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006799 ret = avc_has_perm(&selinux_state,
6800 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006801 bpf_map_fmode_to_av(file->f_mode), NULL);
6802 if (ret)
6803 return ret;
6804 } else if (file->f_op == &bpf_prog_fops) {
6805 prog = file->private_data;
6806 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006807 ret = avc_has_perm(&selinux_state,
6808 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006809 BPF__PROG_RUN, NULL);
6810 if (ret)
6811 return ret;
6812 }
6813 return 0;
6814}
6815
Chenbo Fengec27c352017-10-18 13:00:25 -07006816static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6817{
6818 u32 sid = current_sid();
6819 struct bpf_security_struct *bpfsec;
6820
6821 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006822 return avc_has_perm(&selinux_state,
6823 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006824 bpf_map_fmode_to_av(fmode), NULL);
6825}
6826
6827static int selinux_bpf_prog(struct bpf_prog *prog)
6828{
6829 u32 sid = current_sid();
6830 struct bpf_security_struct *bpfsec;
6831
6832 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006833 return avc_has_perm(&selinux_state,
6834 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006835 BPF__PROG_RUN, NULL);
6836}
6837
6838static int selinux_bpf_map_alloc(struct bpf_map *map)
6839{
6840 struct bpf_security_struct *bpfsec;
6841
6842 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6843 if (!bpfsec)
6844 return -ENOMEM;
6845
6846 bpfsec->sid = current_sid();
6847 map->security = bpfsec;
6848
6849 return 0;
6850}
6851
6852static void selinux_bpf_map_free(struct bpf_map *map)
6853{
6854 struct bpf_security_struct *bpfsec = map->security;
6855
6856 map->security = NULL;
6857 kfree(bpfsec);
6858}
6859
6860static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6861{
6862 struct bpf_security_struct *bpfsec;
6863
6864 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6865 if (!bpfsec)
6866 return -ENOMEM;
6867
6868 bpfsec->sid = current_sid();
6869 aux->security = bpfsec;
6870
6871 return 0;
6872}
6873
6874static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6875{
6876 struct bpf_security_struct *bpfsec = aux->security;
6877
6878 aux->security = NULL;
6879 kfree(bpfsec);
6880}
6881#endif
6882
Stephen Smalley59438b462019-11-27 12:04:36 -05006883static int selinux_lockdown(enum lockdown_reason what)
6884{
6885 struct common_audit_data ad;
6886 u32 sid = current_sid();
6887 int invalid_reason = (what <= LOCKDOWN_NONE) ||
6888 (what == LOCKDOWN_INTEGRITY_MAX) ||
6889 (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
6890
6891 if (WARN(invalid_reason, "Invalid lockdown reason")) {
6892 audit_log(audit_context(),
6893 GFP_ATOMIC, AUDIT_SELINUX_ERR,
6894 "lockdown_reason=invalid");
6895 return -EINVAL;
6896 }
6897
6898 ad.type = LSM_AUDIT_DATA_LOCKDOWN;
6899 ad.u.reason = what;
6900
6901 if (what <= LOCKDOWN_INTEGRITY_MAX)
6902 return avc_has_perm(&selinux_state,
6903 sid, sid, SECCLASS_LOCKDOWN,
6904 LOCKDOWN__INTEGRITY, &ad);
6905 else
6906 return avc_has_perm(&selinux_state,
6907 sid, sid, SECCLASS_LOCKDOWN,
6908 LOCKDOWN__CONFIDENTIALITY, &ad);
6909}
6910
Casey Schauflerbbd36622018-11-12 09:30:56 -08006911struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
6912 .lbs_cred = sizeof(struct task_security_struct),
Casey Schaufler33bf60c2018-11-12 12:02:49 -08006913 .lbs_file = sizeof(struct file_security_struct),
Casey Schauflerafb1cbe32018-09-21 17:19:29 -07006914 .lbs_inode = sizeof(struct inode_security_struct),
Casey Schauflerecd5f822018-11-20 11:55:02 -08006915 .lbs_ipc = sizeof(struct ipc_security_struct),
6916 .lbs_msg_msg = sizeof(struct msg_security_struct),
Casey Schauflerbbd36622018-11-12 09:30:56 -08006917};
6918
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006919#ifdef CONFIG_PERF_EVENTS
6920static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
6921{
6922 u32 requested, sid = current_sid();
6923
6924 if (type == PERF_SECURITY_OPEN)
6925 requested = PERF_EVENT__OPEN;
6926 else if (type == PERF_SECURITY_CPU)
6927 requested = PERF_EVENT__CPU;
6928 else if (type == PERF_SECURITY_KERNEL)
6929 requested = PERF_EVENT__KERNEL;
6930 else if (type == PERF_SECURITY_TRACEPOINT)
6931 requested = PERF_EVENT__TRACEPOINT;
6932 else
6933 return -EINVAL;
6934
6935 return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
6936 requested, NULL);
6937}
6938
6939static int selinux_perf_event_alloc(struct perf_event *event)
6940{
6941 struct perf_event_security_struct *perfsec;
6942
6943 perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
6944 if (!perfsec)
6945 return -ENOMEM;
6946
6947 perfsec->sid = current_sid();
6948 event->security = perfsec;
6949
6950 return 0;
6951}
6952
6953static void selinux_perf_event_free(struct perf_event *event)
6954{
6955 struct perf_event_security_struct *perfsec = event->security;
6956
6957 event->security = NULL;
6958 kfree(perfsec);
6959}
6960
6961static int selinux_perf_event_read(struct perf_event *event)
6962{
6963 struct perf_event_security_struct *perfsec = event->security;
6964 u32 sid = current_sid();
6965
6966 return avc_has_perm(&selinux_state, sid, perfsec->sid,
6967 SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
6968}
6969
6970static int selinux_perf_event_write(struct perf_event *event)
6971{
6972 struct perf_event_security_struct *perfsec = event->security;
6973 u32 sid = current_sid();
6974
6975 return avc_has_perm(&selinux_state, sid, perfsec->sid,
6976 SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
6977}
6978#endif
6979
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01006980/*
6981 * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
6982 * 1. any hooks that don't belong to (2.) or (3.) below,
6983 * 2. hooks that both access structures allocated by other hooks, and allocate
6984 * structures that can be later accessed by other hooks (mostly "cloning"
6985 * hooks),
6986 * 3. hooks that only allocate structures that can be later accessed by other
6987 * hooks ("allocating" hooks).
6988 *
6989 * Please follow block comment delimiters in the list to keep this order.
6990 *
6991 * This ordering is needed for SELinux runtime disable to work at least somewhat
6992 * safely. Breaking the ordering rules above might lead to NULL pointer derefs
6993 * when disabling SELinux at runtime.
6994 */
James Morrisca97d932017-02-15 00:18:51 +11006995static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006996 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6997 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6998 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6999 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02007000
Casey Schauflere20b0432015-05-02 15:11:36 -07007001 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
7002 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
7003 LSM_HOOK_INIT(capget, selinux_capget),
7004 LSM_HOOK_INIT(capset, selinux_capset),
7005 LSM_HOOK_INIT(capable, selinux_capable),
7006 LSM_HOOK_INIT(quotactl, selinux_quotactl),
7007 LSM_HOOK_INIT(quota_on, selinux_quota_on),
7008 LSM_HOOK_INIT(syslog, selinux_syslog),
7009 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05007010
Casey Schauflere20b0432015-05-02 15:11:36 -07007011 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007012
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05007013 LSM_HOOK_INIT(bprm_creds_for_exec, selinux_bprm_creds_for_exec),
Casey Schauflere20b0432015-05-02 15:11:36 -07007014 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
7015 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007016
Casey Schauflere20b0432015-05-02 15:11:36 -07007017 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
Al Viro204cc0c2018-12-13 13:41:47 -05007018 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
Casey Schauflere20b0432015-05-02 15:11:36 -07007019 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
7020 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
7021 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
7022 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
7023 LSM_HOOK_INIT(sb_mount, selinux_mount),
7024 LSM_HOOK_INIT(sb_umount, selinux_umount),
7025 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
7026 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007027
Stephen Smalley98aa0032020-01-17 15:24:07 -05007028 LSM_HOOK_INIT(move_mount, selinux_move_mount),
7029
Casey Schauflere20b0432015-05-02 15:11:36 -07007030 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04007031 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05007032
Casey Schauflere20b0432015-05-02 15:11:36 -07007033 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
7034 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
7035 LSM_HOOK_INIT(inode_create, selinux_inode_create),
7036 LSM_HOOK_INIT(inode_link, selinux_inode_link),
7037 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
7038 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
7039 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
7040 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
7041 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
7042 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
7043 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
7044 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
7045 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
7046 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
7047 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
7048 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
7049 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
7050 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
7051 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
7052 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
7053 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
7054 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
7055 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
7056 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04007057 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04007058 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Aaron Goidelac5656d2019-08-12 11:20:00 -04007059 LSM_HOOK_INIT(path_notify, selinux_path_notify),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01007061 LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
7062
Casey Schauflere20b0432015-05-02 15:11:36 -07007063 LSM_HOOK_INIT(file_permission, selinux_file_permission),
7064 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
Casey Schauflere20b0432015-05-02 15:11:36 -07007065 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
7066 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
7067 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
7068 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
7069 LSM_HOOK_INIT(file_lock, selinux_file_lock),
7070 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
7071 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
7072 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
7073 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007074
Casey Schauflere20b0432015-05-02 15:11:36 -07007075 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007076
Tetsuo Handaa79be232017-03-28 23:08:45 +09007077 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07007078 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
7079 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
Matthew Garrett3ec30112018-01-08 13:36:19 -08007080 LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
Casey Schauflere20b0432015-05-02 15:11:36 -07007081 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
7082 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
7083 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04007084 LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07007085 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07007086 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
7087 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
7088 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
7089 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
7090 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
7091 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
7092 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05007093 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07007094 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
7095 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
7096 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
7097 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
7098 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07007099 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09007100
Casey Schauflere20b0432015-05-02 15:11:36 -07007101 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
7102 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103
Casey Schauflere20b0432015-05-02 15:11:36 -07007104 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
7105 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
7106 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
7107 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Casey Schauflere20b0432015-05-02 15:11:36 -07007109 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
7110 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
7111 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112
Casey Schauflere20b0432015-05-02 15:11:36 -07007113 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
7114 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
7115 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007116
Casey Schauflere20b0432015-05-02 15:11:36 -07007117 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007118
Casey Schauflere20b0432015-05-02 15:11:36 -07007119 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
7120 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007121
Casey Schauflere20b0432015-05-02 15:11:36 -07007122 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
Casey Schauflere20b0432015-05-02 15:11:36 -07007123 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
7124 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05007125 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07007126 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
7127 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128
Casey Schauflere20b0432015-05-02 15:11:36 -07007129 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
7130 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07007131
Casey Schauflere20b0432015-05-02 15:11:36 -07007132 LSM_HOOK_INIT(socket_create, selinux_socket_create),
7133 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
David Herrmann0b811db2018-05-04 16:28:21 +02007134 LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
Casey Schauflere20b0432015-05-02 15:11:36 -07007135 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
7136 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
7137 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
7138 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
7139 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
7140 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
7141 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
7142 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
7143 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
7144 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
7145 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
7146 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
7147 LSM_HOOK_INIT(socket_getpeersec_stream,
7148 selinux_socket_getpeersec_stream),
7149 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
Casey Schauflere20b0432015-05-02 15:11:36 -07007150 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
7151 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
7152 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
7153 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
Richard Hainesd4529302018-02-13 20:57:18 +00007154 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
7155 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
7156 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
Casey Schauflere20b0432015-05-02 15:11:36 -07007157 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
7158 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
7159 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
7160 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
7161 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
7162 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
7163 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
Casey Schauflere20b0432015-05-02 15:11:36 -07007164 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
7165 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
7166 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
7167 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
7168 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007169#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03007170 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03007171 LSM_HOOK_INIT(ib_endport_manage_subnet,
7172 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007173 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
7174#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08007175#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07007176 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
7177 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
Casey Schauflere20b0432015-05-02 15:11:36 -07007178 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
7179 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
7180 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
7181 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
7182 selinux_xfrm_state_pol_flow_match),
7183 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007184#endif
Michael LeMayd7200242006-06-22 14:47:17 -07007185
7186#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07007187 LSM_HOOK_INIT(key_free, selinux_key_free),
7188 LSM_HOOK_INIT(key_permission, selinux_key_permission),
7189 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
David Howells3e412cc2020-01-14 17:07:13 +00007190#ifdef CONFIG_KEY_NOTIFICATIONS
7191 LSM_HOOK_INIT(watch_key, selinux_watch_key),
7192#endif
Michael LeMayd7200242006-06-22 14:47:17 -07007193#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007194
7195#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07007196 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
7197 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
7198 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007199#endif
Chenbo Fengec27c352017-10-18 13:00:25 -07007200
7201#ifdef CONFIG_BPF_SYSCALL
7202 LSM_HOOK_INIT(bpf, selinux_bpf),
7203 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
7204 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
Chenbo Fengec27c352017-10-18 13:00:25 -07007205 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
7206 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
7207#endif
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007208
7209#ifdef CONFIG_PERF_EVENTS
7210 LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007211 LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
7212 LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
7213 LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
7214#endif
Stephen Smalley59438b462019-11-27 12:04:36 -05007215
7216 LSM_HOOK_INIT(locked_down, selinux_lockdown),
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007217
7218 /*
7219 * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE
7220 */
7221 LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
7222 LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
7223 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
7224 LSM_HOOK_INIT(sb_add_mnt_opt, selinux_add_mnt_opt),
7225#ifdef CONFIG_SECURITY_NETWORK_XFRM
7226 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
7227#endif
7228
7229 /*
7230 * PUT "ALLOCATING" HOOKS HERE
7231 */
7232 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
7233 LSM_HOOK_INIT(msg_queue_alloc_security,
7234 selinux_msg_queue_alloc_security),
7235 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
7236 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
7237 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
7238 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
7239 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
7240 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
7241 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
7242 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
7243#ifdef CONFIG_SECURITY_INFINIBAND
7244 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
7245#endif
7246#ifdef CONFIG_SECURITY_NETWORK_XFRM
7247 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
7248 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
7249 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
7250 selinux_xfrm_state_alloc_acquire),
7251#endif
7252#ifdef CONFIG_KEYS
7253 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
7254#endif
7255#ifdef CONFIG_AUDIT
7256 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
7257#endif
7258#ifdef CONFIG_BPF_SYSCALL
7259 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
7260 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
7261#endif
7262#ifdef CONFIG_PERF_EVENTS
7263 LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
7264#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007265};
7266
7267static __init int selinux_init(void)
7268{
peter enderborgc103a912018-06-12 10:09:03 +02007269 pr_info("SELinux: Initializing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007270
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007271 memset(&selinux_state, 0, sizeof(selinux_state));
Paul Mooree5a5ca92018-03-01 17:38:30 -05007272 enforcing_set(&selinux_state, selinux_enforcing_boot);
Lakshmi Ramasubramanian8861d0a2020-09-14 10:31:57 -07007273 checkreqprot_set(&selinux_state, selinux_checkreqprot_boot);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05007274 selinux_avc_init(&selinux_state.avc);
Ondrej Mosnacek4b36cb72020-01-17 14:15:14 +01007275 mutex_init(&selinux_state.status_lock);
Stephen Smalley9ff9abc2020-08-26 13:28:53 -04007276 mutex_init(&selinux_state.policy_mutex);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007277
Linus Torvalds1da177e2005-04-16 15:20:36 -07007278 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11007279 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007280
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04007281 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
7282
Linus Torvalds1da177e2005-04-16 15:20:36 -07007283 avc_init();
7284
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007285 avtab_cache_init();
7286
7287 ebitmap_cache_init();
7288
7289 hashtab_cache_init();
7290
Casey Schauflerd69dece52017-01-18 17:09:05 -08007291 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007292
Paul Moore615e51f2014-06-26 14:33:56 -04007293 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
7294 panic("SELinux: Unable to register AVC netcache callback\n");
7295
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03007296 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
7297 panic("SELinux: Unable to register AVC LSM notifier callback\n");
7298
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007299 if (selinux_enforcing_boot)
peter enderborgc103a912018-06-12 10:09:03 +02007300 pr_debug("SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04007301 else
peter enderborgc103a912018-06-12 10:09:03 +02007302 pr_debug("SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07007303
Al Virod7167b12019-09-07 07:23:15 -04007304 fs_validate_description("selinux", selinux_fs_parameters);
David Howells442155c2018-11-01 23:07:24 +00007305
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306 return 0;
7307}
7308
Al Viroe8c26252010-03-23 06:36:54 -04007309static void delayed_superblock_init(struct super_block *sb, void *unused)
7310{
Al Viro204cc0c2018-12-13 13:41:47 -05007311 selinux_set_mnt_opts(sb, NULL, 0, NULL);
Al Viroe8c26252010-03-23 06:36:54 -04007312}
7313
Linus Torvalds1da177e2005-04-16 15:20:36 -07007314void selinux_complete_init(void)
7315{
peter enderborgc103a912018-06-12 10:09:03 +02007316 pr_debug("SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007317
7318 /* Set up any superblocks initialized prior to the policy load. */
peter enderborgc103a912018-06-12 10:09:03 +02007319 pr_debug("SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04007320 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007321}
7322
7323/* SELinux requires early initialization in order to label
7324 all processes and objects when they are created. */
Kees Cook3d6e5f62018-10-10 17:18:23 -07007325DEFINE_LSM(selinux) = {
Kees Cook07aed2f2018-10-10 17:18:24 -07007326 .name = "selinux",
Kees Cook14bd99c2018-09-19 19:57:06 -07007327 .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007328 .enabled = &selinux_enabled_boot,
Casey Schauflerbbd36622018-11-12 09:30:56 -08007329 .blobs = &selinux_blob_sizes,
Kees Cook3d6e5f62018-10-10 17:18:23 -07007330 .init = selinux_init,
7331};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007332
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007333#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007334
Florian Westphal591bb272017-07-26 11:40:52 +02007335static const struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05007336 {
7337 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007338 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007339 .hooknum = NF_INET_POST_ROUTING,
7340 .priority = NF_IP_PRI_SELINUX_LAST,
7341 },
7342 {
7343 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007344 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007345 .hooknum = NF_INET_FORWARD,
7346 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04007347 },
7348 {
7349 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00007350 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04007351 .hooknum = NF_INET_LOCAL_OUT,
7352 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007353 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04007354#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05007355 {
7356 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007357 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007358 .hooknum = NF_INET_POST_ROUTING,
7359 .priority = NF_IP6_PRI_SELINUX_LAST,
7360 },
7361 {
7362 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007363 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007364 .hooknum = NF_INET_FORWARD,
7365 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007366 },
Huw Davies2917f572016-06-27 15:06:15 -04007367 {
7368 .hook = selinux_ipv6_output,
7369 .pf = NFPROTO_IPV6,
7370 .hooknum = NF_INET_LOCAL_OUT,
7371 .priority = NF_IP6_PRI_SELINUX_FIRST,
7372 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07007373#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02007374};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007375
Florian Westphal8e71bf72017-04-21 11:49:09 +02007376static int __net_init selinux_nf_register(struct net *net)
7377{
7378 return nf_register_net_hooks(net, selinux_nf_ops,
7379 ARRAY_SIZE(selinux_nf_ops));
7380}
7381
7382static void __net_exit selinux_nf_unregister(struct net *net)
7383{
7384 nf_unregister_net_hooks(net, selinux_nf_ops,
7385 ARRAY_SIZE(selinux_nf_ops));
7386}
7387
7388static struct pernet_operations selinux_net_ops = {
7389 .init = selinux_nf_register,
7390 .exit = selinux_nf_unregister,
7391};
7392
Linus Torvalds1da177e2005-04-16 15:20:36 -07007393static int __init selinux_nf_ip_init(void)
7394{
Jiri Pirko25db6be2014-09-03 17:42:13 +02007395 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007396
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007397 if (!selinux_enabled_boot)
Jiri Pirko25db6be2014-09-03 17:42:13 +02007398 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05007399
peter enderborgc103a912018-06-12 10:09:03 +02007400 pr_debug("SELinux: Registering netfilter hooks\n");
Eric Parisfadcdb42007-02-22 18:11:31 -05007401
Florian Westphal8e71bf72017-04-21 11:49:09 +02007402 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07007403 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02007404 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007405
Jiri Pirko25db6be2014-09-03 17:42:13 +02007406 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007407}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408__initcall(selinux_nf_ip_init);
7409
7410#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7411static void selinux_nf_ip_exit(void)
7412{
peter enderborgc103a912018-06-12 10:09:03 +02007413 pr_debug("SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007414
Florian Westphal8e71bf72017-04-21 11:49:09 +02007415 unregister_pernet_subsys(&selinux_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007416}
7417#endif
7418
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007419#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007420
7421#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7422#define selinux_nf_ip_exit()
7423#endif
7424
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007425#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007426
7427#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007428int selinux_disable(struct selinux_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007429{
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007430 if (selinux_initialized(state)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007431 /* Not permitted after initial policy load. */
7432 return -EINVAL;
7433 }
7434
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007435 if (selinux_disabled(state)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436 /* Only do this once. */
7437 return -EINVAL;
7438 }
7439
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007440 selinux_mark_disabled(state);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007441
peter enderborgc103a912018-06-12 10:09:03 +02007442 pr_info("SELinux: Disabled at runtime.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007444 /*
7445 * Unregister netfilter hooks.
7446 * Must be done before security_delete_hooks() to avoid breaking
7447 * runtime disable.
7448 */
7449 selinux_nf_ip_exit();
7450
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07007451 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007452
Eric Parisaf8ff042009-09-20 21:23:01 -04007453 /* Try to destroy the avc node cache */
7454 avc_disable();
7455
Linus Torvalds1da177e2005-04-16 15:20:36 -07007456 /* Unregister selinuxfs. */
7457 exit_sel_fs();
7458
7459 return 0;
7460}
7461#endif