blob: a85a9f52e0c387b0ca0188404df03da5273c79e1 [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/*
Stephen Smalley90aa4f52023-07-18 13:13:35 -04003 * Security-Enhanced Linux (SELinux) security module
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * This file contains the SELinux hook function implementations.
6 *
Stephen Smalley0fe53222023-07-19 11:12:50 -04007 * Authors: Stephen Smalley, <stephen.smalley.work@gmail.com>
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/errno.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010029#include <linux/sched/signal.h>
Ingo Molnar29930022017-02-08 18:51:36 +010030#include <linux/sched/task.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070031#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/xattr.h>
33#include <linux/capability.h>
34#include <linux/unistd.h>
35#include <linux/mm.h>
36#include <linux/mman.h>
37#include <linux/slab.h>
38#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050039#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/spinlock.h>
42#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050043#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040045#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/namei.h>
47#include <linux/mount.h>
David Howells442155c2018-11-01 23:07:24 +000048#include <linux/fs_context.h>
49#include <linux/fs_parser.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <linux/netfilter_ipv4.h>
51#include <linux/netfilter_ipv6.h>
52#include <linux/tty.h>
53#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070054#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050056#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050057#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050058#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040059#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070061#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <linux/bitops.h>
63#include <linux/interrupt.h>
64#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000065#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <linux/tcp.h>
67#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080068#include <linux/dccp.h>
Richard Hainesd4529302018-02-13 20:57:18 +000069#include <linux/sctp.h>
70#include <net/sctp/structs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#include <linux/quota.h>
72#include <linux/un.h> /* for Unix socket types */
73#include <net/af_unix.h> /* for Unix socket types */
74#include <linux/parser.h>
75#include <linux/nfs_mount.h>
76#include <net/ipv6.h>
77#include <linux/hugetlb.h>
78#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070080#include <linux/string.h>
Eric Paris23970742006-09-25 23:32:01 -070081#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070082#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080083#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070084#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040085#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000086#include <linux/msg.h>
87#include <linux/shm.h>
Chenbo Fengec27c352017-10-18 13:00:25 -070088#include <linux/bpf.h>
Ondrej Mosnacekec882da2019-02-22 15:57:17 +010089#include <linux/kernfs.h>
90#include <linux/stringhash.h> /* for hashlen_string() */
David Howellse262e32d2018-11-01 23:07:23 +000091#include <uapi/linux/mount.h>
Aaron Goidelac5656d2019-08-12 11:20:00 -040092#include <linux/fsnotify.h>
93#include <linux/fanotify.h>
Paul Mooref4d653d2022-08-10 15:55:36 -040094#include <linux/io_uring.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 int __init checkreqprot_setup(char *str)
140{
141 unsigned long checkreqprot;
142
Stephen Smalleye9c38f92020-01-08 11:24:47 -0500143 if (!kstrtoul(str, 0, &checkreqprot)) {
Stephen Smalleye9c38f92020-01-08 11:24:47 -0500144 if (checkreqprot)
Paul Moorea7e46762023-03-16 11:43:08 -0400145 pr_err("SELinux: checkreqprot set to 1 via kernel parameter. This is no longer supported.\n");
Stephen Smalleye9c38f92020-01-08 11:24:47 -0500146 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500147 return 1;
148}
149__setup("checkreqprot=", checkreqprot_setup);
150
Paul Moored621d352008-01-29 08:43:36 -0500151/**
152 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
153 *
154 * Description:
155 * This function checks the SECMARK reference counter to see if any SECMARK
156 * targets are currently configured, if the reference counter is greater than
157 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400158 * enabled, false (0) if SECMARK is disabled. If the always_check_network
159 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500160 *
161 */
162static int selinux_secmark_enabled(void)
163{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500164 return (selinux_policycap_alwaysnetwork() ||
165 atomic_read(&selinux_secmark_refcount));
Chris PeBenito2be4d742013-05-03 09:05:39 -0400166}
167
168/**
169 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
170 *
171 * Description:
172 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
173 * (1) if any are enabled or false (0) if neither are enabled. If the
174 * always_check_network policy capability is enabled, peer labeling
175 * is always considered enabled.
176 *
177 */
178static int selinux_peerlbl_enabled(void)
179{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500180 return (selinux_policycap_alwaysnetwork() ||
181 netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500182}
183
Paul Moore615e51f2014-06-26 14:33:56 -0400184static int selinux_netcache_avc_callback(u32 event)
185{
186 if (event == AVC_CALLBACK_RESET) {
187 sel_netif_flush();
188 sel_netnode_flush();
189 sel_netport_flush();
190 synchronize_net();
191 }
192 return 0;
193}
194
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300195static int selinux_lsm_notifier_avc_callback(u32 event)
196{
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300197 if (event == AVC_CALLBACK_RESET) {
198 sel_ib_pkey_flush();
Janne Karhunen42df7442019-06-14 15:20:14 +0300199 call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300200 }
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300201
202 return 0;
203}
204
David Howellsd84f4f92008-11-14 10:39:23 +1100205/*
206 * initialise the security for the init task
207 */
208static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209{
210 struct task_security_struct *tsec;
211
Paul Moorecdeea452022-01-27 10:45:59 -0500212 tsec = selinux_cred(unrcu_pointer(current->real_cred));
David Howellsd84f4f92008-11-14 10:39:23 +1100213 tsec->osid = tsec->sid = SECINITSID_KERNEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214}
215
David Howells275bb412008-11-14 10:39:19 +1100216/*
David Howells88e67f32008-11-14 10:39:21 +1100217 * get the security ID of a set of credentials
218 */
219static inline u32 cred_sid(const struct cred *cred)
220{
221 const struct task_security_struct *tsec;
222
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700223 tsec = selinux_cred(cred);
David Howells88e67f32008-11-14 10:39:21 +1100224 return tsec->sid;
225}
226
227/*
David Howells3b11a1d2008-11-14 10:39:26 +1100228 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100229 */
Paul Mooreeb1231f2021-02-18 15:13:40 -0500230static inline u32 task_sid_obj(const struct task_struct *task)
David Howells275bb412008-11-14 10:39:19 +1100231{
David Howells275bb412008-11-14 10:39:19 +1100232 u32 sid;
233
234 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100235 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100236 rcu_read_unlock();
237 return sid;
238}
239
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500240static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
241
242/*
243 * Try reloading inode security labels that have been marked as invalid. The
244 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100245 * allowed; when set to false, returns -ECHILD when the label is
Al Viroe9193282018-04-24 21:31:02 -0400246 * invalid. The @dentry parameter should be set to a dentry of the inode.
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500247 */
248static int __inode_security_revalidate(struct inode *inode,
Al Viroe9193282018-04-24 21:31:02 -0400249 struct dentry *dentry,
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500250 bool may_sleep)
251{
Casey Schaufler80788c22018-09-21 17:19:11 -0700252 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500253
254 might_sleep_if(may_sleep);
255
Stephen Smalleye67b7982023-03-09 13:30:37 -0500256 if (selinux_initialized() &&
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500257 isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500258 if (!may_sleep)
259 return -ECHILD;
260
261 /*
262 * Try reloading the inode security label. This will fail if
263 * @opt_dentry is NULL and no dentry for this inode can be
264 * found; in that case, continue using the old label.
265 */
Al Viroe9193282018-04-24 21:31:02 -0400266 inode_doinit_with_dentry(inode, dentry);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500267 }
268 return 0;
269}
270
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500271static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
272{
Casey Schaufler80788c22018-09-21 17:19:11 -0700273 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500274}
275
276static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
277{
278 int error;
279
280 error = __inode_security_revalidate(inode, NULL, !rcu);
281 if (error)
282 return ERR_PTR(error);
Casey Schaufler80788c22018-09-21 17:19:11 -0700283 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500284}
285
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500286/*
287 * Get the security label of an inode.
288 */
289static struct inode_security_struct *inode_security(struct inode *inode)
290{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500291 __inode_security_revalidate(inode, NULL, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700292 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500293}
294
Paul Moore2c971652016-04-19 16:36:28 -0400295static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
296{
297 struct inode *inode = d_backing_inode(dentry);
298
Casey Schaufler80788c22018-09-21 17:19:11 -0700299 return selinux_inode(inode);
Paul Moore2c971652016-04-19 16:36:28 -0400300}
301
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500302/*
303 * Get the security label of a dentry's backing inode.
304 */
305static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
306{
307 struct inode *inode = d_backing_inode(dentry);
308
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500309 __inode_security_revalidate(inode, dentry, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700310 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500311}
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313static void inode_free_security(struct inode *inode)
314{
Casey Schaufler80788c22018-09-21 17:19:11 -0700315 struct inode_security_struct *isec = selinux_inode(inode);
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700316 struct superblock_security_struct *sbsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700318 if (!isec)
319 return;
Casey Schaufler1aea7802021-04-22 17:41:15 +0200320 sbsec = selinux_superblock(inode->i_sb);
Waiman Long9629d042015-07-10 17:19:56 -0400321 /*
322 * As not all inode security structures are in a list, we check for
323 * empty list outside of the lock to make sure that we won't waste
324 * time taking a lock doing nothing.
325 *
326 * The list_del_init() function can be safely called more than once.
327 * It should not be possible for this function to be called with
328 * concurrent list_add(), but for better safety against future changes
329 * in the code, we use list_empty_careful() here.
330 */
331 if (!list_empty_careful(&isec->list)) {
332 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400334 spin_unlock(&sbsec->isec_lock);
335 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336}
337
Al Virobd323652018-12-13 15:04:59 -0500338struct selinux_mnt_opts {
Scott Mayhewb8b87fd2022-01-31 13:57:36 -0500339 u32 fscontext_sid;
340 u32 context_sid;
341 u32 rootcontext_sid;
342 u32 defcontext_sid;
Al Virobd323652018-12-13 15:04:59 -0500343};
344
Al Viro204cc0c2018-12-13 13:41:47 -0500345static void selinux_free_mnt_opts(void *mnt_opts)
346{
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100347 kfree(mnt_opts);
Al Viro204cc0c2018-12-13 13:41:47 -0500348}
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350enum {
Eric Paris31e87932007-09-19 17:19:12 -0400351 Opt_error = -1,
David Howells442155c2018-11-01 23:07:24 +0000352 Opt_context = 0,
353 Opt_defcontext = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 Opt_fscontext = 2,
David Howells442155c2018-11-01 23:07:24 +0000355 Opt_rootcontext = 3,
356 Opt_seclabel = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357};
358
Al Viroda3d76a2018-12-17 10:14:16 -0500359#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
Christian Göttsche4158cb62023-04-20 17:05:03 +0200360static const struct {
Al Viro169d68efb2018-12-14 22:44:50 -0500361 const char *name;
362 int len;
363 int opt;
364 bool has_arg;
365} tokens[] = {
Al Viroda3d76a2018-12-17 10:14:16 -0500366 A(context, true),
367 A(fscontext, true),
368 A(defcontext, true),
369 A(rootcontext, true),
370 A(seclabel, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371};
Al Viro169d68efb2018-12-14 22:44:50 -0500372#undef A
373
374static int match_opt_prefix(char *s, int l, char **arg)
375{
376 int i;
377
378 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
379 size_t len = tokens[i].len;
380 if (len > l || memcmp(s, tokens[i].name, len))
381 continue;
382 if (tokens[i].has_arg) {
383 if (len == l || s[len] != '=')
384 continue;
385 *arg = s + len + 1;
386 } else if (len != l)
387 continue;
388 return tokens[i].opt;
389 }
390 return Opt_error;
391}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
394
Eric Parisc312feb2006-07-10 04:43:53 -0700395static int may_context_mount_sb_relabel(u32 sid,
396 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100397 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700398{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700399 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Parisc312feb2006-07-10 04:43:53 -0700400 int rc;
401
Stephen Smalleye67b7982023-03-09 13:30:37 -0500402 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700403 FILESYSTEM__RELABELFROM, NULL);
404 if (rc)
405 return rc;
406
Stephen Smalleye67b7982023-03-09 13:30:37 -0500407 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700408 FILESYSTEM__RELABELTO, NULL);
409 return rc;
410}
411
Eric Paris08089252006-07-10 04:43:55 -0700412static int may_context_mount_inode_relabel(u32 sid,
413 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100414 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700415{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700416 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Paris08089252006-07-10 04:43:55 -0700417 int rc;
Stephen Smalleye67b7982023-03-09 13:30:37 -0500418 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700419 FILESYSTEM__RELABELFROM, NULL);
420 if (rc)
421 return rc;
422
Stephen Smalleye67b7982023-03-09 13:30:37 -0500423 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700424 FILESYSTEM__ASSOCIATE, NULL);
425 return rc;
426}
427
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100428static int selinux_is_genfs_special_handling(struct super_block *sb)
Eric Parisb43e7252012-10-10 14:27:35 -0400429{
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100430 /* Special handling. Genfs but also in-core setxattr handler */
431 return !strcmp(sb->s_type->name, "sysfs") ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500432 !strcmp(sb->s_type->name, "pstore") ||
433 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6fb2017-01-09 10:07:30 -0500434 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500435 !strcmp(sb->s_type->name, "rootfs") ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500436 (selinux_policycap_cgroupseclabel() &&
Stephen Smalley2651225b2017-02-28 10:35:56 -0500437 (!strcmp(sb->s_type->name, "cgroup") ||
438 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400439}
440
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100441static int selinux_is_sblabel_mnt(struct super_block *sb)
442{
Casey Schaufler1aea7802021-04-22 17:41:15 +0200443 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100444
445 /*
446 * IMPORTANT: Double-check logic in this function when adding a new
447 * SECURITY_FS_USE_* definition!
448 */
449 BUILD_BUG_ON(SECURITY_FS_USE_MAX != 7);
450
451 switch (sbsec->behavior) {
452 case SECURITY_FS_USE_XATTR:
453 case SECURITY_FS_USE_TRANS:
454 case SECURITY_FS_USE_TASK:
455 case SECURITY_FS_USE_NATIVE:
456 return 1;
457
458 case SECURITY_FS_USE_GENFS:
459 return selinux_is_genfs_special_handling(sb);
460
461 /* Never allow relabeling on context mounts */
462 case SECURITY_FS_USE_MNTPOINT:
463 case SECURITY_FS_USE_NONE:
464 default:
465 return 0;
466 }
467}
468
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100469static int sb_check_xattr_support(struct super_block *sb)
470{
GONG, Ruiqi0266c252022-01-25 15:11:33 +0800471 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100472 struct dentry *root = sb->s_root;
473 struct inode *root_inode = d_backing_inode(root);
474 u32 sid;
475 int rc;
476
477 /*
478 * Make sure that the xattr handler exists and that no
479 * error other than -ENODATA is returned by getxattr on
480 * the root directory. -ENODATA is ok, as this may be
481 * the first boot of the SELinux kernel before we have
482 * assigned xattr values to the filesystem.
483 */
484 if (!(root_inode->i_opflags & IOP_XATTR)) {
485 pr_warn("SELinux: (dev %s, type %s) has no xattr support\n",
486 sb->s_id, sb->s_type->name);
487 goto fallback;
488 }
489
490 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
491 if (rc < 0 && rc != -ENODATA) {
492 if (rc == -EOPNOTSUPP) {
493 pr_warn("SELinux: (dev %s, type %s) has no security xattr handler\n",
494 sb->s_id, sb->s_type->name);
495 goto fallback;
496 } else {
497 pr_warn("SELinux: (dev %s, type %s) getxattr errno %d\n",
498 sb->s_id, sb->s_type->name, -rc);
499 return rc;
500 }
501 }
502 return 0;
503
504fallback:
505 /* No xattr support - try to fallback to genfs if possible. */
Stephen Smalleye67b7982023-03-09 13:30:37 -0500506 rc = security_genfs_sid(sb->s_type->name, "/",
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100507 SECCLASS_DIR, &sid);
508 if (rc)
509 return -EOPNOTSUPP;
510
511 pr_warn("SELinux: (dev %s, type %s) falling back to genfs\n",
512 sb->s_id, sb->s_type->name);
513 sbsec->behavior = SECURITY_FS_USE_GENFS;
514 sbsec->sid = sid;
515 return 0;
516}
517
Eric Parisc9180a52007-11-30 13:00:35 -0500518static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
Casey Schaufler1aea7802021-04-22 17:41:15 +0200520 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000522 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 int rc = 0;
524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
Ondrej Mosnacek08abe462021-01-13 13:38:02 +0100526 rc = sb_check_xattr_support(sb);
527 if (rc)
528 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 }
530
Eric Pariseadcabc2012-08-24 15:59:14 -0400531 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400532
533 /*
534 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
535 * leave the flag untouched because sb_clone_mnt_opts might be handing
536 * us a superblock that needs the flag to be cleared.
537 */
Eric Parisb43e7252012-10-10 14:27:35 -0400538 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400539 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400540 else
541 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500544 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 /* Initialize any other inodes associated with the superblock, e.g.
547 inodes created prior to initial policy load or inodes created
548 during get_sb by a pseudo filesystem that directly
549 populates itself. */
550 spin_lock(&sbsec->isec_lock);
Al Viro8d641242018-12-10 15:34:12 -0500551 while (!list_empty(&sbsec->isec_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 struct inode_security_struct *isec =
Al Viro8d641242018-12-10 15:34:12 -0500553 list_first_entry(&sbsec->isec_head,
Eric Parisc9180a52007-11-30 13:00:35 -0500554 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 struct inode *inode = isec->inode;
Stephen Smalley923190d32014-10-06 16:32:52 -0400556 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 spin_unlock(&sbsec->isec_lock);
558 inode = igrab(inode);
559 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500560 if (!IS_PRIVATE(inode))
Paul Moorecb89e242020-01-10 16:32:10 -0500561 inode_doinit_with_dentry(inode, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 iput(inode);
563 }
564 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
566 spin_unlock(&sbsec->isec_lock);
Eric Parisc9180a52007-11-30 13:00:35 -0500567 return rc;
568}
569
Eric Parisc9180a52007-11-30 13:00:35 -0500570static int bad_option(struct superblock_security_struct *sbsec, char flag,
571 u32 old_sid, u32 new_sid)
572{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500573 char mnt_flags = sbsec->flags & SE_MNTMASK;
574
Eric Parisc9180a52007-11-30 13:00:35 -0500575 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500576 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500577 if (!(sbsec->flags & flag) ||
578 (old_sid != new_sid))
579 return 1;
580
581 /* check if we were passed the same options twice,
582 * aka someone passed context=a,context=b
583 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500584 if (!(sbsec->flags & SE_SBINITIALIZED))
585 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500586 return 1;
587 return 0;
588}
Eric Parise0007522008-03-05 10:31:54 -0500589
Eric Parisc9180a52007-11-30 13:00:35 -0500590/*
591 * Allow filesystems with binary mount data to explicitly set mount point
592 * labeling information.
593 */
Eric Parise0007522008-03-05 10:31:54 -0500594static int selinux_set_mnt_opts(struct super_block *sb,
Al Viro204cc0c2018-12-13 13:41:47 -0500595 void *mnt_opts,
David Quigley649f6e72013-05-22 12:50:36 -0400596 unsigned long kern_flags,
597 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500598{
David Howells275bb412008-11-14 10:39:19 +1100599 const struct cred *cred = current_cred();
Casey Schaufler1aea7802021-04-22 17:41:15 +0200600 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Ondrej Mosnacekb159e862020-11-04 13:01:10 +0100601 struct dentry *root = sb->s_root;
Al Virobd323652018-12-13 15:04:59 -0500602 struct selinux_mnt_opts *opts = mnt_opts;
Paul Moore2c971652016-04-19 16:36:28 -0400603 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500604 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
605 u32 defcontext_sid = 0;
Al Virobd323652018-12-13 15:04:59 -0500606 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500607
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +0200608 /*
609 * Specifying internal flags without providing a place to
610 * place the results is not allowed
611 */
612 if (kern_flags && !set_kern_flags)
613 return -EINVAL;
614
Eric Parisc9180a52007-11-30 13:00:35 -0500615 mutex_lock(&sbsec->lock);
616
Stephen Smalleye67b7982023-03-09 13:30:37 -0500617 if (!selinux_initialized()) {
Al Virobd323652018-12-13 15:04:59 -0500618 if (!opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500619 /* Defer initialization until selinux_complete_init,
620 after the initial policy is loaded and the security
621 server is ready to handle calls. */
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +0200622 if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
623 sbsec->flags |= SE_SBNATIVE;
624 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
625 }
Eric Parisc9180a52007-11-30 13:00:35 -0500626 goto out;
627 }
628 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200629 pr_warn("SELinux: Unable to set superblock options "
Eric Paris744ba352008-04-17 11:52:44 -0400630 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500631 goto out;
632 }
633
634 /*
Eric Parise0007522008-03-05 10:31:54 -0500635 * Binary mount data FS will come through this function twice. Once
636 * from an explicit call and once from the generic calls from the vfs.
637 * Since the generic VFS calls will not contain any security mount data
638 * we need to skip the double mount verification.
639 *
640 * This does open a hole in which we will not notice if the first
Jonas Lindner9691e4f2022-06-09 00:36:16 +0200641 * mount using this sb set explicit options and a second mount using
Eric Parise0007522008-03-05 10:31:54 -0500642 * this sb does not set any security options. (The first options
643 * will be used for both mounts)
644 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500645 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Al Virobd323652018-12-13 15:04:59 -0500646 && !opts)
Eric Parisf5269712008-05-14 11:27:45 -0400647 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500648
Paul Moore2c971652016-04-19 16:36:28 -0400649 root_isec = backing_inode_security_novalidate(root);
650
Eric Parise0007522008-03-05 10:31:54 -0500651 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500652 * parse the mount options, check if they are valid sids.
653 * also check if someone is trying to mount the same sb more
654 * than once with different security options.
655 */
Al Virobd323652018-12-13 15:04:59 -0500656 if (opts) {
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100657 if (opts->fscontext_sid) {
658 fscontext_sid = opts->fscontext_sid;
Eric Parisc9180a52007-11-30 13:00:35 -0500659 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
660 fscontext_sid))
661 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500662 sbsec->flags |= FSCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500663 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100664 if (opts->context_sid) {
665 context_sid = opts->context_sid;
Eric Parisc9180a52007-11-30 13:00:35 -0500666 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
667 context_sid))
668 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500669 sbsec->flags |= CONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500670 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100671 if (opts->rootcontext_sid) {
672 rootcontext_sid = opts->rootcontext_sid;
Eric Parisc9180a52007-11-30 13:00:35 -0500673 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
674 rootcontext_sid))
675 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500676 sbsec->flags |= ROOTCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500677 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100678 if (opts->defcontext_sid) {
679 defcontext_sid = opts->defcontext_sid;
Eric Parisc9180a52007-11-30 13:00:35 -0500680 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
681 defcontext_sid))
682 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500683 sbsec->flags |= DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500684 }
685 }
686
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500687 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500688 /* previously mounted with options, but not on this attempt? */
Al Virobd323652018-12-13 15:04:59 -0500689 if ((sbsec->flags & SE_MNTMASK) && !opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500690 goto out_double_mount;
691 rc = 0;
692 goto out;
693 }
694
James Morris089be432008-07-15 18:32:49 +1000695 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400696 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
697
Stephen Smalley8e014722015-06-04 16:22:17 -0400698 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700699 !strcmp(sb->s_type->name, "tracefs") ||
Hridya Valsarajua20456a2020-02-01 17:46:23 -0800700 !strcmp(sb->s_type->name, "binder") ||
Connor O'Brien4ca54d32020-02-07 10:01:49 -0800701 !strcmp(sb->s_type->name, "bpf") ||
Christian Göttsche8a764ef2021-09-28 17:39:31 +0200702 !strcmp(sb->s_type->name, "pstore") ||
703 !strcmp(sb->s_type->name, "securityfs"))
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100704 sbsec->flags |= SE_SBGENFS;
705
706 if (!strcmp(sb->s_type->name, "sysfs") ||
Antonio Murdaca901ef842017-02-09 17:02:42 +0100707 !strcmp(sb->s_type->name, "cgroup") ||
708 !strcmp(sb->s_type->name, "cgroup2"))
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100709 sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR;
Eric Parisc9180a52007-11-30 13:00:35 -0500710
David Quigleyeb9ae682013-05-22 12:50:37 -0400711 if (!sbsec->behavior) {
712 /*
713 * Determine the labeling behavior to use for this
714 * filesystem type.
715 */
Stephen Smalleye67b7982023-03-09 13:30:37 -0500716 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400717 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +0200718 pr_warn("%s: security_fs_use(%s) returned %d\n",
David Quigleyeb9ae682013-05-22 12:50:37 -0400719 __func__, sb->s_type->name, rc);
720 goto out;
721 }
Eric Parisc9180a52007-11-30 13:00:35 -0500722 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500723
724 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500725 * If this is a user namespace mount and the filesystem type is not
726 * explicitly whitelisted, then no contexts are allowed on the command
727 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500728 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500729 if (sb->s_user_ns != &init_user_ns &&
730 strcmp(sb->s_type->name, "tmpfs") &&
731 strcmp(sb->s_type->name, "ramfs") &&
Vivek Goyal7fa2e792021-02-11 13:03:03 -0500732 strcmp(sb->s_type->name, "devpts") &&
733 strcmp(sb->s_type->name, "overlay")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500734 if (context_sid || fscontext_sid || rootcontext_sid ||
735 defcontext_sid) {
736 rc = -EACCES;
737 goto out;
738 }
739 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
740 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
Stephen Smalleye67b7982023-03-09 13:30:37 -0500741 rc = security_transition_sid(current_sid(),
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500742 current_sid(),
Seth Forsheeaad82892016-04-26 14:36:20 -0500743 SECCLASS_FILE, NULL,
744 &sbsec->mntpoint_sid);
745 if (rc)
746 goto out;
747 }
748 goto out_set_opts;
749 }
750
Eric Parisc9180a52007-11-30 13:00:35 -0500751 /* sets the context of the superblock for the fs being mounted. */
752 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100753 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500754 if (rc)
755 goto out;
756
757 sbsec->sid = fscontext_sid;
758 }
759
760 /*
761 * Switch to using mount point labeling behavior.
762 * sets the label used on all file below the mountpoint, and will set
763 * the superblock context if not already set.
764 */
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +0200765 if (sbsec->flags & SE_SBNATIVE) {
766 /*
767 * This means we are initializing a superblock that has been
768 * mounted before the SELinux was initialized and the
769 * filesystem requested native labeling. We had already
770 * returned SECURITY_LSM_NATIVE_LABELS in *set_kern_flags
771 * in the original mount attempt, so now we just need to set
772 * the SECURITY_FS_USE_NATIVE behavior.
773 */
774 sbsec->behavior = SECURITY_FS_USE_NATIVE;
775 } else if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400776 sbsec->behavior = SECURITY_FS_USE_NATIVE;
777 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
778 }
779
Eric Parisc9180a52007-11-30 13:00:35 -0500780 if (context_sid) {
781 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100782 rc = may_context_mount_sb_relabel(context_sid, sbsec,
783 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500784 if (rc)
785 goto out;
786 sbsec->sid = context_sid;
787 } else {
David Howells275bb412008-11-14 10:39:19 +1100788 rc = may_context_mount_inode_relabel(context_sid, sbsec,
789 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500790 if (rc)
791 goto out;
792 }
793 if (!rootcontext_sid)
794 rootcontext_sid = context_sid;
795
796 sbsec->mntpoint_sid = context_sid;
797 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
798 }
799
800 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100801 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
802 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500803 if (rc)
804 goto out;
805
806 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500807 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500808 }
809
810 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400811 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
812 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500813 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200814 pr_warn("SELinux: defcontext option is "
Eric Parisc9180a52007-11-30 13:00:35 -0500815 "invalid for this filesystem type\n");
816 goto out;
817 }
818
819 if (defcontext_sid != sbsec->def_sid) {
820 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100821 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500822 if (rc)
823 goto out;
824 }
825
826 sbsec->def_sid = defcontext_sid;
827 }
828
Seth Forsheeaad82892016-04-26 14:36:20 -0500829out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500830 rc = sb_finish_set_opts(sb);
831out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700832 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500834out_double_mount:
835 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200836 pr_warn("SELinux: mount invalid. Same superblock, different "
Al Virobd323652018-12-13 15:04:59 -0500837 "security settings for (dev %s, type %s)\n", sb->s_id,
838 sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500839 goto out;
840}
841
Jeff Layton094f7b62013-04-01 08:14:24 -0400842static int selinux_cmp_sb_context(const struct super_block *oldsb,
843 const struct super_block *newsb)
844{
Casey Schaufler1aea7802021-04-22 17:41:15 +0200845 struct superblock_security_struct *old = selinux_superblock(oldsb);
846 struct superblock_security_struct *new = selinux_superblock(newsb);
Jeff Layton094f7b62013-04-01 08:14:24 -0400847 char oldflags = old->flags & SE_MNTMASK;
848 char newflags = new->flags & SE_MNTMASK;
849
850 if (oldflags != newflags)
851 goto mismatch;
852 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
853 goto mismatch;
854 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
855 goto mismatch;
856 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
857 goto mismatch;
858 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500859 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
860 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400861 if (oldroot->sid != newroot->sid)
862 goto mismatch;
863 }
864 return 0;
865mismatch:
peter enderborgc103a912018-06-12 10:09:03 +0200866 pr_warn("SELinux: mount invalid. Same superblock, "
Jeff Layton094f7b62013-04-01 08:14:24 -0400867 "different security settings for (dev %s, "
868 "type %s)\n", newsb->s_id, newsb->s_type->name);
869 return -EBUSY;
870}
871
872static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400873 struct super_block *newsb,
874 unsigned long kern_flags,
875 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500876{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400877 int rc = 0;
Casey Schaufler1aea7802021-04-22 17:41:15 +0200878 const struct superblock_security_struct *oldsbsec =
879 selinux_superblock(oldsb);
880 struct superblock_security_struct *newsbsec = selinux_superblock(newsb);
Eric Parisc9180a52007-11-30 13:00:35 -0500881
882 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
883 int set_context = (oldsbsec->flags & CONTEXT_MNT);
884 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
885
Eric Paris0f5e6422008-04-21 16:24:11 -0400886 /*
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400887 * Specifying internal flags without providing a place to
888 * place the results is not allowed.
889 */
890 if (kern_flags && !set_kern_flags)
891 return -EINVAL;
892
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +0200893 mutex_lock(&newsbsec->lock);
894
895 /*
896 * if the parent was able to be mounted it clearly had no special lsm
897 * mount options. thus we can safely deal with this superblock later
898 */
899 if (!selinux_initialized()) {
900 if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
901 newsbsec->flags |= SE_SBNATIVE;
902 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
903 }
904 goto out;
905 }
906
Eric Parisc9180a52007-11-30 13:00:35 -0500907 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500908 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500909
Jeff Layton094f7b62013-04-01 08:14:24 -0400910 /* if fs is reusing a sb, make sure that the contexts match */
J. Bruce Fields3815a242019-03-05 16:17:58 -0500911 if (newsbsec->flags & SE_SBINITIALIZED) {
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +0200912 mutex_unlock(&newsbsec->lock);
J. Bruce Fields3815a242019-03-05 16:17:58 -0500913 if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
914 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
Jeff Layton094f7b62013-04-01 08:14:24 -0400915 return selinux_cmp_sb_context(oldsb, newsb);
J. Bruce Fields3815a242019-03-05 16:17:58 -0500916 }
Eric Paris5a552612008-04-09 14:08:35 -0400917
Eric Parisc9180a52007-11-30 13:00:35 -0500918 newsbsec->flags = oldsbsec->flags;
919
920 newsbsec->sid = oldsbsec->sid;
921 newsbsec->def_sid = oldsbsec->def_sid;
922 newsbsec->behavior = oldsbsec->behavior;
923
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400924 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
925 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
Stephen Smalleye67b7982023-03-09 13:30:37 -0500926 rc = security_fs_use(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400927 if (rc)
928 goto out;
929 }
930
931 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
932 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
933 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
934 }
935
Eric Parisc9180a52007-11-30 13:00:35 -0500936 if (set_context) {
937 u32 sid = oldsbsec->mntpoint_sid;
938
939 if (!set_fscontext)
940 newsbsec->sid = sid;
941 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500942 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500943 newisec->sid = sid;
944 }
945 newsbsec->mntpoint_sid = sid;
946 }
947 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500948 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
949 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500950
951 newisec->sid = oldisec->sid;
952 }
953
954 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400955out:
Eric Parisc9180a52007-11-30 13:00:35 -0500956 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400957 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500958}
959
Xiu Jianfengef54ccb2022-06-17 17:44:12 +0800960/*
Christian Göttsche3d9047a2023-04-20 17:04:59 +0200961 * NOTE: the caller is responsible for freeing the memory even if on error.
Xiu Jianfengef54ccb2022-06-17 17:44:12 +0800962 */
Al Viroba641862018-12-14 20:28:15 -0500963static int selinux_add_opt(int token, const char *s, void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500964{
Al Viroba641862018-12-14 20:28:15 -0500965 struct selinux_mnt_opts *opts = *mnt_opts;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100966 u32 *dst_sid;
967 int rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500968
Paul Moore6cd9d4b2021-12-21 15:01:29 -0500969 if (token == Opt_seclabel)
970 /* eaten and completely ignored */
Al Viro169d68efb2018-12-14 22:44:50 -0500971 return 0;
Bernard Zhao2e08df32021-12-10 04:03:58 -0800972 if (!s)
Xiu Jianfengef54ccb2022-06-17 17:44:12 +0800973 return -EINVAL;
Eric Parisc9180a52007-11-30 13:00:35 -0500974
Stephen Smalleye67b7982023-03-09 13:30:37 -0500975 if (!selinux_initialized()) {
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100976 pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n");
977 return -EINVAL;
978 }
979
Al Viroba641862018-12-14 20:28:15 -0500980 if (!opts) {
Paul Moore6cd9d4b2021-12-21 15:01:29 -0500981 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
Al Viroba641862018-12-14 20:28:15 -0500982 if (!opts)
983 return -ENOMEM;
984 *mnt_opts = opts;
985 }
Bernard Zhao2e08df32021-12-10 04:03:58 -0800986
Al Viroba641862018-12-14 20:28:15 -0500987 switch (token) {
988 case Opt_context:
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100989 if (opts->context_sid || opts->defcontext_sid)
Paul Moore6cd9d4b2021-12-21 15:01:29 -0500990 goto err;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100991 dst_sid = &opts->context_sid;
Al Viroba641862018-12-14 20:28:15 -0500992 break;
993 case Opt_fscontext:
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100994 if (opts->fscontext_sid)
Paul Moore6cd9d4b2021-12-21 15:01:29 -0500995 goto err;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100996 dst_sid = &opts->fscontext_sid;
Al Viroba641862018-12-14 20:28:15 -0500997 break;
998 case Opt_rootcontext:
Ondrej Mosnacek70f41692022-02-02 13:55:29 +0100999 if (opts->rootcontext_sid)
Paul Moore6cd9d4b2021-12-21 15:01:29 -05001000 goto err;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01001001 dst_sid = &opts->rootcontext_sid;
Al Viroba641862018-12-14 20:28:15 -05001002 break;
1003 case Opt_defcontext:
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01001004 if (opts->context_sid || opts->defcontext_sid)
Paul Moore6cd9d4b2021-12-21 15:01:29 -05001005 goto err;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01001006 dst_sid = &opts->defcontext_sid;
Al Viroba641862018-12-14 20:28:15 -05001007 break;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01001008 default:
1009 WARN_ON(1);
1010 return -EINVAL;
Al Viroba641862018-12-14 20:28:15 -05001011 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05001012 rc = security_context_str_to_sid(s, dst_sid, GFP_KERNEL);
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01001013 if (rc)
1014 pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n",
1015 s, rc);
1016 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -05001017
Paul Moore6cd9d4b2021-12-21 15:01:29 -05001018err:
Eric Parisc9180a52007-11-30 13:00:35 -05001019 pr_warn(SEL_MOUNT_FAIL_MSG);
1020 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Al Viroe3489f82018-12-13 00:24:36 -05001023static int show_sid(struct seq_file *m, u32 sid)
Eric Paris2069f452008-07-04 09:47:13 +10001024{
Al Viroe3489f82018-12-13 00:24:36 -05001025 char *context = NULL;
1026 u32 len;
1027 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Stephen Smalleye67b7982023-03-09 13:30:37 -05001029 rc = security_sid_to_context(sid, &context, &len);
Al Viroe3489f82018-12-13 00:24:36 -05001030 if (!rc) {
Christian Göttsche4d3d0ed2022-02-17 15:21:28 +01001031 bool has_comma = strchr(context, ',');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
David Howells442155c2018-11-01 23:07:24 +00001033 seq_putc(m, '=');
Eric Paris2069f452008-07-04 09:47:13 +10001034 if (has_comma)
1035 seq_putc(m, '\"');
Al Viroe3489f82018-12-13 00:24:36 -05001036 seq_escape(m, context, "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001037 if (has_comma)
1038 seq_putc(m, '\"');
1039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 return rc;
1042}
Eric Paris2069f452008-07-04 09:47:13 +10001043
1044static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1045{
Casey Schaufler1aea7802021-04-22 17:41:15 +02001046 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Eric Paris2069f452008-07-04 09:47:13 +10001047 int rc;
1048
Al Viroe3489f82018-12-13 00:24:36 -05001049 if (!(sbsec->flags & SE_SBINITIALIZED))
1050 return 0;
1051
Stephen Smalleye67b7982023-03-09 13:30:37 -05001052 if (!selinux_initialized())
Al Viroe3489f82018-12-13 00:24:36 -05001053 return 0;
1054
1055 if (sbsec->flags & FSCONTEXT_MNT) {
1056 seq_putc(m, ',');
1057 seq_puts(m, FSCONTEXT_STR);
1058 rc = show_sid(m, sbsec->sid);
1059 if (rc)
1060 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001061 }
Al Viroe3489f82018-12-13 00:24:36 -05001062 if (sbsec->flags & CONTEXT_MNT) {
1063 seq_putc(m, ',');
1064 seq_puts(m, CONTEXT_STR);
1065 rc = show_sid(m, sbsec->mntpoint_sid);
1066 if (rc)
1067 return rc;
1068 }
1069 if (sbsec->flags & DEFCONTEXT_MNT) {
1070 seq_putc(m, ',');
1071 seq_puts(m, DEFCONTEXT_STR);
1072 rc = show_sid(m, sbsec->def_sid);
1073 if (rc)
1074 return rc;
1075 }
1076 if (sbsec->flags & ROOTCONTEXT_MNT) {
Ondrej Mosnacekb159e862020-11-04 13:01:10 +01001077 struct dentry *root = sb->s_root;
Al Viroe3489f82018-12-13 00:24:36 -05001078 struct inode_security_struct *isec = backing_inode_security(root);
1079 seq_putc(m, ',');
1080 seq_puts(m, ROOTCONTEXT_STR);
1081 rc = show_sid(m, isec->sid);
1082 if (rc)
1083 return rc;
1084 }
1085 if (sbsec->flags & SBLABEL_MNT) {
1086 seq_putc(m, ',');
David Howells442155c2018-11-01 23:07:24 +00001087 seq_puts(m, SECLABEL_STR);
Al Viroe3489f82018-12-13 00:24:36 -05001088 }
1089 return 0;
Eric Paris2069f452008-07-04 09:47:13 +10001090}
1091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092static inline u16 inode_mode_to_security_class(umode_t mode)
1093{
1094 switch (mode & S_IFMT) {
1095 case S_IFSOCK:
1096 return SECCLASS_SOCK_FILE;
1097 case S_IFLNK:
1098 return SECCLASS_LNK_FILE;
1099 case S_IFREG:
1100 return SECCLASS_FILE;
1101 case S_IFBLK:
1102 return SECCLASS_BLK_FILE;
1103 case S_IFDIR:
1104 return SECCLASS_DIR;
1105 case S_IFCHR:
1106 return SECCLASS_CHR_FILE;
1107 case S_IFIFO:
1108 return SECCLASS_FIFO_FILE;
1109
1110 }
1111
1112 return SECCLASS_FILE;
1113}
1114
James Morris13402582005-09-30 14:24:34 -04001115static inline int default_protocol_stream(int protocol)
1116{
Paolo Abeni95ca9072020-12-16 12:55:27 +01001117 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP ||
1118 protocol == IPPROTO_MPTCP);
James Morris13402582005-09-30 14:24:34 -04001119}
1120
1121static inline int default_protocol_dgram(int protocol)
1122{
1123 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1124}
1125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1127{
Christian Göttschea13479b2023-07-06 15:23:27 +02001128 bool extsockclass = selinux_policycap_extsockclass();
Stephen Smalleyda69a532017-01-09 10:07:30 -05001129
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 switch (family) {
1131 case PF_UNIX:
1132 switch (type) {
1133 case SOCK_STREAM:
1134 case SOCK_SEQPACKET:
1135 return SECCLASS_UNIX_STREAM_SOCKET;
1136 case SOCK_DGRAM:
Luis Ressel2a764b52017-07-25 15:13:41 -04001137 case SOCK_RAW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 return SECCLASS_UNIX_DGRAM_SOCKET;
1139 }
1140 break;
1141 case PF_INET:
1142 case PF_INET6:
1143 switch (type) {
1144 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001145 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001146 if (default_protocol_stream(protocol))
1147 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001148 else if (extsockclass && protocol == IPPROTO_SCTP)
1149 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001150 else
1151 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001153 if (default_protocol_dgram(protocol))
1154 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001155 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1156 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001157 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001158 else
1159 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001160 case SOCK_DCCP:
1161 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001162 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return SECCLASS_RAWIP_SOCKET;
1164 }
1165 break;
1166 case PF_NETLINK:
1167 switch (protocol) {
1168 case NETLINK_ROUTE:
1169 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001170 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1172 case NETLINK_NFLOG:
1173 return SECCLASS_NETLINK_NFLOG_SOCKET;
1174 case NETLINK_XFRM:
1175 return SECCLASS_NETLINK_XFRM_SOCKET;
1176 case NETLINK_SELINUX:
1177 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001178 case NETLINK_ISCSI:
1179 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 case NETLINK_AUDIT:
1181 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001182 case NETLINK_FIB_LOOKUP:
1183 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1184 case NETLINK_CONNECTOR:
1185 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1186 case NETLINK_NETFILTER:
1187 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 case NETLINK_DNRTMSG:
1189 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001190 case NETLINK_KOBJECT_UEVENT:
1191 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001192 case NETLINK_GENERIC:
1193 return SECCLASS_NETLINK_GENERIC_SOCKET;
1194 case NETLINK_SCSITRANSPORT:
1195 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1196 case NETLINK_RDMA:
1197 return SECCLASS_NETLINK_RDMA_SOCKET;
1198 case NETLINK_CRYPTO:
1199 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 default:
1201 return SECCLASS_NETLINK_SOCKET;
1202 }
1203 case PF_PACKET:
1204 return SECCLASS_PACKET_SOCKET;
1205 case PF_KEY:
1206 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001207 case PF_APPLETALK:
1208 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 }
1210
Stephen Smalleyda69a532017-01-09 10:07:30 -05001211 if (extsockclass) {
1212 switch (family) {
1213 case PF_AX25:
1214 return SECCLASS_AX25_SOCKET;
1215 case PF_IPX:
1216 return SECCLASS_IPX_SOCKET;
1217 case PF_NETROM:
1218 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001219 case PF_ATMPVC:
1220 return SECCLASS_ATMPVC_SOCKET;
1221 case PF_X25:
1222 return SECCLASS_X25_SOCKET;
1223 case PF_ROSE:
1224 return SECCLASS_ROSE_SOCKET;
1225 case PF_DECnet:
1226 return SECCLASS_DECNET_SOCKET;
1227 case PF_ATMSVC:
1228 return SECCLASS_ATMSVC_SOCKET;
1229 case PF_RDS:
1230 return SECCLASS_RDS_SOCKET;
1231 case PF_IRDA:
1232 return SECCLASS_IRDA_SOCKET;
1233 case PF_PPPOX:
1234 return SECCLASS_PPPOX_SOCKET;
1235 case PF_LLC:
1236 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001237 case PF_CAN:
1238 return SECCLASS_CAN_SOCKET;
1239 case PF_TIPC:
1240 return SECCLASS_TIPC_SOCKET;
1241 case PF_BLUETOOTH:
1242 return SECCLASS_BLUETOOTH_SOCKET;
1243 case PF_IUCV:
1244 return SECCLASS_IUCV_SOCKET;
1245 case PF_RXRPC:
1246 return SECCLASS_RXRPC_SOCKET;
1247 case PF_ISDN:
1248 return SECCLASS_ISDN_SOCKET;
1249 case PF_PHONET:
1250 return SECCLASS_PHONET_SOCKET;
1251 case PF_IEEE802154:
1252 return SECCLASS_IEEE802154_SOCKET;
1253 case PF_CAIF:
1254 return SECCLASS_CAIF_SOCKET;
1255 case PF_ALG:
1256 return SECCLASS_ALG_SOCKET;
1257 case PF_NFC:
1258 return SECCLASS_NFC_SOCKET;
1259 case PF_VSOCK:
1260 return SECCLASS_VSOCK_SOCKET;
1261 case PF_KCM:
1262 return SECCLASS_KCM_SOCKET;
1263 case PF_QIPCRTR:
1264 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001265 case PF_SMC:
1266 return SECCLASS_SMC_SOCKET;
Björn Töpel68e8b842018-05-02 13:01:22 +02001267 case PF_XDP:
1268 return SECCLASS_XDP_SOCKET;
Jeremy Kerrbc49d812021-07-29 10:20:39 +08001269 case PF_MCTP:
1270 return SECCLASS_MCTP_SOCKET;
1271#if PF_MAX > 46
Stephen Smalleyda69a532017-01-09 10:07:30 -05001272#error New address family defined, please update this function.
1273#endif
1274 }
1275 }
1276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return SECCLASS_SOCKET;
1278}
1279
Stephen Smalley134509d2015-06-04 16:22:17 -04001280static int selinux_genfs_get_sid(struct dentry *dentry,
1281 u16 tclass,
1282 u16 flags,
1283 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001285 int rc;
Al Virofc640052016-04-10 01:33:30 -04001286 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001287 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Eric Paris828dfe12008-04-17 13:17:49 -04001289 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 if (!buffer)
1291 return -ENOMEM;
1292
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001293 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1294 if (IS_ERR(path))
1295 rc = PTR_ERR(path);
1296 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001297 if (flags & SE_SBPROC) {
1298 /* each process gets a /proc/PID/ entry. Strip off the
1299 * PID part to get a valid selinux labeling.
1300 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1301 while (path[1] >= '0' && path[1] <= '9') {
1302 path[1] = '/';
1303 path++;
1304 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001305 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05001306 rc = security_genfs_sid(sb->s_type->name,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001307 path, tclass, sid);
Stephen Smalley7bb185e2018-09-04 16:51:36 -04001308 if (rc == -ENOENT) {
1309 /* No match in policy, mark as unlabeled. */
1310 *sid = SECINITSID_UNLABELED;
1311 rc = 0;
1312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 free_page((unsigned long)buffer);
1315 return rc;
1316}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001318static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
1319 u32 def_sid, u32 *sid)
1320{
1321#define INITCONTEXTLEN 255
1322 char *context;
1323 unsigned int len;
1324 int rc;
1325
1326 len = INITCONTEXTLEN;
1327 context = kmalloc(len + 1, GFP_NOFS);
1328 if (!context)
1329 return -ENOMEM;
1330
1331 context[len] = '\0';
1332 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1333 if (rc == -ERANGE) {
1334 kfree(context);
1335
1336 /* Need a larger buffer. Query for the right size. */
1337 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
1338 if (rc < 0)
1339 return rc;
1340
1341 len = rc;
1342 context = kmalloc(len + 1, GFP_NOFS);
1343 if (!context)
1344 return -ENOMEM;
1345
1346 context[len] = '\0';
1347 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
1348 context, len);
1349 }
1350 if (rc < 0) {
1351 kfree(context);
1352 if (rc != -ENODATA) {
1353 pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n",
1354 __func__, -rc, inode->i_sb->s_id, inode->i_ino);
1355 return rc;
1356 }
1357 *sid = def_sid;
1358 return 0;
1359 }
1360
Stephen Smalleye67b7982023-03-09 13:30:37 -05001361 rc = security_context_to_sid_default(context, rc, sid,
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001362 def_sid, GFP_NOFS);
1363 if (rc) {
1364 char *dev = inode->i_sb->s_id;
1365 unsigned long ino = inode->i_ino;
1366
1367 if (rc == -EINVAL) {
1368 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",
1369 ino, dev, context);
1370 } else {
1371 pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n",
1372 __func__, context, -rc, dev, ino);
1373 }
1374 }
1375 kfree(context);
1376 return 0;
1377}
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379/* The inode's security attributes must be initialized before first use. */
1380static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1381{
1382 struct superblock_security_struct *sbsec = NULL;
Casey Schaufler80788c22018-09-21 17:19:11 -07001383 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001384 u32 task_sid, sid = 0;
1385 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 struct dentry *dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001389 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001390 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001392 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001393 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001394 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001396 if (isec->sclass == SECCLASS_FILE)
1397 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1398
Casey Schaufler1aea7802021-04-22 17:41:15 +02001399 sbsec = selinux_superblock(inode->i_sb);
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001400 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 /* Defer initialization until selinux_complete_init,
1402 after the initial policy is loaded and the security
1403 server is ready to handle calls. */
1404 spin_lock(&sbsec->isec_lock);
1405 if (list_empty(&isec->list))
1406 list_add(&isec->list, &sbsec->isec_head);
1407 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001408 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 }
1410
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001411 sclass = isec->sclass;
1412 task_sid = isec->task_sid;
1413 sid = isec->sid;
1414 isec->initialized = LABEL_PENDING;
1415 spin_unlock(&isec->lock);
1416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 switch (sbsec->behavior) {
Ondrej Mosnacekcec5fe72023-05-29 16:05:27 +02001418 /*
1419 * In case of SECURITY_FS_USE_NATIVE we need to re-fetch the labels
1420 * via xattr when called from delayed_superblock_init().
1421 */
David Quigleyeb9ae682013-05-22 12:50:37 -04001422 case SECURITY_FS_USE_NATIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001424 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001425 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 break;
1427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 /* Need a dentry, since the xattr API requires one.
1429 Life would be simpler if we could just pass the inode. */
1430 if (opt_dentry) {
1431 /* Called from d_instantiate or d_splice_alias. */
1432 dentry = dget(opt_dentry);
1433 } else {
Al Virob1271252018-04-25 10:28:38 -04001434 /*
1435 * Called from selinux_complete_init, try to find a dentry.
1436 * Some filesystems really want a connected one, so try
1437 * that first. We could split SECURITY_FS_USE_XATTR in
1438 * two, depending upon that...
1439 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001441 if (!dentry)
1442 dentry = d_find_any_alias(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 }
1444 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001445 /*
1446 * this is can be hit on boot when a file is accessed
1447 * before the policy is loaded. When we load policy we
1448 * may find inodes that have no dentry on the
1449 * sbsec->isec_head list. No reason to complain as these
1450 * will get fixed up the next time we go through
1451 * inode_doinit with a dentry, before these inodes could
1452 * be used again by userspace.
1453 */
Paul Moore200ea5a2020-11-03 11:49:38 -05001454 goto out_invalid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 }
1456
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001457 rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
1458 &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 dput(dentry);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001460 if (rc)
1461 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 break;
1463 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001464 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 break;
1466 case SECURITY_FS_USE_TRANS:
1467 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001468 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
1470 /* Try to obtain a transition SID. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05001471 rc = security_transition_sid(task_sid, sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001472 sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001474 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001476 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001477 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001478 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001480 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001481 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Christian Göttsche7470d0d12020-01-28 20:16:48 +01001483 if ((sbsec->flags & SE_SBGENFS) &&
1484 (!S_ISLNK(inode->i_mode) ||
1485 selinux_policycap_genfs_seclabel_symlinks())) {
Paul Mooref64410e2014-03-19 16:46:18 -04001486 /* We must have a dentry to determine the label on
1487 * procfs inodes */
Al Virob1271252018-04-25 10:28:38 -04001488 if (opt_dentry) {
Paul Mooref64410e2014-03-19 16:46:18 -04001489 /* Called from d_instantiate or
1490 * d_splice_alias. */
1491 dentry = dget(opt_dentry);
Al Virob1271252018-04-25 10:28:38 -04001492 } else {
Paul Mooref64410e2014-03-19 16:46:18 -04001493 /* Called from selinux_complete_init, try to
Al Virob1271252018-04-25 10:28:38 -04001494 * find a dentry. Some filesystems really want
1495 * a connected one, so try that first.
1496 */
Paul Mooref64410e2014-03-19 16:46:18 -04001497 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001498 if (!dentry)
1499 dentry = d_find_any_alias(inode);
1500 }
Paul Mooref64410e2014-03-19 16:46:18 -04001501 /*
1502 * This can be hit on boot when a file is accessed
1503 * before the policy is loaded. When we load policy we
1504 * may find inodes that have no dentry on the
1505 * sbsec->isec_head list. No reason to complain as
1506 * these will get fixed up the next time we go through
1507 * inode_doinit() with a dentry, before these inodes
1508 * could be used again by userspace.
1509 */
1510 if (!dentry)
Paul Moore200ea5a2020-11-03 11:49:38 -05001511 goto out_invalid;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001512 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001513 sbsec->flags, &sid);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001514 if (rc) {
1515 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001516 goto out;
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001517 }
1518
1519 if ((sbsec->flags & SE_SBGENFS_XATTR) &&
1520 (inode->i_opflags & IOP_XATTR)) {
1521 rc = inode_doinit_use_xattr(inode, dentry,
1522 sid, &sid);
1523 if (rc) {
1524 dput(dentry);
1525 goto out;
1526 }
1527 }
1528 dput(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 }
1530 break;
1531 }
1532
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001533out:
1534 spin_lock(&isec->lock);
1535 if (isec->initialized == LABEL_PENDING) {
Paul Moore200ea5a2020-11-03 11:49:38 -05001536 if (rc) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001537 isec->initialized = LABEL_INVALID;
1538 goto out_unlock;
1539 }
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001540 isec->initialized = LABEL_INITIALIZED;
1541 isec->sid = sid;
1542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Eric Paris23970742006-09-25 23:32:01 -07001544out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001545 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 return rc;
Paul Moore200ea5a2020-11-03 11:49:38 -05001547
1548out_invalid:
1549 spin_lock(&isec->lock);
1550 if (isec->initialized == LABEL_PENDING) {
1551 isec->initialized = LABEL_INVALID;
1552 isec->sid = sid;
1553 }
1554 spin_unlock(&isec->lock);
1555 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556}
1557
1558/* Convert a Linux signal to an access vector. */
1559static inline u32 signal_to_av(int sig)
1560{
1561 u32 perm = 0;
1562
1563 switch (sig) {
1564 case SIGCHLD:
1565 /* Commonly granted from child to parent. */
1566 perm = PROCESS__SIGCHLD;
1567 break;
1568 case SIGKILL:
1569 /* Cannot be caught or ignored */
1570 perm = PROCESS__SIGKILL;
1571 break;
1572 case SIGSTOP:
1573 /* Cannot be caught or ignored */
1574 perm = PROCESS__SIGSTOP;
1575 break;
1576 default:
1577 /* All other signals. */
1578 perm = PROCESS__SIGNAL;
1579 break;
1580 }
1581
1582 return perm;
1583}
1584
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001585#if CAP_LAST_CAP > 63
1586#error Fix SELinux to handle capabilities > 63.
1587#endif
1588
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001590static int cred_has_capability(const struct cred *cred,
Micah Mortonc1a85a02019-01-07 16:10:53 -08001591 int cap, unsigned int opts, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
Thomas Liu2bf49692009-07-14 12:14:09 -04001593 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001594 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001595 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001596 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001597 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001598 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
Eric Paris50c205f2012-04-04 15:01:43 -04001600 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 ad.u.cap = cap;
1602
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001603 switch (CAP_TO_INDEX(cap)) {
1604 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001605 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001606 break;
1607 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001608 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001609 break;
1610 default:
peter enderborgc103a912018-06-12 10:09:03 +02001611 pr_err("SELinux: out of range capability %d\n", cap);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001612 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001613 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001614 }
Eric Paris06112162008-11-11 22:02:50 +11001615
Stephen Smalleye67b7982023-03-09 13:30:37 -05001616 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Micah Mortonc1a85a02019-01-07 16:10:53 -08001617 if (!(opts & CAP_OPT_NOAUDIT)) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05001618 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001619 if (rc2)
1620 return rc2;
1621 }
Eric Paris06112162008-11-11 22:02:50 +11001622 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623}
1624
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625/* Check whether a task has a particular permission to an inode.
1626 The 'adp' parameter is optional and allows other audit
1627 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001628static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 struct inode *inode,
1630 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001631 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001634 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
David Howellse0e81732009-09-02 09:13:40 +01001636 validate_creds(cred);
1637
Eric Paris828dfe12008-04-17 13:17:49 -04001638 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001639 return 0;
1640
David Howells88e67f32008-11-14 10:39:21 +11001641 sid = cred_sid(cred);
Casey Schaufler80788c22018-09-21 17:19:11 -07001642 isec = selinux_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Stephen Smalleye67b7982023-03-09 13:30:37 -05001644 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645}
1646
1647/* Same as inode_has_perm, but pass explicit audit data containing
1648 the dentry to help the auditing code to more easily generate the
1649 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001650static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 struct dentry *dentry,
1652 u32 av)
1653{
David Howellsc6f493d2015-03-17 22:26:22 +00001654 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001655 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001656
Eric Paris50c205f2012-04-04 15:01:43 -04001657 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001658 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001659 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001660 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001661}
1662
1663/* Same as inode_has_perm, but pass explicit audit data containing
1664 the path to help the auditing code to more easily generate the
1665 pathname if needed. */
1666static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001667 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001668 u32 av)
1669{
David Howellsc6f493d2015-03-17 22:26:22 +00001670 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001671 struct common_audit_data ad;
1672
Eric Paris50c205f2012-04-04 15:01:43 -04001673 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001674 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001675 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001676 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677}
1678
David Howells13f8e982013-06-13 23:37:55 +01001679/* Same as path_has_perm, but uses the inode from the file struct. */
1680static inline int file_path_has_perm(const struct cred *cred,
1681 struct file *file,
1682 u32 av)
1683{
1684 struct common_audit_data ad;
1685
Vivek Goyal43af5de2016-09-09 11:37:49 -04001686 ad.type = LSM_AUDIT_DATA_FILE;
1687 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001688 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001689}
1690
Chenbo Fengf66e4482017-10-18 13:00:26 -07001691#ifdef CONFIG_BPF_SYSCALL
1692static int bpf_fd_pass(struct file *file, u32 sid);
1693#endif
1694
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695/* Check whether a task can use an open file descriptor to
1696 access an inode in a given way. Check access to the
1697 descriptor itself, and then use dentry_has_perm to
1698 check a particular permission to the file.
1699 Access to the descriptor is implicitly granted if it
1700 has the same SID as the process. If av is zero, then
1701 access to the file is not checked, e.g. for cases
1702 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001703static int file_has_perm(const struct cred *cred,
1704 struct file *file,
1705 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07001707 struct file_security_struct *fsec = selinux_file(file);
Al Viro496ad9a2013-01-23 17:07:38 -05001708 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001709 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001710 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 int rc;
1712
Vivek Goyal43af5de2016-09-09 11:37:49 -04001713 ad.type = LSM_AUDIT_DATA_FILE;
1714 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
David Howells275bb412008-11-14 10:39:19 +11001716 if (sid != fsec->sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05001717 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 SECCLASS_FD,
1719 FD__USE,
1720 &ad);
1721 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001722 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 }
1724
Chenbo Fengf66e4482017-10-18 13:00:26 -07001725#ifdef CONFIG_BPF_SYSCALL
1726 rc = bpf_fd_pass(file, cred_sid(cred));
1727 if (rc)
1728 return rc;
1729#endif
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001732 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001734 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
David Howells88e67f32008-11-14 10:39:21 +11001736out:
1737 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738}
1739
David Howellsc3c188b2015-07-10 17:19:58 -04001740/*
1741 * Determine the label for an inode that might be unioned.
1742 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001743static int
1744selinux_determine_inode_label(const struct task_security_struct *tsec,
1745 struct inode *dir,
1746 const struct qstr *name, u16 tclass,
1747 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001748{
Casey Schaufler1aea7802021-04-22 17:41:15 +02001749 const struct superblock_security_struct *sbsec =
1750 selinux_superblock(dir->i_sb);
David Howellsc3c188b2015-07-10 17:19:58 -04001751
1752 if ((sbsec->flags & SE_SBINITIALIZED) &&
1753 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1754 *_new_isid = sbsec->mntpoint_sid;
1755 } else if ((sbsec->flags & SBLABEL_MNT) &&
1756 tsec->create_sid) {
1757 *_new_isid = tsec->create_sid;
1758 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001759 const struct inode_security_struct *dsec = inode_security(dir);
Stephen Smalleye67b7982023-03-09 13:30:37 -05001760 return security_transition_sid(tsec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001761 dsec->sid, tclass,
David Howellsc3c188b2015-07-10 17:19:58 -04001762 name, _new_isid);
1763 }
1764
1765 return 0;
1766}
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768/* Check whether a task can create a file. */
1769static int may_create(struct inode *dir,
1770 struct dentry *dentry,
1771 u16 tclass)
1772{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07001773 const struct task_security_struct *tsec = selinux_cred(current_cred());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 struct inode_security_struct *dsec;
1775 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001776 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001777 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 int rc;
1779
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001780 dsec = inode_security(dir);
Casey Schaufler1aea7802021-04-22 17:41:15 +02001781 sbsec = selinux_superblock(dir->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
David Howells275bb412008-11-14 10:39:19 +11001783 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001784
Eric Paris50c205f2012-04-04 15:01:43 -04001785 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001786 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Stephen Smalleye67b7982023-03-09 13:30:37 -05001788 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 DIR__ADD_NAME | DIR__SEARCH,
1790 &ad);
1791 if (rc)
1792 return rc;
1793
Yang Guo210a2922019-12-12 10:02:24 +08001794 rc = selinux_determine_inode_label(tsec, dir, &dentry->d_name, tclass,
1795 &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001796 if (rc)
1797 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Stephen Smalleye67b7982023-03-09 13:30:37 -05001799 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 if (rc)
1801 return rc;
1802
Stephen Smalleye67b7982023-03-09 13:30:37 -05001803 return avc_has_perm(newsid, sbsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 SECCLASS_FILESYSTEM,
1805 FILESYSTEM__ASSOCIATE, &ad);
1806}
1807
Eric Paris828dfe12008-04-17 13:17:49 -04001808#define MAY_LINK 0
1809#define MAY_UNLINK 1
1810#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
1812/* Check whether a task can link, unlink, or rmdir a file/directory. */
1813static int may_link(struct inode *dir,
1814 struct dentry *dentry,
1815 int kind)
1816
1817{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001819 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001820 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 u32 av;
1822 int rc;
1823
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001824 dsec = inode_security(dir);
1825 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Eric Paris50c205f2012-04-04 15:01:43 -04001827 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001828 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
1830 av = DIR__SEARCH;
1831 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
Stephen Smalleye67b7982023-03-09 13:30:37 -05001832 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 if (rc)
1834 return rc;
1835
1836 switch (kind) {
1837 case MAY_LINK:
1838 av = FILE__LINK;
1839 break;
1840 case MAY_UNLINK:
1841 av = FILE__UNLINK;
1842 break;
1843 case MAY_RMDIR:
1844 av = DIR__RMDIR;
1845 break;
1846 default:
peter enderborgc103a912018-06-12 10:09:03 +02001847 pr_warn("SELinux: %s: unrecognized kind %d\n",
Eric Paris744ba352008-04-17 11:52:44 -04001848 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 return 0;
1850 }
1851
Stephen Smalleye67b7982023-03-09 13:30:37 -05001852 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 return rc;
1854}
1855
1856static inline int may_rename(struct inode *old_dir,
1857 struct dentry *old_dentry,
1858 struct inode *new_dir,
1859 struct dentry *new_dentry)
1860{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001862 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001863 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 u32 av;
1865 int old_is_dir, new_is_dir;
1866 int rc;
1867
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001868 old_dsec = inode_security(old_dir);
1869 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001870 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001871 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Eric Paris50c205f2012-04-04 15:01:43 -04001873 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
Eric Parisa2694342011-04-25 13:10:27 -04001875 ad.u.dentry = old_dentry;
Stephen Smalleye67b7982023-03-09 13:30:37 -05001876 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1878 if (rc)
1879 return rc;
Stephen Smalleye67b7982023-03-09 13:30:37 -05001880 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 old_isec->sclass, FILE__RENAME, &ad);
1882 if (rc)
1883 return rc;
1884 if (old_is_dir && new_dir != old_dir) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05001885 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 old_isec->sclass, DIR__REPARENT, &ad);
1887 if (rc)
1888 return rc;
1889 }
1890
Eric Parisa2694342011-04-25 13:10:27 -04001891 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001893 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 av |= DIR__REMOVE_NAME;
Stephen Smalleye67b7982023-03-09 13:30:37 -05001895 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 if (rc)
1897 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001898 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001899 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001900 new_is_dir = d_is_dir(new_dentry);
Stephen Smalleye67b7982023-03-09 13:30:37 -05001901 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 new_isec->sclass,
1903 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1904 if (rc)
1905 return rc;
1906 }
1907
1908 return 0;
1909}
1910
1911/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001912static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 struct super_block *sb,
1914 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001915 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001918 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
Casey Schaufler1aea7802021-04-22 17:41:15 +02001920 sbsec = selinux_superblock(sb);
Stephen Smalleye67b7982023-03-09 13:30:37 -05001921 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922}
1923
1924/* Convert a Linux mode and permission mask to an access vector. */
1925static inline u32 file_mask_to_av(int mode, int mask)
1926{
1927 u32 av = 0;
1928
Al Virodba19c62011-07-25 20:49:29 -04001929 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (mask & MAY_EXEC)
1931 av |= FILE__EXECUTE;
1932 if (mask & MAY_READ)
1933 av |= FILE__READ;
1934
1935 if (mask & MAY_APPEND)
1936 av |= FILE__APPEND;
1937 else if (mask & MAY_WRITE)
1938 av |= FILE__WRITE;
1939
1940 } else {
1941 if (mask & MAY_EXEC)
1942 av |= DIR__SEARCH;
1943 if (mask & MAY_WRITE)
1944 av |= DIR__WRITE;
1945 if (mask & MAY_READ)
1946 av |= DIR__READ;
1947 }
1948
1949 return av;
1950}
1951
1952/* Convert a Linux file to an access vector. */
1953static inline u32 file_to_av(struct file *file)
1954{
1955 u32 av = 0;
1956
1957 if (file->f_mode & FMODE_READ)
1958 av |= FILE__READ;
1959 if (file->f_mode & FMODE_WRITE) {
1960 if (file->f_flags & O_APPEND)
1961 av |= FILE__APPEND;
1962 else
1963 av |= FILE__WRITE;
1964 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001965 if (!av) {
1966 /*
1967 * Special file opened with flags 3 for ioctl-only use.
1968 */
1969 av = FILE__IOCTL;
1970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
1972 return av;
1973}
1974
Eric Paris8b6a5a32008-10-29 17:06:46 -04001975/*
Randy Dunlapc76a2f92020-08-07 09:51:34 -07001976 * Convert a file to an access vector and include the correct
Eric Paris8b6a5a32008-10-29 17:06:46 -04001977 * open permission.
1978 */
1979static inline u32 open_file_to_av(struct file *file)
1980{
1981 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04001982 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04001983
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001984 if (selinux_policycap_openperm() &&
1985 inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04001986 av |= FILE__OPEN;
1987
Eric Paris8b6a5a32008-10-29 17:06:46 -04001988 return av;
1989}
1990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991/* Hook functions begin here. */
1992
Todd Kjos52f88692021-10-12 09:56:13 -07001993static int selinux_binder_set_context_mgr(const struct cred *mgr)
Stephen Smalley79af7302015-01-21 10:54:10 -05001994{
Stephen Smalleye67b7982023-03-09 13:30:37 -05001995 return avc_has_perm(current_sid(), cred_sid(mgr), SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05001996 BINDER__SET_CONTEXT_MGR, NULL);
1997}
1998
Todd Kjos52f88692021-10-12 09:56:13 -07001999static int selinux_binder_transaction(const struct cred *from,
2000 const struct cred *to)
Stephen Smalley79af7302015-01-21 10:54:10 -05002001{
2002 u32 mysid = current_sid();
Todd Kjos52f88692021-10-12 09:56:13 -07002003 u32 fromsid = cred_sid(from);
2004 u32 tosid = cred_sid(to);
Stephen Smalley79af7302015-01-21 10:54:10 -05002005 int rc;
2006
2007 if (mysid != fromsid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002008 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002009 BINDER__IMPERSONATE, NULL);
2010 if (rc)
2011 return rc;
2012 }
2013
Stephen Smalleye67b7982023-03-09 13:30:37 -05002014 return avc_has_perm(fromsid, tosid,
Paul Mooreeb1231f2021-02-18 15:13:40 -05002015 SECCLASS_BINDER, BINDER__CALL, NULL);
Stephen Smalley79af7302015-01-21 10:54:10 -05002016}
2017
Todd Kjos52f88692021-10-12 09:56:13 -07002018static int selinux_binder_transfer_binder(const struct cred *from,
2019 const struct cred *to)
Stephen Smalley79af7302015-01-21 10:54:10 -05002020{
Stephen Smalleye67b7982023-03-09 13:30:37 -05002021 return avc_has_perm(cred_sid(from), cred_sid(to),
Paul Mooreeb1231f2021-02-18 15:13:40 -05002022 SECCLASS_BINDER, BINDER__TRANSFER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002023 NULL);
2024}
2025
Todd Kjos52f88692021-10-12 09:56:13 -07002026static int selinux_binder_transfer_file(const struct cred *from,
2027 const struct cred *to,
Stephen Smalley79af7302015-01-21 10:54:10 -05002028 struct file *file)
2029{
Todd Kjos52f88692021-10-12 09:56:13 -07002030 u32 sid = cred_sid(to);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07002031 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002032 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002033 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002034 struct common_audit_data ad;
2035 int rc;
2036
2037 ad.type = LSM_AUDIT_DATA_PATH;
2038 ad.u.path = file->f_path;
2039
2040 if (sid != fsec->sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002041 rc = avc_has_perm(sid, fsec->sid,
Stephen Smalley79af7302015-01-21 10:54:10 -05002042 SECCLASS_FD,
2043 FD__USE,
2044 &ad);
2045 if (rc)
2046 return rc;
2047 }
2048
Chenbo Fengf66e4482017-10-18 13:00:26 -07002049#ifdef CONFIG_BPF_SYSCALL
2050 rc = bpf_fd_pass(file, sid);
2051 if (rc)
2052 return rc;
2053#endif
2054
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002055 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002056 return 0;
2057
Paul Moore20cdef82016-04-04 14:14:42 -04002058 isec = backing_inode_security(dentry);
Stephen Smalleye67b7982023-03-09 13:30:37 -05002059 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
Stephen Smalley79af7302015-01-21 10:54:10 -05002060 &ad);
2061}
2062
Ingo Molnar9e488582009-05-07 19:26:19 +10002063static int selinux_ptrace_access_check(struct task_struct *child,
Paul Mooreeb1231f2021-02-18 15:13:40 -05002064 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002066 u32 sid = current_sid();
Paul Mooreeb1231f2021-02-18 15:13:40 -05002067 u32 csid = task_sid_obj(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002068
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002069 if (mode & PTRACE_MODE_READ)
Stephen Smalleye67b7982023-03-09 13:30:37 -05002070 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ,
2071 NULL);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002072
Stephen Smalleye67b7982023-03-09 13:30:37 -05002073 return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE,
2074 NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002075}
2076
2077static int selinux_ptrace_traceme(struct task_struct *parent)
2078{
Stephen Smalleye67b7982023-03-09 13:30:37 -05002079 return avc_has_perm(task_sid_obj(parent), task_sid_obj(current),
Paul Mooreeb1231f2021-02-18 15:13:40 -05002080 SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081}
2082
2083static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002084 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085{
Stephen Smalleye67b7982023-03-09 13:30:37 -05002086 return avc_has_perm(current_sid(), task_sid_obj(target),
2087 SECCLASS_PROCESS, PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
David Howellsd84f4f92008-11-14 10:39:23 +11002090static int selinux_capset(struct cred *new, const struct cred *old,
2091 const kernel_cap_t *effective,
2092 const kernel_cap_t *inheritable,
2093 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094{
Stephen Smalleye67b7982023-03-09 13:30:37 -05002095 return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002096 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097}
2098
James Morris5626d3e2009-01-30 10:05:06 +11002099/*
2100 * (This comment used to live with the selinux_task_setuid hook,
2101 * which was removed).
2102 *
2103 * Since setuid only affects the current process, and since the SELinux
2104 * controls are not based on the Linux identity attributes, SELinux does not
2105 * need to control this operation. However, SELinux does control the use of
2106 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2107 */
2108
Eric Paris6a9de492012-01-03 12:25:14 -05002109static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002110 int cap, unsigned int opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111{
Micah Mortonc1a85a02019-01-07 16:10:53 -08002112 return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113}
2114
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2116{
David Howells88e67f32008-11-14 10:39:21 +11002117 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 int rc = 0;
2119
2120 if (!sb)
2121 return 0;
2122
2123 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002124 case Q_SYNC:
2125 case Q_QUOTAON:
2126 case Q_QUOTAOFF:
2127 case Q_SETINFO:
2128 case Q_SETQUOTA:
Richard Hainese4cfa052020-02-20 15:32:34 +00002129 case Q_XQUOTAOFF:
2130 case Q_XQUOTAON:
2131 case Q_XSETQLIM:
David Howells88e67f32008-11-14 10:39:21 +11002132 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002133 break;
2134 case Q_GETFMT:
2135 case Q_GETINFO:
2136 case Q_GETQUOTA:
Richard Hainese4cfa052020-02-20 15:32:34 +00002137 case Q_XGETQUOTA:
2138 case Q_XGETQSTAT:
2139 case Q_XGETQSTATV:
2140 case Q_XGETNEXTQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002141 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002142 break;
2143 default:
2144 rc = 0; /* let the kernel handle invalid cmds */
2145 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 }
2147 return rc;
2148}
2149
2150static int selinux_quota_on(struct dentry *dentry)
2151{
David Howells88e67f32008-11-14 10:39:21 +11002152 const struct cred *cred = current_cred();
2153
Eric Paris2875fa02011-04-28 16:04:24 -04002154 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155}
2156
Eric Paris12b30522010-11-15 18:36:29 -05002157static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002160 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2161 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002162 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002163 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002164 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2165 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2166 /* Set level of messages printed to console */
2167 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalleye67b7982023-03-09 13:30:37 -05002168 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002169 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2170 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002172 /* All other syslog types */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002173 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002174 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175}
2176
2177/*
2178 * Check that a process has enough memory to allocate a new virtual
2179 * mapping. 0 means there is enough memory for the allocation to
2180 * succeed and -ENOMEM implies there is not.
2181 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 * Do not audit the selinux permission check, as this is applied to all
2183 * processes that allocate mappings.
2184 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002185static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
2187 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002189 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002190 CAP_OPT_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 if (rc == 0)
2192 cap_sys_admin = 1;
2193
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002194 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195}
2196
2197/* binprm security operations */
2198
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002199static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002200{
2201 u32 sid = 0;
2202 struct task_struct *tracer;
2203
2204 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002205 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002206 if (tracer)
Paul Mooreeb1231f2021-02-18 15:13:40 -05002207 sid = task_sid_obj(tracer);
Paul Moore0c6181c2016-03-30 21:41:21 -04002208 rcu_read_unlock();
2209
2210 return sid;
2211}
2212
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002213static int check_nnp_nosuid(const struct linux_binprm *bprm,
2214 const struct task_security_struct *old_tsec,
2215 const struct task_security_struct *new_tsec)
2216{
2217 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002218 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002219 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002220 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002221
2222 if (!nnp && !nosuid)
2223 return 0; /* neither NNP nor nosuid */
2224
2225 if (new_tsec->sid == old_tsec->sid)
2226 return 0; /* No change in credentials */
2227
2228 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002229 * If the policy enables the nnp_nosuid_transition policy capability,
2230 * then we permit transitions under NNP or nosuid if the
2231 * policy allows the corresponding permission between
2232 * the old and new contexts.
2233 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002234 if (selinux_policycap_nnp_nosuid_transition()) {
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002235 av = 0;
2236 if (nnp)
2237 av |= PROCESS2__NNP_TRANSITION;
2238 if (nosuid)
2239 av |= PROCESS2__NOSUID_TRANSITION;
Stephen Smalleye67b7982023-03-09 13:30:37 -05002240 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002241 SECCLASS_PROCESS2, av, NULL);
2242 if (!rc)
2243 return 0;
2244 }
2245
2246 /*
2247 * We also permit NNP or nosuid transitions to bounded SIDs,
2248 * i.e. SIDs that are guaranteed to only be allowed a subset
2249 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002250 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002251 rc = security_bounded_transition(old_tsec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002252 new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002253 if (!rc)
2254 return 0;
2255
2256 /*
2257 * On failure, preserve the errno values for NNP vs nosuid.
2258 * NNP: Operation not permitted for caller.
2259 * nosuid: Permission denied to file.
2260 */
2261 if (nnp)
2262 return -EPERM;
2263 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002264}
2265
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05002266static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267{
David Howellsa6f76f22008-11-14 10:39:24 +11002268 const struct task_security_struct *old_tsec;
2269 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002271 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002272 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 int rc;
2274
David Howellsa6f76f22008-11-14 10:39:24 +11002275 /* SELinux context only depends on initial program or script and not
2276 * the script interpreter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002278 old_tsec = selinux_cred(current_cred());
2279 new_tsec = selinux_cred(bprm->cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002280 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
2282 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002283 new_tsec->sid = old_tsec->sid;
2284 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Michael LeMay28eba5b2006-06-27 02:53:42 -07002286 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002287 new_tsec->create_sid = 0;
2288 new_tsec->keycreate_sid = 0;
2289 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Ondrej Mosnacek5b0eea82023-06-20 15:12:22 +02002291 /*
2292 * Before policy is loaded, label any task outside kernel space
2293 * as SECINITSID_INIT, so that any userspace tasks surviving from
2294 * early boot end up with a label different from SECINITSID_KERNEL
2295 * (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL).
2296 */
2297 if (!selinux_initialized()) {
2298 new_tsec->sid = SECINITSID_INIT;
2299 /* also clear the exec_sid just in case */
2300 new_tsec->exec_sid = 0;
2301 return 0;
2302 }
2303
David Howellsa6f76f22008-11-14 10:39:24 +11002304 if (old_tsec->exec_sid) {
2305 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002307 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002308
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002309 /* Fail on NNP or nosuid if not an allowed transition. */
2310 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2311 if (rc)
2312 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 } else {
2314 /* Check for a default transition on this program. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002315 rc = security_transition_sid(old_tsec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002316 isec->sid, SECCLASS_PROCESS, NULL,
Eric Paris652bb9b2011-02-01 11:05:40 -05002317 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 if (rc)
2319 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002320
2321 /*
2322 * Fallback to old SID on NNP or nosuid if not an allowed
2323 * transition.
2324 */
2325 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2326 if (rc)
2327 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
2329
Vivek Goyal43af5de2016-09-09 11:37:49 -04002330 ad.type = LSM_AUDIT_DATA_FILE;
2331 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
David Howellsa6f76f22008-11-14 10:39:24 +11002333 if (new_tsec->sid == old_tsec->sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002334 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2336 if (rc)
2337 return rc;
2338 } else {
2339 /* Check permissions for the transition. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002340 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2342 if (rc)
2343 return rc;
2344
Stephen Smalleye67b7982023-03-09 13:30:37 -05002345 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2347 if (rc)
2348 return rc;
2349
David Howellsa6f76f22008-11-14 10:39:24 +11002350 /* Check for shared state */
2351 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002352 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002353 SECCLASS_PROCESS, PROCESS__SHARE,
2354 NULL);
2355 if (rc)
2356 return -EPERM;
2357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
David Howellsa6f76f22008-11-14 10:39:24 +11002359 /* Make sure that anyone attempting to ptrace over a task that
2360 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002361 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002362 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002363 if (ptsid != 0) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002364 rc = avc_has_perm(ptsid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002365 SECCLASS_PROCESS,
2366 PROCESS__PTRACE, NULL);
2367 if (rc)
2368 return -EPERM;
2369 }
2370 }
2371
2372 /* Clear any possibly unsafe personality bits on exec: */
2373 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 /* Enable secure mode for SIDs transitions unless
2376 the noatsecure permission is granted between
2377 the two SIDs, i.e. ahp returns 0. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002378 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Kees Cook62874c32017-07-18 15:25:25 -07002379 SECCLASS_PROCESS, PROCESS__NOATSECURE,
2380 NULL);
2381 bprm->secureexec |= !!rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 }
2383
Kees Cook62874c32017-07-18 15:25:25 -07002384 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385}
2386
Al Viroc3c073f2012-08-21 22:32:06 -04002387static int match_file(const void *p, struct file *file, unsigned fd)
2388{
2389 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2390}
2391
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002393static inline void flush_unauthorized_files(const struct cred *cred,
2394 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002397 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002398 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002399 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002401 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002403 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002404 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002405 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002406
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002408 Use file_path_has_perm on the tty path directly
2409 rather than using file_has_perm, as this particular
2410 open file may belong to another process and we are
2411 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002412 file_priv = list_first_entry(&tty->tty_files,
2413 struct tty_file_private, list);
2414 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002415 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002416 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 }
Peter Hurley4a510962016-01-09 21:35:23 -08002418 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002419 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002421 /* Reset controlling tty. */
2422 if (drop_tty)
2423 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
2425 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002426 n = iterate_fd(files, 0, match_file, cred);
2427 if (!n) /* none found? */
2428 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
Al Viroc3c073f2012-08-21 22:32:06 -04002430 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002431 if (IS_ERR(devnull))
2432 devnull = NULL;
2433 /* replace all the matching ones with this */
2434 do {
2435 replace_fd(n - 1, devnull, 0);
2436 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2437 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002438 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439}
2440
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441/*
David Howellsa6f76f22008-11-14 10:39:24 +11002442 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 */
David Howellsa6f76f22008-11-14 10:39:24 +11002444static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445{
David Howellsa6f76f22008-11-14 10:39:24 +11002446 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 int rc, i;
2449
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002450 new_tsec = selinux_cred(bprm->cred);
David Howellsa6f76f22008-11-14 10:39:24 +11002451 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 return;
2453
2454 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002455 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
David Howellsa6f76f22008-11-14 10:39:24 +11002457 /* Always clear parent death signal on SID transitions. */
2458 current->pdeath_signal = 0;
2459
2460 /* Check whether the new SID can inherit resource limits from the old
2461 * SID. If not, reset all soft limits to the lower of the current
2462 * task's hard limit and the init task's soft limit.
2463 *
2464 * Note that the setting of hard limits (even to lower them) can be
2465 * controlled by the setrlimit check. The inclusion of the init task's
2466 * soft limit into the computation is to avoid resetting soft limits
2467 * higher than the default soft limit for cases where the default is
2468 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2469 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002470 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
David Howellsa6f76f22008-11-14 10:39:24 +11002471 PROCESS__RLIMITINH, NULL);
2472 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002473 /* protect against do_prlimit() */
2474 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002475 for (i = 0; i < RLIM_NLIMITS; i++) {
2476 rlim = current->signal->rlim + i;
2477 initrlim = init_task.signal->rlim + i;
2478 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2479 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002480 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002481 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2482 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002483 }
2484}
2485
2486/*
2487 * Clean up the process immediately after the installation of new credentials
2488 * due to exec
2489 */
2490static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2491{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002492 const struct task_security_struct *tsec = selinux_cred(current_cred());
David Howellsa6f76f22008-11-14 10:39:24 +11002493 u32 osid, sid;
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002494 int rc;
David Howellsa6f76f22008-11-14 10:39:24 +11002495
David Howellsa6f76f22008-11-14 10:39:24 +11002496 osid = tsec->osid;
2497 sid = tsec->sid;
2498
2499 if (sid == osid)
2500 return;
2501
2502 /* Check whether the new SID can inherit signal state from the old SID.
2503 * If not, clear itimers to avoid subsequent signal generation and
2504 * flush and unblock signals.
2505 *
2506 * This must occur _after_ the task SID has been updated so that any
2507 * kill done after the flush will be checked against the new SID.
2508 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05002509 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 if (rc) {
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002511 clear_itimer();
2512
Paul Moore0e326df2022-01-27 10:56:13 -05002513 spin_lock_irq(&unrcu_pointer(current->sighand)->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002514 if (!fatal_signal_pending(current)) {
2515 flush_sigqueue(&current->pending);
2516 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002517 flush_signal_handlers(current, 1);
2518 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002519 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002520 }
Paul Moore0e326df2022-01-27 10:56:13 -05002521 spin_unlock_irq(&unrcu_pointer(current->sighand)->siglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 }
2523
David Howellsa6f76f22008-11-14 10:39:24 +11002524 /* Wake up the parent if it is waiting so that it can recheck
2525 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002526 read_lock(&tasklist_lock);
Paul Moore0e326df2022-01-27 10:56:13 -05002527 __wake_up_parent(current, unrcu_pointer(current->real_parent));
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002528 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529}
2530
2531/* superblock security operations */
2532
2533static int selinux_sb_alloc_security(struct super_block *sb)
2534{
Casey Schaufler1aea7802021-04-22 17:41:15 +02002535 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Paul Moorecb89e242020-01-10 16:32:10 -05002536
2537 mutex_init(&sbsec->lock);
2538 INIT_LIST_HEAD(&sbsec->isec_head);
2539 spin_lock_init(&sbsec->isec_lock);
Paul Moorecb89e242020-01-10 16:32:10 -05002540 sbsec->sid = SECINITSID_UNLABELED;
2541 sbsec->def_sid = SECINITSID_FILE;
2542 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Paul Moorecb89e242020-01-10 16:32:10 -05002543
2544 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545}
2546
Al Viro99dbbb52018-12-14 21:56:23 -05002547static inline int opt_len(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548{
Al Viro99dbbb52018-12-14 21:56:23 -05002549 bool open_quote = false;
2550 int len;
2551 char c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
Al Viro99dbbb52018-12-14 21:56:23 -05002553 for (len = 0; (c = s[len]) != '\0'; len++) {
2554 if (c == '"')
Cory Olmo3528a952006-09-29 01:58:44 -07002555 open_quote = !open_quote;
Al Viro99dbbb52018-12-14 21:56:23 -05002556 if (c == ',' && !open_quote)
2557 break;
2558 }
2559 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560}
2561
Al Viro204cc0c2018-12-13 13:41:47 -05002562static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002563{
Al Viro99dbbb52018-12-14 21:56:23 -05002564 char *from = options;
2565 char *to = options;
2566 bool first = true;
Gen Zhangfec63752019-06-12 21:55:38 +08002567 int rc;
Al Viro5b400232018-12-12 20:13:29 -05002568
Al Viro99dbbb52018-12-14 21:56:23 -05002569 while (1) {
2570 int len = opt_len(from);
Gen Zhangfec63752019-06-12 21:55:38 +08002571 int token;
Al Viro99dbbb52018-12-14 21:56:23 -05002572 char *arg = NULL;
2573
2574 token = match_opt_prefix(from, len, &arg);
2575
2576 if (token != Opt_error) {
2577 char *p, *q;
2578
2579 /* strip quotes */
2580 if (arg) {
2581 for (p = q = arg; p < from + len; p++) {
2582 char c = *p;
2583 if (c != '"')
2584 *q++ = c;
2585 }
2586 arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
Gen Zhangfec63752019-06-12 21:55:38 +08002587 if (!arg) {
2588 rc = -ENOMEM;
2589 goto free_opt;
2590 }
Al Viro99dbbb52018-12-14 21:56:23 -05002591 }
2592 rc = selinux_add_opt(token, arg, mnt_opts);
Christian Göttschecad140d2022-06-15 17:38:39 +02002593 kfree(arg);
2594 arg = NULL;
Al Viro99dbbb52018-12-14 21:56:23 -05002595 if (unlikely(rc)) {
Gen Zhangfec63752019-06-12 21:55:38 +08002596 goto free_opt;
Al Viro99dbbb52018-12-14 21:56:23 -05002597 }
2598 } else {
2599 if (!first) { // copy with preceding comma
2600 from--;
2601 len++;
2602 }
2603 if (to != from)
2604 memmove(to, from, len);
2605 to += len;
2606 first = false;
2607 }
2608 if (!from[len])
2609 break;
2610 from += len + 1;
2611 }
2612 *to = '\0';
2613 return 0;
Gen Zhangfec63752019-06-12 21:55:38 +08002614
2615free_opt:
2616 if (*mnt_opts) {
2617 selinux_free_mnt_opts(*mnt_opts);
2618 *mnt_opts = NULL;
2619 }
2620 return rc;
Al Viro5b400232018-12-12 20:13:29 -05002621}
2622
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002623static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
2624{
2625 struct selinux_mnt_opts *opts = mnt_opts;
GONG, Ruiqi0266c252022-01-25 15:11:33 +08002626 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002627
2628 /*
2629 * Superblock not initialized (i.e. no options) - reject if any
2630 * options specified, otherwise accept.
2631 */
2632 if (!(sbsec->flags & SE_SBINITIALIZED))
2633 return opts ? 1 : 0;
2634
2635 /*
2636 * Superblock initialized and no options specified - reject if
2637 * superblock has any options set, otherwise accept.
2638 */
2639 if (!opts)
2640 return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
2641
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002642 if (opts->fscontext_sid) {
2643 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
2644 opts->fscontext_sid))
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002645 return 1;
2646 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002647 if (opts->context_sid) {
2648 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
2649 opts->context_sid))
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002650 return 1;
2651 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002652 if (opts->rootcontext_sid) {
2653 struct inode_security_struct *root_isec;
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002654
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002655 root_isec = backing_inode_security(sb->s_root);
2656 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
2657 opts->rootcontext_sid))
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002658 return 1;
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002659 }
2660 if (opts->defcontext_sid) {
2661 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
2662 opts->defcontext_sid))
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05002663 return 1;
2664 }
2665 return 0;
2666}
2667
Al Viro204cc0c2018-12-13 13:41:47 -05002668static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002669{
Al Virobd323652018-12-13 15:04:59 -05002670 struct selinux_mnt_opts *opts = mnt_opts;
Casey Schaufler1aea7802021-04-22 17:41:15 +02002671 struct superblock_security_struct *sbsec = selinux_superblock(sb);
Eric Paris026eb162011-03-03 16:09:14 -05002672
2673 if (!(sbsec->flags & SE_SBINITIALIZED))
2674 return 0;
2675
Al Viro204cc0c2018-12-13 13:41:47 -05002676 if (!opts)
Eric Paris026eb162011-03-03 16:09:14 -05002677 return 0;
2678
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002679 if (opts->fscontext_sid) {
Scott Mayhew6bc19682022-01-31 13:57:37 -05002680 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
2681 opts->fscontext_sid))
Al Virobd323652018-12-13 15:04:59 -05002682 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002683 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002684 if (opts->context_sid) {
Scott Mayhew6bc19682022-01-31 13:57:37 -05002685 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
2686 opts->context_sid))
Al Virobd323652018-12-13 15:04:59 -05002687 goto out_bad_option;
2688 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002689 if (opts->rootcontext_sid) {
Al Virobd323652018-12-13 15:04:59 -05002690 struct inode_security_struct *root_isec;
2691 root_isec = backing_inode_security(sb->s_root);
Scott Mayhew6bc19682022-01-31 13:57:37 -05002692 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
2693 opts->rootcontext_sid))
Al Virobd323652018-12-13 15:04:59 -05002694 goto out_bad_option;
2695 }
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002696 if (opts->defcontext_sid) {
Scott Mayhew6bc19682022-01-31 13:57:37 -05002697 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
2698 opts->defcontext_sid))
Al Virobd323652018-12-13 15:04:59 -05002699 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002700 }
Al Viroc039bc32018-12-01 23:06:57 -05002701 return 0;
Eric Paris026eb162011-03-03 16:09:14 -05002702
Eric Paris026eb162011-03-03 16:09:14 -05002703out_bad_option:
peter enderborgc103a912018-06-12 10:09:03 +02002704 pr_warn("SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002705 "during remount (dev %s, type=%s)\n", sb->s_id,
2706 sb->s_type->name);
Al Viroc039bc32018-12-01 23:06:57 -05002707 return -EINVAL;
Eric Paris026eb162011-03-03 16:09:14 -05002708}
2709
Al Viroa10d7c22018-12-05 11:58:35 -05002710static int selinux_sb_kern_mount(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711{
David Howells88e67f32008-11-14 10:39:21 +11002712 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002713 struct common_audit_data ad;
James Morris74192242008-12-19 11:41:10 +11002714
Eric Paris50c205f2012-04-04 15:01:43 -04002715 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002716 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002717 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718}
2719
David Howells726c3342006-06-23 02:02:58 -07002720static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721{
David Howells88e67f32008-11-14 10:39:21 +11002722 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002723 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Eric Paris50c205f2012-04-04 15:01:43 -04002725 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002726 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002727 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728}
2729
Al Viro808d4e32012-10-11 11:42:01 -04002730static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002731 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002732 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002733 unsigned long flags,
2734 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735{
David Howells88e67f32008-11-14 10:39:21 +11002736 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002739 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002740 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 else
Eric Paris2875fa02011-04-28 16:04:24 -04002742 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743}
2744
Stephen Smalley98aa003452020-01-17 15:24:07 -05002745static int selinux_move_mount(const struct path *from_path,
2746 const struct path *to_path)
2747{
2748 const struct cred *cred = current_cred();
2749
2750 return path_has_perm(cred, to_path, FILE__MOUNTON);
2751}
2752
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753static int selinux_umount(struct vfsmount *mnt, int flags)
2754{
David Howells88e67f32008-11-14 10:39:21 +11002755 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756
David Howells88e67f32008-11-14 10:39:21 +11002757 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002758 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759}
2760
Al Viro0b520752018-12-23 16:02:47 -05002761static int selinux_fs_context_dup(struct fs_context *fc,
2762 struct fs_context *src_fc)
2763{
2764 const struct selinux_mnt_opts *src = src_fc->security;
Al Viro0b520752018-12-23 16:02:47 -05002765
2766 if (!src)
2767 return 0;
2768
Ondrej Mosnacek70f41692022-02-02 13:55:29 +01002769 fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
2770 return fc->security ? 0 : -ENOMEM;
Al Viro0b520752018-12-23 16:02:47 -05002771}
2772
Al Virod7167b12019-09-07 07:23:15 -04002773static const struct fs_parameter_spec selinux_fs_parameters[] = {
David Howells442155c2018-11-01 23:07:24 +00002774 fsparam_string(CONTEXT_STR, Opt_context),
2775 fsparam_string(DEFCONTEXT_STR, Opt_defcontext),
2776 fsparam_string(FSCONTEXT_STR, Opt_fscontext),
2777 fsparam_string(ROOTCONTEXT_STR, Opt_rootcontext),
2778 fsparam_flag (SECLABEL_STR, Opt_seclabel),
2779 {}
2780};
2781
David Howells442155c2018-11-01 23:07:24 +00002782static int selinux_fs_context_parse_param(struct fs_context *fc,
2783 struct fs_parameter *param)
2784{
2785 struct fs_parse_result result;
Christian Göttschecad140d2022-06-15 17:38:39 +02002786 int opt;
David Howells442155c2018-11-01 23:07:24 +00002787
Al Virod7167b12019-09-07 07:23:15 -04002788 opt = fs_parse(fc, selinux_fs_parameters, param, &result);
David Howells442155c2018-11-01 23:07:24 +00002789 if (opt < 0)
2790 return opt;
2791
Christian Göttschecad140d2022-06-15 17:38:39 +02002792 return selinux_add_opt(opt, param->string, &fc->security);
David Howells442155c2018-11-01 23:07:24 +00002793}
2794
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795/* inode security operations */
2796
2797static int selinux_inode_alloc_security(struct inode *inode)
2798{
Paul Moorecb89e242020-01-10 16:32:10 -05002799 struct inode_security_struct *isec = selinux_inode(inode);
2800 u32 sid = current_sid();
2801
2802 spin_lock_init(&isec->lock);
2803 INIT_LIST_HEAD(&isec->list);
2804 isec->inode = inode;
2805 isec->sid = SECINITSID_UNLABELED;
2806 isec->sclass = SECCLASS_FILE;
2807 isec->task_sid = sid;
2808 isec->initialized = LABEL_INVALID;
2809
2810 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811}
2812
2813static void selinux_inode_free_security(struct inode *inode)
2814{
2815 inode_free_security(inode);
2816}
2817
David Quigleyd47be3d2013-05-22 12:50:34 -04002818static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Vivek Goyal15bf3232021-10-12 09:23:07 -04002819 const struct qstr *name,
2820 const char **xattr_name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002821 u32 *ctxlen)
2822{
David Quigleyd47be3d2013-05-22 12:50:34 -04002823 u32 newsid;
2824 int rc;
2825
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002826 rc = selinux_determine_inode_label(selinux_cred(current_cred()),
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002827 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002828 inode_mode_to_security_class(mode),
2829 &newsid);
2830 if (rc)
2831 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002832
Vivek Goyal15bf3232021-10-12 09:23:07 -04002833 if (xattr_name)
2834 *xattr_name = XATTR_NAME_SELINUX;
2835
Stephen Smalleye67b7982023-03-09 13:30:37 -05002836 return security_sid_to_context(newsid, (char **)ctx,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002837 ctxlen);
David Quigleyd47be3d2013-05-22 12:50:34 -04002838}
2839
Vivek Goyala518b0a2016-07-13 10:44:53 -04002840static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2841 struct qstr *name,
2842 const struct cred *old,
2843 struct cred *new)
2844{
2845 u32 newsid;
2846 int rc;
2847 struct task_security_struct *tsec;
2848
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002849 rc = selinux_determine_inode_label(selinux_cred(old),
Vivek Goyala518b0a2016-07-13 10:44:53 -04002850 d_inode(dentry->d_parent), name,
2851 inode_mode_to_security_class(mode),
2852 &newsid);
2853 if (rc)
2854 return rc;
2855
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002856 tsec = selinux_cred(new);
Vivek Goyala518b0a2016-07-13 10:44:53 -04002857 tsec->create_sid = newsid;
2858 return 0;
2859}
2860
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002861static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002862 const struct qstr *qstr,
2863 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002864 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002865{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002866 const struct task_security_struct *tsec = selinux_cred(current_cred());
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002867 struct superblock_security_struct *sbsec;
Corentin LABBEc0d4f462017-10-04 20:32:17 +02002868 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002869 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002870 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002871
Casey Schaufler1aea7802021-04-22 17:41:15 +02002872 sbsec = selinux_superblock(dir->i_sb);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002873
David Howells275bb412008-11-14 10:39:19 +11002874 newsid = tsec->create_sid;
2875
Yang Guo210a2922019-12-12 10:02:24 +08002876 rc = selinux_determine_inode_label(tsec, dir, qstr,
David Howellsc3c188b2015-07-10 17:19:58 -04002877 inode_mode_to_security_class(inode->i_mode),
2878 &newsid);
2879 if (rc)
2880 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002881
Eric Paris296fddf2006-09-25 23:32:00 -07002882 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002883 if (sbsec->flags & SE_SBINITIALIZED) {
Casey Schaufler80788c22018-09-21 17:19:11 -07002884 struct inode_security_struct *isec = selinux_inode(inode);
Eric Paris296fddf2006-09-25 23:32:00 -07002885 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2886 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002887 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002888 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002889
Stephen Smalleye67b7982023-03-09 13:30:37 -05002890 if (!selinux_initialized() ||
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01002891 !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002892 return -EOPNOTSUPP;
2893
Tetsuo Handa95489062013-07-25 05:44:02 +09002894 if (name)
2895 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002896
2897 if (value && len) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05002898 rc = security_sid_to_context_force(newsid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002899 &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002900 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002901 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002902 *value = context;
2903 *len = clen;
2904 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002905
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002906 return 0;
2907}
2908
Daniel Colascione29cd6592021-01-08 14:22:22 -08002909static int selinux_inode_init_security_anon(struct inode *inode,
2910 const struct qstr *name,
2911 const struct inode *context_inode)
2912{
2913 const struct task_security_struct *tsec = selinux_cred(current_cred());
2914 struct common_audit_data ad;
2915 struct inode_security_struct *isec;
2916 int rc;
2917
Stephen Smalleye67b7982023-03-09 13:30:37 -05002918 if (unlikely(!selinux_initialized()))
Daniel Colascione29cd6592021-01-08 14:22:22 -08002919 return 0;
2920
2921 isec = selinux_inode(inode);
2922
2923 /*
2924 * We only get here once per ephemeral inode. The inode has
2925 * been initialized via inode_alloc_security but is otherwise
2926 * untouched.
2927 */
2928
2929 if (context_inode) {
2930 struct inode_security_struct *context_isec =
2931 selinux_inode(context_inode);
2932 if (context_isec->initialized != LABEL_INITIALIZED) {
Christian Göttschee5faa832023-07-18 21:00:24 +02002933 pr_err("SELinux: context_inode is not initialized\n");
Daniel Colascione29cd6592021-01-08 14:22:22 -08002934 return -EACCES;
2935 }
2936
2937 isec->sclass = context_isec->sclass;
2938 isec->sid = context_isec->sid;
2939 } else {
2940 isec->sclass = SECCLASS_ANON_INODE;
2941 rc = security_transition_sid(
Stephen Smalleye67b7982023-03-09 13:30:37 -05002942 tsec->sid, tsec->sid,
Daniel Colascione29cd6592021-01-08 14:22:22 -08002943 isec->sclass, name, &isec->sid);
2944 if (rc)
2945 return rc;
2946 }
2947
2948 isec->initialized = LABEL_INITIALIZED;
2949 /*
2950 * Now that we've initialized security, check whether we're
2951 * allowed to actually create this type of anonymous inode.
2952 */
2953
Christian Göttschec29722f2022-03-08 18:09:26 +01002954 ad.type = LSM_AUDIT_DATA_ANONINODE;
2955 ad.u.anonclass = name ? (const char *)name->name : "?";
Daniel Colascione29cd6592021-01-08 14:22:22 -08002956
Stephen Smalleye67b7982023-03-09 13:30:37 -05002957 return avc_has_perm(tsec->sid,
Daniel Colascione29cd6592021-01-08 14:22:22 -08002958 isec->sid,
2959 isec->sclass,
2960 FILE__CREATE,
2961 &ad);
2962}
2963
Al Viro4acdaf22011-07-26 01:42:34 -04002964static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965{
2966 return may_create(dir, dentry, SECCLASS_FILE);
2967}
2968
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2970{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971 return may_link(dir, old_dentry, MAY_LINK);
2972}
2973
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2975{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 return may_link(dir, dentry, MAY_UNLINK);
2977}
2978
2979static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2980{
2981 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2982}
2983
Al Viro18bb1db2011-07-26 01:41:39 -04002984static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985{
2986 return may_create(dir, dentry, SECCLASS_DIR);
2987}
2988
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2990{
2991 return may_link(dir, dentry, MAY_RMDIR);
2992}
2993
Al Viro1a67aaf2011-07-26 01:52:52 -04002994static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2997}
2998
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04003000 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001{
3002 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
3003}
3004
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005static int selinux_inode_readlink(struct dentry *dentry)
3006{
David Howells88e67f32008-11-14 10:39:21 +11003007 const struct cred *cred = current_cred();
3008
Eric Paris2875fa02011-04-28 16:04:24 -04003009 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010}
3011
NeilBrownbda0be72015-03-23 13:37:39 +11003012static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
3013 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014{
David Howells88e67f32008-11-14 10:39:21 +11003015 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11003016 struct common_audit_data ad;
3017 struct inode_security_struct *isec;
3018 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
NeilBrownbda0be72015-03-23 13:37:39 +11003020 validate_creds(cred);
3021
3022 ad.type = LSM_AUDIT_DATA_DENTRY;
3023 ad.u.dentry = dentry;
3024 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003025 isec = inode_security_rcu(inode, rcu);
3026 if (IS_ERR(isec))
3027 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11003028
Stephen Smalleye67b7982023-03-09 13:30:37 -05003029 return avc_has_perm(sid, isec->sid, isec->sclass, FILE__READ, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030}
3031
Eric Parisd4cf970d2012-04-04 15:01:42 -04003032static noinline int audit_inode_permission(struct inode *inode,
3033 u32 perms, u32 audited, u32 denied,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003034 int result)
Eric Parisd4cf970d2012-04-04 15:01:42 -04003035{
3036 struct common_audit_data ad;
Casey Schaufler80788c22018-09-21 17:19:11 -07003037 struct inode_security_struct *isec = selinux_inode(inode);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003038
Eric Paris50c205f2012-04-04 15:01:43 -04003039 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003040 ad.u.inode = inode;
3041
Stephen Smalleye67b7982023-03-09 13:30:37 -05003042 return slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003043 audited, denied, result, &ad);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003044}
3045
Al Viroe74f71e2011-06-20 19:38:15 -04003046static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
David Howells88e67f32008-11-14 10:39:21 +11003048 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003049 u32 perms;
3050 bool from_access;
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003051 bool no_block = mask & MAY_NOT_BLOCK;
Eric Paris2e3340572012-04-04 15:01:42 -04003052 struct inode_security_struct *isec;
3053 u32 sid;
3054 struct av_decision avd;
3055 int rc, rc2;
3056 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
Eric Parisb782e0a2010-07-23 11:44:03 -04003058 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003059 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3060
Eric Parisb782e0a2010-07-23 11:44:03 -04003061 /* No permission to check. Existence test. */
3062 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Eric Paris2e3340572012-04-04 15:01:42 -04003065 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003066
Eric Paris2e3340572012-04-04 15:01:42 -04003067 if (unlikely(IS_PRIVATE(inode)))
3068 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003069
3070 perms = file_mask_to_av(inode->i_mode, mask);
3071
Eric Paris2e3340572012-04-04 15:01:42 -04003072 sid = cred_sid(cred);
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003073 isec = inode_security_rcu(inode, no_block);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003074 if (IS_ERR(isec))
3075 return PTR_ERR(isec);
Eric Paris2e3340572012-04-04 15:01:42 -04003076
Stephen Smalleye67b7982023-03-09 13:30:37 -05003077 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0,
Stephen Smalley3a28cff2018-12-12 10:10:55 -05003078 &avd);
Eric Paris2e3340572012-04-04 15:01:42 -04003079 audited = avc_audit_required(perms, &avd, rc,
3080 from_access ? FILE__AUDIT_ACCESS : 0,
3081 &denied);
3082 if (likely(!audited))
3083 return rc;
3084
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003085 rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
Eric Paris2e3340572012-04-04 15:01:42 -04003086 if (rc2)
3087 return rc2;
3088 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089}
3090
3091static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3092{
David Howells88e67f32008-11-14 10:39:21 +11003093 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003094 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003095 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003096 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003098 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3099 if (ia_valid & ATTR_FORCE) {
3100 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3101 ATTR_FORCE);
3102 if (!ia_valid)
3103 return 0;
3104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003106 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3107 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003108 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003110 if (selinux_policycap_openperm() &&
Stephen Smalleyccb54472017-05-12 12:41:24 -04003111 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3112 (ia_valid & ATTR_SIZE) &&
3113 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003114 av |= FILE__OPEN;
3115
3116 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117}
3118
Al Viro3f7036a2015-03-08 19:28:30 -04003119static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120{
Al Viro3f7036a2015-03-08 19:28:30 -04003121 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122}
3123
Stephen Smalleydb590002017-04-20 11:31:30 -04003124static bool has_cap_mac_admin(bool audit)
3125{
3126 const struct cred *cred = current_cred();
Micah Mortonc1a85a02019-01-07 16:10:53 -08003127 unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
Stephen Smalleydb590002017-04-20 11:31:30 -04003128
Micah Mortonc1a85a02019-01-07 16:10:53 -08003129 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
Stephen Smalleydb590002017-04-20 11:31:30 -04003130 return false;
Micah Mortonc1a85a02019-01-07 16:10:53 -08003131 if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
Stephen Smalleydb590002017-04-20 11:31:30 -04003132 return false;
3133 return true;
3134}
3135
Christian Brauner39f60c12023-01-13 12:49:23 +01003136static int selinux_inode_setxattr(struct mnt_idmap *idmap,
Christian Brauner71bc3562021-01-21 14:19:29 +01003137 struct dentry *dentry, const char *name,
David Howells8f0cfa52008-04-29 00:59:41 -07003138 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139{
David Howellsc6f493d2015-03-17 22:26:22 +00003140 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003141 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003143 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003144 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 int rc = 0;
3146
Eric W. Biederman6b240302017-10-02 09:38:20 -05003147 if (strcmp(name, XATTR_NAME_SELINUX)) {
3148 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3149 if (rc)
3150 return rc;
3151
3152 /* Not an attribute we recognize, so just check the
3153 ordinary setattr permission. */
3154 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156
Stephen Smalleye67b7982023-03-09 13:30:37 -05003157 if (!selinux_initialized())
Christian Brauner01beba72023-01-13 12:49:26 +01003158 return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM);
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003159
Casey Schaufler1aea7802021-04-22 17:41:15 +02003160 sbsec = selinux_superblock(inode->i_sb);
Eric Paris12f348b2012-10-09 10:56:25 -04003161 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 return -EOPNOTSUPP;
3163
Christian Brauner01beba72023-01-13 12:49:26 +01003164 if (!inode_owner_or_capable(idmap, inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 return -EPERM;
3166
Eric Paris50c205f2012-04-04 15:01:43 -04003167 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003168 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Paul Moore20cdef82016-04-04 14:14:42 -04003170 isec = backing_inode_security(dentry);
Stephen Smalleye67b7982023-03-09 13:30:37 -05003171 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 FILE__RELABELFROM, &ad);
3173 if (rc)
3174 return rc;
3175
Stephen Smalleye67b7982023-03-09 13:30:37 -05003176 rc = security_context_to_sid(value, size, &newsid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003177 GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003178 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003179 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003180 struct audit_buffer *ab;
3181 size_t audit_size;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003182
3183 /* We strip a nul only if it is at the end, otherwise the
3184 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003185 if (value) {
Colin Ian Kingadd24372017-10-14 13:46:55 +01003186 const char *str = value;
3187
Al Viroe3fea3f2012-06-09 08:15:16 +01003188 if (str[size - 1] == '\0')
3189 audit_size = size - 1;
3190 else
3191 audit_size = size;
3192 } else {
Al Viroe3fea3f2012-06-09 08:15:16 +01003193 audit_size = 0;
3194 }
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04003195 ab = audit_log_start(audit_context(),
3196 GFP_ATOMIC, AUDIT_SELINUX_ERR);
Austin Kim893c47d2021-07-14 01:11:27 +01003197 if (!ab)
3198 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003199 audit_log_format(ab, "op=setxattr invalid_context=");
3200 audit_log_n_untrustedstring(ab, value, audit_size);
3201 audit_log_end(ab);
3202
Stephen Smalley12b29f32008-05-07 13:03:20 -04003203 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003204 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05003205 rc = security_context_to_sid_force(value,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003206 size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 if (rc)
3209 return rc;
3210
Stephen Smalleye67b7982023-03-09 13:30:37 -05003211 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 FILE__RELABELTO, &ad);
3213 if (rc)
3214 return rc;
3215
Stephen Smalleye67b7982023-03-09 13:30:37 -05003216 rc = security_validate_transition(isec->sid, newsid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003217 sid, isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 if (rc)
3219 return rc;
3220
Stephen Smalleye67b7982023-03-09 13:30:37 -05003221 return avc_has_perm(newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 sbsec->sid,
3223 SECCLASS_FILESYSTEM,
3224 FILESYSTEM__ASSOCIATE,
3225 &ad);
3226}
3227
Christian Brauner700b7942023-01-13 12:49:24 +01003228static int selinux_inode_set_acl(struct mnt_idmap *idmap,
Christian Brauner1bdeb212022-09-22 17:17:08 +02003229 struct dentry *dentry, const char *acl_name,
3230 struct posix_acl *kacl)
3231{
3232 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3233}
3234
Christian Brauner700b7942023-01-13 12:49:24 +01003235static int selinux_inode_get_acl(struct mnt_idmap *idmap,
Christian Brauner1bdeb212022-09-22 17:17:08 +02003236 struct dentry *dentry, const char *acl_name)
3237{
3238 return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
3239}
3240
Christian Brauner700b7942023-01-13 12:49:24 +01003241static int selinux_inode_remove_acl(struct mnt_idmap *idmap,
Christian Brauner1bdeb212022-09-22 17:17:08 +02003242 struct dentry *dentry, const char *acl_name)
3243{
3244 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3245}
3246
David Howells8f0cfa52008-04-29 00:59:41 -07003247static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003248 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003249 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250{
David Howellsc6f493d2015-03-17 22:26:22 +00003251 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003252 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 u32 newsid;
3254 int rc;
3255
3256 if (strcmp(name, XATTR_NAME_SELINUX)) {
3257 /* Not an attribute we recognize, so nothing to do. */
3258 return;
3259 }
3260
Stephen Smalleye67b7982023-03-09 13:30:37 -05003261 if (!selinux_initialized()) {
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003262 /* If we haven't even been initialized, then we can't validate
3263 * against a policy, so leave the label as invalid. It may
3264 * resolve to a valid label on the next revalidation try if
3265 * we've since initialized.
3266 */
3267 return;
3268 }
3269
Stephen Smalleye67b7982023-03-09 13:30:37 -05003270 rc = security_context_to_sid_force(value, size,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003271 &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +02003273 pr_err("SELinux: unable to map context to SID"
Stephen Smalley12b29f32008-05-07 13:03:20 -04003274 "for (%s, %lu), rc=%d\n",
3275 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 return;
3277 }
3278
Paul Moore20cdef82016-04-04 14:14:42 -04003279 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003280 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003281 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003283 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003284 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285}
3286
David Howells8f0cfa52008-04-29 00:59:41 -07003287static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288{
David Howells88e67f32008-11-14 10:39:21 +11003289 const struct cred *cred = current_cred();
3290
Eric Paris2875fa02011-04-28 16:04:24 -04003291 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292}
3293
Eric Paris828dfe12008-04-17 13:17:49 -04003294static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295{
David Howells88e67f32008-11-14 10:39:21 +11003296 const struct cred *cred = current_cred();
3297
Eric Paris2875fa02011-04-28 16:04:24 -04003298 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299}
3300
Christian Brauner39f60c12023-01-13 12:49:23 +01003301static int selinux_inode_removexattr(struct mnt_idmap *idmap,
Christian Brauner71bc3562021-01-21 14:19:29 +01003302 struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303{
Eric W. Biederman6b240302017-10-02 09:38:20 -05003304 if (strcmp(name, XATTR_NAME_SELINUX)) {
Christian Brauner39f60c12023-01-13 12:49:23 +01003305 int rc = cap_inode_removexattr(idmap, dentry, name);
Eric W. Biederman6b240302017-10-02 09:38:20 -05003306 if (rc)
3307 return rc;
3308
3309 /* Not an attribute we recognize, so just check the
3310 ordinary setattr permission. */
3311 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
Stephen Smalleye67b7982023-03-09 13:30:37 -05003314 if (!selinux_initialized())
Stephen Smalley9530a3e2020-08-20 13:00:40 -04003315 return 0;
3316
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 /* No one is allowed to remove a SELinux security label.
3318 You can change the label, but all data must be labeled. */
3319 return -EACCES;
3320}
3321
Aaron Goidelac5656d2019-08-12 11:20:00 -04003322static int selinux_path_notify(const struct path *path, u64 mask,
3323 unsigned int obj_type)
3324{
3325 int ret;
3326 u32 perm;
3327
3328 struct common_audit_data ad;
3329
3330 ad.type = LSM_AUDIT_DATA_PATH;
3331 ad.u.path = *path;
3332
3333 /*
3334 * Set permission needed based on the type of mark being set.
3335 * Performs an additional check for sb watches.
3336 */
3337 switch (obj_type) {
3338 case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
3339 perm = FILE__WATCH_MOUNT;
3340 break;
3341 case FSNOTIFY_OBJ_TYPE_SB:
3342 perm = FILE__WATCH_SB;
3343 ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
3344 FILESYSTEM__WATCH, &ad);
3345 if (ret)
3346 return ret;
3347 break;
3348 case FSNOTIFY_OBJ_TYPE_INODE:
3349 perm = FILE__WATCH;
3350 break;
3351 default:
3352 return -EINVAL;
3353 }
3354
3355 /* blocking watches require the file:watch_with_perm permission */
3356 if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
3357 perm |= FILE__WATCH_WITH_PERM;
3358
3359 /* watches on read-like events need the file:watch_reads permission */
3360 if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3361 perm |= FILE__WATCH_READS;
3362
3363 return path_has_perm(current_cred(), path, perm);
3364}
3365
James Morrisd381d8a2005-10-30 14:59:22 -08003366/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003367 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003368 *
3369 * Permission check is handled by selinux_inode_getxattr hook.
3370 */
Christian Brauner4609e1f2023-01-13 12:49:22 +01003371static int selinux_inode_getsecurity(struct mnt_idmap *idmap,
Christian Brauner71bc3562021-01-21 14:19:29 +01003372 struct inode *inode, const char *name,
3373 void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374{
David P. Quigley42492592008-02-04 22:29:39 -08003375 u32 size;
3376 int error;
3377 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003378 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Jonathan Lebonc8e22262020-05-28 10:39:40 -04003380 /*
3381 * If we're not initialized yet, then we can't validate contexts, so
3382 * just let vfs_getxattr fall back to using the on-disk xattr.
3383 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05003384 if (!selinux_initialized() ||
Jonathan Lebonc8e22262020-05-28 10:39:40 -04003385 strcmp(name, XATTR_SELINUX_SUFFIX))
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003386 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003388 /*
3389 * If the caller has CAP_MAC_ADMIN, then get the raw context
3390 * value even if it is not defined by current policy; otherwise,
3391 * use the in-core value under current policy.
3392 * Use the non-auditing forms of the permission checks since
3393 * getxattr may be called by unprivileged processes commonly
3394 * and lack of permission just means that we fall back to the
3395 * in-core context value, not a denial.
3396 */
Paul Moore20cdef82016-04-04 14:14:42 -04003397 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003398 if (has_cap_mac_admin(false))
Stephen Smalleye67b7982023-03-09 13:30:37 -05003399 error = security_sid_to_context_force(isec->sid, &context,
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003400 &size);
3401 else
Stephen Smalleye67b7982023-03-09 13:30:37 -05003402 error = security_sid_to_context(isec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003403 &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003404 if (error)
3405 return error;
3406 error = size;
3407 if (alloc) {
3408 *buffer = context;
3409 goto out_nofree;
3410 }
3411 kfree(context);
3412out_nofree:
3413 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414}
3415
3416static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003417 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418{
Paul Moore2c971652016-04-19 16:36:28 -04003419 struct inode_security_struct *isec = inode_security_novalidate(inode);
Casey Schaufler1aea7802021-04-22 17:41:15 +02003420 struct superblock_security_struct *sbsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 u32 newsid;
3422 int rc;
3423
3424 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3425 return -EOPNOTSUPP;
3426
Casey Schaufler1aea7802021-04-22 17:41:15 +02003427 sbsec = selinux_superblock(inode->i_sb);
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01003428 if (!(sbsec->flags & SBLABEL_MNT))
3429 return -EOPNOTSUPP;
3430
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 if (!value || !size)
3432 return -EACCES;
3433
Stephen Smalleye67b7982023-03-09 13:30:37 -05003434 rc = security_context_to_sid(value, size, &newsid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003435 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 if (rc)
3437 return rc;
3438
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003439 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003440 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003442 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003443 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 return 0;
3445}
3446
3447static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3448{
3449 const int len = sizeof(XATTR_NAME_SELINUX);
Amir Goldsteina9ffe682020-12-19 12:05:27 +02003450
Stephen Smalleye67b7982023-03-09 13:30:37 -05003451 if (!selinux_initialized())
Amir Goldsteina9ffe682020-12-19 12:05:27 +02003452 return 0;
3453
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 if (buffer && len <= buffer_size)
3455 memcpy(buffer, XATTR_NAME_SELINUX, len);
3456 return len;
3457}
3458
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003459static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003460{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003461 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003462 *secid = isec->sid;
3463}
3464
Vivek Goyal56909eb2016-07-13 10:44:48 -04003465static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3466{
3467 u32 sid;
3468 struct task_security_struct *tsec;
3469 struct cred *new_creds = *new;
3470
3471 if (new_creds == NULL) {
3472 new_creds = prepare_creds();
3473 if (!new_creds)
3474 return -ENOMEM;
3475 }
3476
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003477 tsec = selinux_cred(new_creds);
Vivek Goyal56909eb2016-07-13 10:44:48 -04003478 /* Get label from overlay inode and set it in create_sid */
3479 selinux_inode_getsecid(d_inode(src), &sid);
3480 tsec->create_sid = sid;
3481 *new = new_creds;
3482 return 0;
3483}
3484
Vivek Goyal19472b62016-07-13 10:44:50 -04003485static int selinux_inode_copy_up_xattr(const char *name)
3486{
3487 /* The copy_up hook above sets the initial context on an inode, but we
3488 * don't then want to overwrite it by blindly copying all the lower
3489 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3490 */
3491 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3492 return 1; /* Discard */
3493 /*
3494 * Any other attribute apart from SELINUX is not claimed, supported
3495 * by selinux.
3496 */
3497 return -EOPNOTSUPP;
3498}
3499
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003500/* kernfs node operations */
3501
YueHaibingc72c4cd2019-03-22 22:04:00 +08003502static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
3503 struct kernfs_node *kn)
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003504{
Stephen Smalley169ce0c2019-09-04 10:32:48 -04003505 const struct task_security_struct *tsec = selinux_cred(current_cred());
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003506 u32 parent_sid, newsid, clen;
3507 int rc;
3508 char *context;
3509
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003510 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003511 if (rc == -ENODATA)
3512 return 0;
3513 else if (rc < 0)
3514 return rc;
3515
3516 clen = (u32)rc;
3517 context = kmalloc(clen, GFP_KERNEL);
3518 if (!context)
3519 return -ENOMEM;
3520
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003521 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, context, clen);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003522 if (rc < 0) {
3523 kfree(context);
3524 return rc;
3525 }
3526
Stephen Smalleye67b7982023-03-09 13:30:37 -05003527 rc = security_context_to_sid(context, clen, &parent_sid,
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003528 GFP_KERNEL);
3529 kfree(context);
3530 if (rc)
3531 return rc;
3532
3533 if (tsec->create_sid) {
3534 newsid = tsec->create_sid;
3535 } else {
3536 u16 secclass = inode_mode_to_security_class(kn->mode);
3537 struct qstr q;
3538
3539 q.name = kn->name;
3540 q.hash_len = hashlen_string(kn_dir, kn->name);
3541
Stephen Smalleye67b7982023-03-09 13:30:37 -05003542 rc = security_transition_sid(tsec->sid,
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003543 parent_sid, secclass, &q,
3544 &newsid);
3545 if (rc)
3546 return rc;
3547 }
3548
Stephen Smalleye67b7982023-03-09 13:30:37 -05003549 rc = security_sid_to_context_force(newsid,
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003550 &context, &clen);
3551 if (rc)
3552 return rc;
3553
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003554 rc = kernfs_xattr_set(kn, XATTR_NAME_SELINUX, context, clen,
3555 XATTR_CREATE);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003556 kfree(context);
3557 return rc;
3558}
3559
3560
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561/* file security operations */
3562
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003563static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564{
David Howells88e67f32008-11-14 10:39:21 +11003565 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003566 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3569 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3570 mask |= MAY_APPEND;
3571
Paul Moore389fb8002009-03-27 17:10:34 -04003572 return file_has_perm(cred, file,
3573 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574}
3575
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003576static int selinux_file_permission(struct file *file, int mask)
3577{
Al Viro496ad9a2013-01-23 17:07:38 -05003578 struct inode *inode = file_inode(file);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003579 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003580 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003581 u32 sid = current_sid();
3582
Paul Moore389fb8002009-03-27 17:10:34 -04003583 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003584 /* No permission to check. Existence test. */
3585 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003586
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003587 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003588 if (sid == fsec->sid && fsec->isid == isec->sid &&
Stephen Smalleye67b7982023-03-09 13:30:37 -05003589 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003590 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003591 return 0;
3592
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003593 return selinux_revalidate_file_permission(file, mask);
3594}
3595
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596static int selinux_file_alloc_security(struct file *file)
3597{
Paul Moorecb89e242020-01-10 16:32:10 -05003598 struct file_security_struct *fsec = selinux_file(file);
3599 u32 sid = current_sid();
3600
3601 fsec->sid = sid;
3602 fsec->fown_sid = sid;
3603
3604 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605}
3606
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003607/*
3608 * Check whether a task has the ioctl permission and cmd
3609 * operation to an inode.
3610 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003611static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003612 u32 requested, u16 cmd)
3613{
3614 struct common_audit_data ad;
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003615 struct file_security_struct *fsec = selinux_file(file);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003616 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003617 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003618 struct lsm_ioctlop_audit ioctl;
3619 u32 ssid = cred_sid(cred);
3620 int rc;
3621 u8 driver = cmd >> 8;
3622 u8 xperm = cmd & 0xff;
3623
3624 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3625 ad.u.op = &ioctl;
3626 ad.u.op->cmd = cmd;
3627 ad.u.op->path = file->f_path;
3628
3629 if (ssid != fsec->sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05003630 rc = avc_has_perm(ssid, fsec->sid,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003631 SECCLASS_FD,
3632 FD__USE,
3633 &ad);
3634 if (rc)
3635 goto out;
3636 }
3637
3638 if (unlikely(IS_PRIVATE(inode)))
3639 return 0;
3640
Paul Moore20cdef82016-04-04 14:14:42 -04003641 isec = inode_security(inode);
Stephen Smalleye67b7982023-03-09 13:30:37 -05003642 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003643 requested, driver, xperm, &ad);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003644out:
3645 return rc;
3646}
3647
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3649 unsigned long arg)
3650{
David Howells88e67f32008-11-14 10:39:21 +11003651 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003652 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
Eric Paris0b24dcb2011-02-25 15:39:20 -05003654 switch (cmd) {
3655 case FIONREAD:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003656 case FIBMAP:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003657 case FIGETBSZ:
Al Viro2f99c362012-03-23 16:04:05 -04003658 case FS_IOC_GETFLAGS:
Al Viro2f99c362012-03-23 16:04:05 -04003659 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003660 error = file_has_perm(cred, file, FILE__GETATTR);
3661 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662
Al Viro2f99c362012-03-23 16:04:05 -04003663 case FS_IOC_SETFLAGS:
Al Viro2f99c362012-03-23 16:04:05 -04003664 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003665 error = file_has_perm(cred, file, FILE__SETATTR);
3666 break;
3667
3668 /* sys_ioctl() checks */
3669 case FIONBIO:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003670 case FIOASYNC:
3671 error = file_has_perm(cred, file, 0);
3672 break;
3673
3674 case KDSKBENT:
3675 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003676 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Micah Mortonc1a85a02019-01-07 16:10:53 -08003677 CAP_OPT_NONE, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003678 break;
3679
Richard Haines65881e12022-02-25 17:54:38 +00003680 case FIOCLEX:
3681 case FIONCLEX:
3682 if (!selinux_policycap_ioctl_skip_cloexec())
3683 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
3684 break;
3685
Eric Paris0b24dcb2011-02-25 15:39:20 -05003686 /* default case assumes that the command will go
3687 * to the file's ioctl() function.
3688 */
3689 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003690 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003691 }
3692 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693}
3694
Stephen Smalleyb78b7d52020-01-08 12:23:56 -05003695static int default_noexec __ro_after_init;
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3698{
David Howells88e67f32008-11-14 10:39:21 +11003699 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003700 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003701 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003702
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003703 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003704 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3705 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 /*
3707 * We are making executable an anonymous mapping or a
3708 * private file mapping that will also be writable.
3709 * This has an additional check.
3710 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05003711 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003712 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003714 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716
3717 if (file) {
3718 /* read access is always possible with a mapping */
3719 u32 av = FILE__READ;
3720
3721 /* write access only matters if the mapping is shared */
3722 if (shared && (prot & PROT_WRITE))
3723 av |= FILE__WRITE;
3724
3725 if (prot & PROT_EXEC)
3726 av |= FILE__EXECUTE;
3727
David Howells88e67f32008-11-14 10:39:21 +11003728 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 }
David Howellsd84f4f92008-11-14 10:39:23 +11003730
3731error:
3732 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733}
3734
Al Viroe5467852012-05-30 13:30:51 -04003735static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003737 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003738
3739 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3740 u32 sid = current_sid();
Stephen Smalleye67b7982023-03-09 13:30:37 -05003741 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
Paul Moore98883bf2014-03-19 16:46:11 -04003742 MEMPROTECT__MMAP_ZERO, NULL);
3743 }
3744
3745 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003746}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
Paul Moorea7e46762023-03-16 11:43:08 -04003748static int selinux_mmap_file(struct file *file,
3749 unsigned long reqprot __always_unused,
Al Viroe5467852012-05-30 13:30:51 -04003750 unsigned long prot, unsigned long flags)
3751{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003752 struct common_audit_data ad;
3753 int rc;
3754
3755 if (file) {
3756 ad.type = LSM_AUDIT_DATA_FILE;
3757 ad.u.file = file;
3758 rc = inode_has_perm(current_cred(), file_inode(file),
3759 FILE__MAP, &ad);
3760 if (rc)
3761 return rc;
3762 }
3763
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 return file_map_prot_check(file, prot,
3765 (flags & MAP_TYPE) == MAP_SHARED);
3766}
3767
3768static int selinux_file_mprotect(struct vm_area_struct *vma,
Paul Moorea7e46762023-03-16 11:43:08 -04003769 unsigned long reqprot __always_unused,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 unsigned long prot)
3771{
David Howells88e67f32008-11-14 10:39:21 +11003772 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003773 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003775 if (default_noexec &&
3776 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003777 int rc = 0;
Stephen Smalleydb4c96412006-02-01 03:05:54 -08003778 if (vma->vm_start >= vma->vm_mm->start_brk &&
3779 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05003780 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003781 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c96412006-02-01 03:05:54 -08003782 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003783 ((vma->vm_start <= vma->vm_mm->start_stack &&
3784 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003785 vma_is_stack_for_current(vma))) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05003786 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003787 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c96412006-02-01 03:05:54 -08003788 } else if (vma->vm_file && vma->anon_vma) {
3789 /*
3790 * We are making executable a file mapping that has
3791 * had some COW done. Since pages might have been
3792 * written, check ability to execute the possibly
3793 * modified content. This typically should only
3794 * occur for text relocations.
3795 */
David Howellsd84f4f92008-11-14 10:39:23 +11003796 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c96412006-02-01 03:05:54 -08003797 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003798 if (rc)
3799 return rc;
3800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
3802 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3803}
3804
3805static int selinux_file_lock(struct file *file, unsigned int cmd)
3806{
David Howells88e67f32008-11-14 10:39:21 +11003807 const struct cred *cred = current_cred();
3808
3809 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810}
3811
3812static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3813 unsigned long arg)
3814{
David Howells88e67f32008-11-14 10:39:21 +11003815 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 int err = 0;
3817
3818 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003819 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003820 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003821 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003823 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05003824 fallthrough;
Eric Paris828dfe12008-04-17 13:17:49 -04003825 case F_SETOWN:
3826 case F_SETSIG:
3827 case F_GETFL:
3828 case F_GETOWN:
3829 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003830 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003831 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003832 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003833 break;
3834 case F_GETLK:
3835 case F_SETLK:
3836 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003837 case F_OFD_GETLK:
3838 case F_OFD_SETLK:
3839 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003841 case F_GETLK64:
3842 case F_SETLK64:
3843 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844#endif
David Howells88e67f32008-11-14 10:39:21 +11003845 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003846 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 }
3848
3849 return err;
3850}
3851
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003852static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 struct file_security_struct *fsec;
3855
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003856 fsec = selinux_file(file);
David Howells275bb412008-11-14 10:39:19 +11003857 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858}
3859
3860static int selinux_file_send_sigiotask(struct task_struct *tsk,
3861 struct fown_struct *fown, int signum)
3862{
Eric Paris828dfe12008-04-17 13:17:49 -04003863 struct file *file;
Paul Mooreeb1231f2021-02-18 15:13:40 -05003864 u32 sid = task_sid_obj(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 struct file_security_struct *fsec;
3867
3868 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003869 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003871 fsec = selinux_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
3873 if (!signum)
3874 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3875 else
3876 perm = signal_to_av(signum);
3877
Stephen Smalleye67b7982023-03-09 13:30:37 -05003878 return avc_has_perm(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 Smalleye67b7982023-03-09 13:30:37 -05003904 fsec->pseqno = avc_policy_seqno();
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 Smalleye67b7982023-03-09 13:30:37 -05003923 return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924}
3925
David Howellsf1752ee2008-11-14 10:39:17 +11003926/*
David Howellsd84f4f92008-11-14 10:39:23 +11003927 * prepare a new set of credentials for modification
3928 */
3929static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3930 gfp_t gfp)
3931{
Casey Schauflerbbd36622018-11-12 09:30:56 -08003932 const struct task_security_struct *old_tsec = selinux_cred(old);
3933 struct task_security_struct *tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11003934
Casey Schauflerbbd36622018-11-12 09:30:56 -08003935 *tsec = *old_tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11003936 return 0;
3937}
3938
3939/*
David Howellsee18d642009-09-02 09:14:21 +01003940 * transfer the SELinux data to a blank set of creds
3941 */
3942static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3943{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003944 const struct task_security_struct *old_tsec = selinux_cred(old);
3945 struct task_security_struct *tsec = selinux_cred(new);
David Howellsee18d642009-09-02 09:14:21 +01003946
3947 *tsec = *old_tsec;
3948}
3949
Matthew Garrett3ec30112018-01-08 13:36:19 -08003950static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3951{
3952 *secid = cred_sid(c);
3953}
3954
David Howellsee18d642009-09-02 09:14:21 +01003955/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003956 * set the security data for a kernel service
3957 * - all the creation contexts are set to unlabelled
3958 */
3959static int selinux_kernel_act_as(struct cred *new, u32 secid)
3960{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003961 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003962 u32 sid = current_sid();
3963 int ret;
3964
Stephen Smalleye67b7982023-03-09 13:30:37 -05003965 ret = avc_has_perm(sid, secid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003966 SECCLASS_KERNEL_SERVICE,
3967 KERNEL_SERVICE__USE_AS_OVERRIDE,
3968 NULL);
3969 if (ret == 0) {
3970 tsec->sid = secid;
3971 tsec->create_sid = 0;
3972 tsec->keycreate_sid = 0;
3973 tsec->sockcreate_sid = 0;
3974 }
3975 return ret;
3976}
3977
3978/*
3979 * set the file creation context in a security record to the same as the
3980 * objective context of the specified inode
3981 */
3982static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3983{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003984 struct inode_security_struct *isec = inode_security(inode);
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003985 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003986 u32 sid = current_sid();
3987 int ret;
3988
Stephen Smalleye67b7982023-03-09 13:30:37 -05003989 ret = avc_has_perm(sid, isec->sid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003990 SECCLASS_KERNEL_SERVICE,
3991 KERNEL_SERVICE__CREATE_FILES_AS,
3992 NULL);
3993
3994 if (ret == 0)
3995 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003996 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003997}
3998
Eric Parisdd8dbf22009-11-03 16:35:32 +11003999static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04004000{
Eric Parisdd8dbf22009-11-03 16:35:32 +11004001 struct common_audit_data ad;
4002
Eric Paris50c205f2012-04-04 15:01:43 -04004003 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11004004 ad.u.kmod_name = kmod_name;
4005
Stephen Smalleye67b7982023-03-09 13:30:37 -05004006 return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11004007 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04004008}
4009
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004010static int selinux_kernel_module_from_file(struct file *file)
4011{
4012 struct common_audit_data ad;
4013 struct inode_security_struct *isec;
4014 struct file_security_struct *fsec;
4015 u32 sid = current_sid();
4016 int rc;
4017
4018 /* init_module */
4019 if (file == NULL)
Stephen Smalleye67b7982023-03-09 13:30:37 -05004020 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004021 SYSTEM__MODULE_LOAD, NULL);
4022
4023 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04004024
Vivek Goyal43af5de2016-09-09 11:37:49 -04004025 ad.type = LSM_AUDIT_DATA_FILE;
4026 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004027
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07004028 fsec = selinux_file(file);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004029 if (sid != fsec->sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05004030 rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004031 if (rc)
4032 return rc;
4033 }
4034
Paul Moore20cdef82016-04-04 14:14:42 -04004035 isec = inode_security(file_inode(file));
Stephen Smalleye67b7982023-03-09 13:30:37 -05004036 return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004037 SYSTEM__MODULE_LOAD, &ad);
4038}
4039
4040static int selinux_kernel_read_file(struct file *file,
Kees Cook2039bda2020-10-02 10:38:23 -07004041 enum kernel_read_file_id id,
4042 bool contents)
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004043{
4044 int rc = 0;
4045
4046 switch (id) {
4047 case READING_MODULE:
Kees Cook2039bda2020-10-02 10:38:23 -07004048 rc = selinux_kernel_module_from_file(contents ? file : NULL);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07004049 break;
4050 default:
4051 break;
4052 }
4053
4054 return rc;
4055}
4056
Kees Cookb64fcae2020-10-02 10:38:20 -07004057static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04004058{
4059 int rc = 0;
4060
4061 switch (id) {
4062 case LOADING_MODULE:
4063 rc = selinux_kernel_module_from_file(NULL);
Gustavo A. R. Silvab2d99bc2020-11-20 12:32:26 -06004064 break;
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04004065 default:
4066 break;
4067 }
4068
4069 return rc;
4070}
4071
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
4073{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004074 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004075 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076}
4077
4078static int selinux_task_getpgid(struct task_struct *p)
4079{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004080 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004081 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082}
4083
4084static int selinux_task_getsid(struct task_struct *p)
4085{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004086 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004087 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088}
4089
Paul Moore63269482021-09-29 11:01:21 -04004090static void selinux_current_getsecid_subj(u32 *secid)
David Quigleyf9008e4c2006-06-30 01:55:46 -07004091{
Paul Moore63269482021-09-29 11:01:21 -04004092 *secid = current_sid();
Paul Mooreeb1231f2021-02-18 15:13:40 -05004093}
4094
4095static void selinux_task_getsecid_obj(struct task_struct *p, u32 *secid)
4096{
4097 *secid = task_sid_obj(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07004098}
4099
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100static int selinux_task_setnice(struct task_struct *p, int nice)
4101{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004102 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004103 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104}
4105
James Morris03e68062006-06-23 02:03:58 -07004106static int selinux_task_setioprio(struct task_struct *p, int ioprio)
4107{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004108 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004109 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07004110}
4111
David Quigleya1836a42006-06-30 01:55:49 -07004112static int selinux_task_getioprio(struct task_struct *p)
4113{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004114 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004115 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07004116}
4117
Corentin LABBE42985552017-10-04 20:32:18 +02004118static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
4119 unsigned int flags)
Stephen Smalley791ec492017-02-17 07:57:00 -05004120{
4121 u32 av = 0;
4122
Stephen Smalley84e68852017-02-28 09:35:08 -05004123 if (!flags)
4124 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05004125 if (flags & LSM_PRLIMIT_WRITE)
4126 av |= PROCESS__SETRLIMIT;
4127 if (flags & LSM_PRLIMIT_READ)
4128 av |= PROCESS__GETRLIMIT;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004129 return avc_has_perm(cred_sid(cred), cred_sid(tcred),
Stephen Smalley791ec492017-02-17 07:57:00 -05004130 SECCLASS_PROCESS, av, NULL);
4131}
4132
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004133static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
4134 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004136 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
4138 /* Control the ability to change the hard limit (whether
4139 lowering or raising it), so that the hard limit can
4140 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11004141 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalleye67b7982023-03-09 13:30:37 -05004143 return avc_has_perm(current_sid(), task_sid_obj(p),
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004144 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
4146 return 0;
4147}
4148
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09004149static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004151 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004152 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153}
4154
4155static int selinux_task_getscheduler(struct task_struct *p)
4156{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004157 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004158 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159}
4160
David Quigley35601542006-06-23 02:04:01 -07004161static int selinux_task_movememory(struct task_struct *p)
4162{
Stephen Smalleye67b7982023-03-09 13:30:37 -05004163 return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004164 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07004165}
4166
Eric W. Biedermanae7795b2018-09-25 11:27:20 +02004167static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004168 int sig, const struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004170 u32 secid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 if (!sig)
4174 perm = PROCESS__SIGNULL; /* null signal; existence test */
4175 else
4176 perm = signal_to_av(sig);
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004177 if (!cred)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004178 secid = current_sid();
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004179 else
4180 secid = cred_sid(cred);
Stephen Smalleye67b7982023-03-09 13:30:37 -05004181 return avc_has_perm(secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182}
4183
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184static void selinux_task_to_inode(struct task_struct *p,
4185 struct inode *inode)
4186{
Casey Schaufler80788c22018-09-21 17:19:11 -07004187 struct inode_security_struct *isec = selinux_inode(inode);
Paul Mooreeb1231f2021-02-18 15:13:40 -05004188 u32 sid = task_sid_obj(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004190 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004191 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004192 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004193 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004194 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195}
4196
Frederick Lawlered5d44d2022-08-15 11:20:28 -05004197static int selinux_userns_create(const struct cred *cred)
4198{
4199 u32 sid = current_sid();
4200
Stephen Smalleye67b7982023-03-09 13:30:37 -05004201 return avc_has_perm(sid, sid, SECCLASS_USER_NAMESPACE,
4202 USER_NAMESPACE__CREATE, NULL);
Frederick Lawlered5d44d2022-08-15 11:20:28 -05004203}
4204
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004206static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004207 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208{
4209 int offset, ihlen, ret = -EINVAL;
4210 struct iphdr _iph, *ih;
4211
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004212 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4214 if (ih == NULL)
4215 goto out;
4216
4217 ihlen = ih->ihl * 4;
4218 if (ihlen < sizeof(_iph))
4219 goto out;
4220
Eric Paris48c62af2012-04-02 13:15:44 -04004221 ad->u.net->v4info.saddr = ih->saddr;
4222 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 ret = 0;
4224
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004225 if (proto)
4226 *proto = ih->protocol;
4227
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004229 case IPPROTO_TCP: {
4230 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
Eric Paris828dfe12008-04-17 13:17:49 -04004232 if (ntohs(ih->frag_off) & IP_OFFSET)
4233 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
4235 offset += ihlen;
4236 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4237 if (th == NULL)
4238 break;
4239
Eric Paris48c62af2012-04-02 13:15:44 -04004240 ad->u.net->sport = th->source;
4241 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Eric Paris828dfe12008-04-17 13:17:49 -04004245 case IPPROTO_UDP: {
4246 struct udphdr _udph, *uh;
4247
4248 if (ntohs(ih->frag_off) & IP_OFFSET)
4249 break;
4250
4251 offset += ihlen;
4252 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4253 if (uh == NULL)
4254 break;
4255
Eric Paris48c62af2012-04-02 13:15:44 -04004256 ad->u.net->sport = uh->source;
4257 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004258 break;
4259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
James Morris2ee92d42006-11-13 16:09:01 -08004261 case IPPROTO_DCCP: {
4262 struct dccp_hdr _dccph, *dh;
4263
4264 if (ntohs(ih->frag_off) & IP_OFFSET)
4265 break;
4266
4267 offset += ihlen;
4268 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4269 if (dh == NULL)
4270 break;
4271
Eric Paris48c62af2012-04-02 13:15:44 -04004272 ad->u.net->sport = dh->dccph_sport;
4273 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004274 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004275 }
James Morris2ee92d42006-11-13 16:09:01 -08004276
Richard Hainesd4529302018-02-13 20:57:18 +00004277#if IS_ENABLED(CONFIG_IP_SCTP)
4278 case IPPROTO_SCTP: {
4279 struct sctphdr _sctph, *sh;
4280
4281 if (ntohs(ih->frag_off) & IP_OFFSET)
4282 break;
4283
4284 offset += ihlen;
4285 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4286 if (sh == NULL)
4287 break;
4288
4289 ad->u.net->sport = sh->source;
4290 ad->u.net->dport = sh->dest;
4291 break;
4292 }
4293#endif
Eric Paris828dfe12008-04-17 13:17:49 -04004294 default:
4295 break;
4296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297out:
4298 return ret;
4299}
4300
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004301#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302
4303/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004304static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004305 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306{
4307 u8 nexthdr;
4308 int ret = -EINVAL, offset;
4309 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004310 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004312 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4314 if (ip6 == NULL)
4315 goto out;
4316
Eric Paris48c62af2012-04-02 13:15:44 -04004317 ad->u.net->v6info.saddr = ip6->saddr;
4318 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 ret = 0;
4320
4321 nexthdr = ip6->nexthdr;
4322 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004323 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 if (offset < 0)
4325 goto out;
4326
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004327 if (proto)
4328 *proto = nexthdr;
4329
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 switch (nexthdr) {
4331 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004332 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
4334 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4335 if (th == NULL)
4336 break;
4337
Eric Paris48c62af2012-04-02 13:15:44 -04004338 ad->u.net->sport = th->source;
4339 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 break;
4341 }
4342
4343 case IPPROTO_UDP: {
4344 struct udphdr _udph, *uh;
4345
4346 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4347 if (uh == NULL)
4348 break;
4349
Eric Paris48c62af2012-04-02 13:15:44 -04004350 ad->u.net->sport = uh->source;
4351 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 break;
4353 }
4354
James Morris2ee92d42006-11-13 16:09:01 -08004355 case IPPROTO_DCCP: {
4356 struct dccp_hdr _dccph, *dh;
4357
4358 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4359 if (dh == NULL)
4360 break;
4361
Eric Paris48c62af2012-04-02 13:15:44 -04004362 ad->u.net->sport = dh->dccph_sport;
4363 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004364 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004365 }
James Morris2ee92d42006-11-13 16:09:01 -08004366
Richard Hainesd4529302018-02-13 20:57:18 +00004367#if IS_ENABLED(CONFIG_IP_SCTP)
4368 case IPPROTO_SCTP: {
4369 struct sctphdr _sctph, *sh;
4370
4371 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4372 if (sh == NULL)
4373 break;
4374
4375 ad->u.net->sport = sh->source;
4376 ad->u.net->dport = sh->dest;
4377 break;
4378 }
4379#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 /* includes fragments */
4381 default:
4382 break;
4383 }
4384out:
4385 return ret;
4386}
4387
4388#endif /* IPV6 */
4389
Thomas Liu2bf49692009-07-14 12:14:09 -04004390static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004391 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392{
David Howellscf9481e2008-07-27 21:31:07 +10004393 char *addrp;
4394 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395
Eric Paris48c62af2012-04-02 13:15:44 -04004396 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004398 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004399 if (ret)
4400 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004401 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4402 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004403 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004405#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004407 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004408 if (ret)
4409 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004410 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4411 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004412 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413#endif /* IPV6 */
4414 default:
David Howellscf9481e2008-07-27 21:31:07 +10004415 addrp = NULL;
4416 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 }
4418
David Howellscf9481e2008-07-27 21:31:07 +10004419parse_error:
peter enderborgc103a912018-06-12 10:09:03 +02004420 pr_warn(
David Howellscf9481e2008-07-27 21:31:07 +10004421 "SELinux: failure in selinux_parse_skb(),"
4422 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004424
4425okay:
4426 if (_addrp)
4427 *_addrp = addrp;
4428 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429}
4430
Paul Moore4f6a9932007-03-01 14:35:22 -05004431/**
Paul Moore220deb92008-01-29 08:38:23 -05004432 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004433 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004434 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004435 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004436 *
4437 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004438 * Check the various different forms of network peer labeling and determine
4439 * the peer label/SID for the packet; most of the magic actually occurs in
4440 * the security server function security_net_peersid_cmp(). The function
4441 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4442 * or -EACCES if @sid is invalid due to inconsistencies with the different
4443 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004444 *
4445 */
Paul Moore220deb92008-01-29 08:38:23 -05004446static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004447{
Paul Moore71f1cb02008-01-29 08:51:16 -05004448 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004449 u32 xfrm_sid;
4450 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004451 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004452
Paul Moore817eff72013-12-10 14:57:54 -05004453 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004454 if (unlikely(err))
4455 return -EACCES;
4456 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4457 if (unlikely(err))
4458 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004459
Stephen Smalleye67b7982023-03-09 13:30:37 -05004460 err = security_net_peersid_resolve(nlbl_sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004461 nlbl_type, xfrm_sid, sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004462 if (unlikely(err)) {
peter enderborgc103a912018-06-12 10:09:03 +02004463 pr_warn(
Paul Moore71f1cb02008-01-29 08:51:16 -05004464 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4465 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004466 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004467 }
Paul Moore220deb92008-01-29 08:38:23 -05004468
4469 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004470}
4471
Paul Moore446b8022013-12-04 16:10:51 -05004472/**
4473 * selinux_conn_sid - Determine the child socket label for a connection
4474 * @sk_sid: the parent socket's SID
4475 * @skb_sid: the packet's SID
4476 * @conn_sid: the resulting connection SID
4477 *
4478 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4479 * combined with the MLS information from @skb_sid in order to create
Randy Dunlapc76a2f92020-08-07 09:51:34 -07004480 * @conn_sid. If @skb_sid is not valid then @conn_sid is simply a copy
Paul Moore446b8022013-12-04 16:10:51 -05004481 * of @sk_sid. Returns zero on success, negative values on failure.
4482 *
4483 */
4484static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4485{
4486 int err = 0;
4487
4488 if (skb_sid != SECSID_NULL)
Stephen Smalleye67b7982023-03-09 13:30:37 -05004489 err = security_sid_mls_copy(sk_sid, skb_sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004490 conn_sid);
Paul Moore446b8022013-12-04 16:10:51 -05004491 else
4492 *conn_sid = sk_sid;
4493
4494 return err;
4495}
4496
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004498
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004499static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4500 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004501{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004502 if (tsec->sockcreate_sid > SECSID_NULL) {
4503 *socksid = tsec->sockcreate_sid;
4504 return 0;
4505 }
4506
Stephen Smalleye67b7982023-03-09 13:30:37 -05004507 return security_transition_sid(tsec->sid, tsec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004508 secclass, NULL, socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004509}
4510
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004511static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512{
Paul Moore253bfae2010-04-22 14:46:19 -04004513 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004514 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004515 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516
Paul Moore253bfae2010-04-22 14:46:19 -04004517 if (sksec->sid == SECINITSID_KERNEL)
4518 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519
Ondrej Mosnacek5b0eea82023-06-20 15:12:22 +02004520 /*
4521 * Before POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, sockets that
4522 * inherited the kernel context from early boot used to be skipped
4523 * here, so preserve that behavior unless the capability is set.
4524 *
4525 * By setting the capability the policy signals that it is ready
4526 * for this quirk to be fixed. Note that sockets created by a kernel
4527 * thread or a usermode helper executed without a transition will
4528 * still be skipped in this check regardless of the policycap
4529 * setting.
4530 */
4531 if (!selinux_policycap_userspace_initial_context() &&
4532 sksec->sid == SECINITSID_INIT)
4533 return 0;
4534
Eric Paris50c205f2012-04-04 15:01:43 -04004535 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004536 ad.u.net = &net;
4537 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538
Stephen Smalleye67b7982023-03-09 13:30:37 -05004539 return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004540 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541}
4542
4543static int selinux_socket_create(int family, int type,
4544 int protocol, int kern)
4545{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004546 const struct task_security_struct *tsec = selinux_cred(current_cred());
Paul Moored4f2d972010-04-22 14:46:18 -04004547 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004548 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004549 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
4551 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004552 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553
David Howells275bb412008-11-14 10:39:19 +11004554 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004555 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4556 if (rc)
4557 return rc;
4558
Stephen Smalleye67b7982023-03-09 13:30:37 -05004559 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560}
4561
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004562static int selinux_socket_post_create(struct socket *sock, int family,
4563 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004565 const struct task_security_struct *tsec = selinux_cred(current_cred());
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004566 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004567 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004568 u16 sclass = socket_type_to_security_class(family, type, protocol);
4569 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004570 int err = 0;
4571
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004572 if (!kern) {
4573 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004574 if (err)
4575 return err;
4576 }
David Howells275bb412008-11-14 10:39:19 +11004577
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004578 isec->sclass = sclass;
4579 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004580 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004582 if (sock->sk) {
4583 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004584 sksec->sclass = sclass;
4585 sksec->sid = sid;
Richard Hainesd4529302018-02-13 20:57:18 +00004586 /* Allows detection of the first association on this socket */
4587 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4588 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4589
Paul Moore389fb8002009-03-27 17:10:34 -04004590 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004591 }
4592
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004593 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594}
4595
David Herrmann0b811db2018-05-04 16:28:21 +02004596static int selinux_socket_socketpair(struct socket *socka,
4597 struct socket *sockb)
4598{
4599 struct sk_security_struct *sksec_a = socka->sk->sk_security;
4600 struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4601
4602 sksec_a->peer_sid = sksec_b->sid;
4603 sksec_b->peer_sid = sksec_a->sid;
4604
4605 return 0;
4606}
4607
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608/* Range of port numbers used to automatically bind.
4609 Need to determine whether we should perform a name_bind
4610 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611
4612static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4613{
Paul Moore253bfae2010-04-22 14:46:19 -04004614 struct sock *sk = sock->sk;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004615 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 u16 family;
4617 int err;
4618
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004619 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620 if (err)
4621 goto out;
4622
Richard Hainesd4529302018-02-13 20:57:18 +00004623 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
Paul Moore253bfae2010-04-22 14:46:19 -04004624 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 if (family == PF_INET || family == PF_INET6) {
4626 char *addrp;
Thomas Liu2bf49692009-07-14 12:14:09 -04004627 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004628 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 struct sockaddr_in *addr4 = NULL;
4630 struct sockaddr_in6 *addr6 = NULL;
Tetsuo Handac750e692019-04-12 19:59:34 +09004631 u16 family_sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004633 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634
Richard Hainesd4529302018-02-13 20:57:18 +00004635 /*
4636 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4637 * that validates multiple binding addresses. Because of this
4638 * need to check address->sa_family as it is possible to have
4639 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4640 */
Tetsuo Handac750e692019-04-12 19:59:34 +09004641 if (addrlen < offsetofend(struct sockaddr, sa_family))
4642 return -EINVAL;
4643 family_sa = address->sa_family;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004644 switch (family_sa) {
4645 case AF_UNSPEC:
Richard Haines68741a8a2018-03-02 19:54:34 +00004646 case AF_INET:
4647 if (addrlen < sizeof(struct sockaddr_in))
4648 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 addr4 = (struct sockaddr_in *)address;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004650 if (family_sa == AF_UNSPEC) {
4651 /* see __inet_bind(), we only want to allow
4652 * AF_UNSPEC if the address is INADDR_ANY
4653 */
4654 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4655 goto err_af;
4656 family_sa = AF_INET;
4657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 addrp = (char *)&addr4->sin_addr.s_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004660 break;
4661 case AF_INET6:
4662 if (addrlen < SIN6_LEN_RFC2133)
4663 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664 addr6 = (struct sockaddr_in6 *)address;
4665 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666 addrp = (char *)&addr6->sin6_addr.s6_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004667 break;
4668 default:
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004669 goto err_af;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 }
4671
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004672 ad.type = LSM_AUDIT_DATA_NET;
4673 ad.u.net = &net;
4674 ad.u.net->sport = htons(snum);
4675 ad.u.net->family = family_sa;
4676
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004677 if (snum) {
4678 int low, high;
4679
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004680 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004681
Maciej Żenczykowski82f31eb2019-11-25 15:37:04 -08004682 if (inet_port_requires_bind_service(sock_net(sk), snum) ||
4683 snum < low || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004684 err = sel_netport_sid(sk->sk_protocol,
4685 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004686 if (err)
4687 goto out;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004688 err = avc_has_perm(sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004689 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004690 SOCKET__NAME_BIND, &ad);
4691 if (err)
4692 goto out;
4693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694 }
Eric Paris828dfe12008-04-17 13:17:49 -04004695
Paul Moore253bfae2010-04-22 14:46:19 -04004696 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004697 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698 node_perm = TCP_SOCKET__NODE_BIND;
4699 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004700
James Morris13402582005-09-30 14:24:34 -04004701 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702 node_perm = UDP_SOCKET__NODE_BIND;
4703 break;
James Morris2ee92d42006-11-13 16:09:01 -08004704
4705 case SECCLASS_DCCP_SOCKET:
4706 node_perm = DCCP_SOCKET__NODE_BIND;
4707 break;
4708
Richard Hainesd4529302018-02-13 20:57:18 +00004709 case SECCLASS_SCTP_SOCKET:
4710 node_perm = SCTP_SOCKET__NODE_BIND;
4711 break;
4712
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713 default:
4714 node_perm = RAWIP_SOCKET__NODE_BIND;
4715 break;
4716 }
Eric Paris828dfe12008-04-17 13:17:49 -04004717
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004718 err = sel_netnode_sid(addrp, family_sa, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719 if (err)
4720 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004721
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004722 if (family_sa == AF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004723 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724 else
Eric Paris48c62af2012-04-02 13:15:44 -04004725 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
Stephen Smalleye67b7982023-03-09 13:30:37 -05004727 err = avc_has_perm(sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004728 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729 if (err)
4730 goto out;
4731 }
4732out:
4733 return err;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004734err_af:
4735 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4736 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4737 return -EINVAL;
4738 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739}
4740
Richard Hainesd4529302018-02-13 20:57:18 +00004741/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
Kees Cookd61330c2019-02-17 14:08:36 -08004742 * and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
Richard Hainesd4529302018-02-13 20:57:18 +00004743 */
4744static int selinux_socket_connect_helper(struct socket *sock,
4745 struct sockaddr *address, int addrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746{
Paul Moore014ab192008-10-10 10:16:33 -04004747 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004748 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749 int err;
4750
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004751 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 if (err)
4753 return err;
Paolo Abeni05174c92019-05-10 19:12:33 +02004754 if (addrlen < offsetofend(struct sockaddr, sa_family))
4755 return -EINVAL;
4756
4757 /* connect(AF_UNSPEC) has special handling, as it is a documented
4758 * way to disconnect the socket
4759 */
4760 if (address->sa_family == AF_UNSPEC)
4761 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
4763 /*
Richard Hainesd4529302018-02-13 20:57:18 +00004764 * If a TCP, DCCP or SCTP socket, check name_connect permission
4765 * for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766 */
Paul Moore253bfae2010-04-22 14:46:19 -04004767 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004768 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4769 sksec->sclass == SECCLASS_SCTP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004770 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004771 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 struct sockaddr_in *addr4 = NULL;
4773 struct sockaddr_in6 *addr6 = NULL;
4774 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004775 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776
Richard Hainesd4529302018-02-13 20:57:18 +00004777 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4778 * that validates multiple connect addresses. Because of this
4779 * need to check address->sa_family as it is possible to have
4780 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4781 */
Richard Haines68741a8a2018-03-02 19:54:34 +00004782 switch (address->sa_family) {
4783 case AF_INET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004784 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004785 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786 return -EINVAL;
4787 snum = ntohs(addr4->sin_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004788 break;
4789 case AF_INET6:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004791 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792 return -EINVAL;
4793 snum = ntohs(addr6->sin6_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004794 break;
4795 default:
4796 /* Note that SCTP services expect -EINVAL, whereas
4797 * others expect -EAFNOSUPPORT.
4798 */
4799 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4800 return -EINVAL;
4801 else
4802 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803 }
4804
Paul Moore3e112172008-04-10 10:48:14 -04004805 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004807 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808
Richard Hainesd4529302018-02-13 20:57:18 +00004809 switch (sksec->sclass) {
4810 case SECCLASS_TCP_SOCKET:
4811 perm = TCP_SOCKET__NAME_CONNECT;
4812 break;
4813 case SECCLASS_DCCP_SOCKET:
4814 perm = DCCP_SOCKET__NAME_CONNECT;
4815 break;
4816 case SECCLASS_SCTP_SOCKET:
4817 perm = SCTP_SOCKET__NAME_CONNECT;
4818 break;
4819 }
James Morris2ee92d42006-11-13 16:09:01 -08004820
Eric Paris50c205f2012-04-04 15:01:43 -04004821 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004822 ad.u.net = &net;
4823 ad.u.net->dport = htons(snum);
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004824 ad.u.net->family = address->sa_family;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004825 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004827 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 }
4829
Richard Hainesd4529302018-02-13 20:57:18 +00004830 return 0;
4831}
Paul Moore014ab192008-10-10 10:16:33 -04004832
Richard Hainesd4529302018-02-13 20:57:18 +00004833/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4834static int selinux_socket_connect(struct socket *sock,
4835 struct sockaddr *address, int addrlen)
4836{
4837 int err;
4838 struct sock *sk = sock->sk;
4839
4840 err = selinux_socket_connect_helper(sock, address, addrlen);
4841 if (err)
4842 return err;
4843
4844 return selinux_netlbl_socket_connect(sk, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845}
4846
4847static int selinux_socket_listen(struct socket *sock, int backlog)
4848{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004849 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850}
4851
4852static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4853{
4854 int err;
4855 struct inode_security_struct *isec;
4856 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004857 u16 sclass;
4858 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004860 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861 if (err)
4862 return err;
4863
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004864 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004865 spin_lock(&isec->lock);
4866 sclass = isec->sclass;
4867 sid = isec->sid;
4868 spin_unlock(&isec->lock);
4869
4870 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4871 newisec->sclass = sclass;
4872 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004873 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004874
4875 return 0;
4876}
4877
4878static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004879 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004880{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004881 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882}
4883
4884static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4885 int size, int flags)
4886{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004887 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888}
4889
4890static int selinux_socket_getsockname(struct socket *sock)
4891{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004892 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893}
4894
4895static int selinux_socket_getpeername(struct socket *sock)
4896{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004897 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898}
4899
Eric Paris828dfe12008-04-17 13:17:49 -04004900static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901{
Paul Mooref8687af2006-10-30 15:22:15 -08004902 int err;
4903
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004904 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004905 if (err)
4906 return err;
4907
4908 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909}
4910
4911static int selinux_socket_getsockopt(struct socket *sock, int level,
4912 int optname)
4913{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004914 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004915}
4916
4917static int selinux_socket_shutdown(struct socket *sock, int how)
4918{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004919 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920}
4921
David S. Miller3610cda2011-01-05 15:38:53 -08004922static int selinux_socket_unix_stream_connect(struct sock *sock,
4923 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 struct sock *newsk)
4925{
David S. Miller3610cda2011-01-05 15:38:53 -08004926 struct sk_security_struct *sksec_sock = sock->sk_security;
4927 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004928 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004929 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004930 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931 int err;
4932
Eric Paris50c205f2012-04-04 15:01:43 -04004933 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004934 ad.u.net = &net;
4935 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936
Stephen Smalleye67b7982023-03-09 13:30:37 -05004937 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
Paul Moore4d1e2452010-04-22 14:46:18 -04004938 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4940 if (err)
4941 return err;
4942
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004944 sksec_new->peer_sid = sksec_sock->sid;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004945 err = security_sid_mls_copy(sksec_other->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004946 sksec_sock->sid, &sksec_new->sid);
Paul Moore4d1e2452010-04-22 14:46:18 -04004947 if (err)
4948 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004949
Paul Moore4d1e2452010-04-22 14:46:18 -04004950 /* connecting socket */
4951 sksec_sock->peer_sid = sksec_new->sid;
4952
4953 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004954}
4955
4956static int selinux_socket_unix_may_send(struct socket *sock,
4957 struct socket *other)
4958{
Paul Moore253bfae2010-04-22 14:46:19 -04004959 struct sk_security_struct *ssec = sock->sk->sk_security;
4960 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004961 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004962 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963
Eric Paris50c205f2012-04-04 15:01:43 -04004964 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004965 ad.u.net = &net;
4966 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967
Stephen Smalleye67b7982023-03-09 13:30:37 -05004968 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
Paul Moore253bfae2010-04-22 14:46:19 -04004969 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970}
4971
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004972static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4973 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004974 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004975{
4976 int err;
4977 u32 if_sid;
4978 u32 node_sid;
4979
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004980 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004981 if (err)
4982 return err;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004983 err = avc_has_perm(peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004984 SECCLASS_NETIF, NETIF__INGRESS, ad);
4985 if (err)
4986 return err;
4987
4988 err = sel_netnode_sid(addrp, family, &node_sid);
4989 if (err)
4990 return err;
Stephen Smalleye67b7982023-03-09 13:30:37 -05004991 return avc_has_perm(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 Smalleye67b7982023-03-09 13:30:37 -05005014 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04005015 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04005016 if (err)
5017 return err;
5018 }
Paul Moore220deb92008-01-29 08:38:23 -05005019
Steffen Klassertb9679a72011-02-23 12:55:21 +01005020 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
5021 if (err)
5022 return err;
5023 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005024
James Morris4e5ab4c2006-06-09 00:33:33 -07005025 return err;
5026}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005027
James Morris4e5ab4c2006-06-09 00:33:33 -07005028static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
5029{
Christian Göttschea13479b2023-07-06 15:23:27 +02005030 int err, peerlbl_active, secmark_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005031 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05005032 u16 family = sk->sk_family;
5033 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005034 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005035 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05005036 char *addrp;
James Morris4e5ab4c2006-06-09 00:33:33 -07005037
James Morris4e5ab4c2006-06-09 00:33:33 -07005038 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05005039 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07005040
5041 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00005042 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07005043 family = PF_INET;
5044
Paul Moored8395c82008-10-10 10:16:30 -04005045 /* If any sort of compatibility mode is enabled then handoff processing
5046 * to the selinux_sock_rcv_skb_compat() function to deal with the
5047 * special handling. We do this in an attempt to keep this function
5048 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005049 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005050 return selinux_sock_rcv_skb_compat(sk, skb, family);
5051
5052 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005053 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04005054 if (!secmark_active && !peerlbl_active)
5055 return 0;
5056
Eric Paris50c205f2012-04-04 15:01:43 -04005057 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005058 ad.u.net = &net;
5059 ad.u.net->netif = skb->skb_iif;
5060 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05005061 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07005062 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05005063 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07005064
Paul Moored8395c82008-10-10 10:16:30 -04005065 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05005066 u32 peer_sid;
5067
5068 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
5069 if (err)
5070 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005071 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
5072 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005073 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005074 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005075 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04005076 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05005077 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
Paul Moored621d352008-01-29 08:43:36 -05005078 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05005079 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005080 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05005081 return err;
5082 }
Paul Moored621d352008-01-29 08:43:36 -05005083 }
5084
Paul Moored8395c82008-10-10 10:16:30 -04005085 if (secmark_active) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05005086 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005087 PACKET__RECV, &ad);
5088 if (err)
5089 return err;
5090 }
5091
Paul Moored621d352008-01-29 08:43:36 -05005092 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093}
5094
Paul Mooreb10b9c32022-10-10 12:31:21 -04005095static int selinux_socket_getpeersec_stream(struct socket *sock,
5096 sockptr_t optval, sockptr_t optlen,
5097 unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098{
5099 int err = 0;
Paul Mooreb10b9c32022-10-10 12:31:21 -04005100 char *scontext = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04005102 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05005103 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104
Paul Moore253bfae2010-04-22 14:46:19 -04005105 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00005106 sksec->sclass == SECCLASS_TCP_SOCKET ||
5107 sksec->sclass == SECCLASS_SCTP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04005108 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04005109 if (peer_sid == SECSID_NULL)
5110 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111
Stephen Smalleye67b7982023-03-09 13:30:37 -05005112 err = security_sid_to_context(peer_sid, &scontext,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005113 &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04005115 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116 if (scontext_len > len) {
5117 err = -ERANGE;
5118 goto out_len;
5119 }
5120
Paul Mooreb10b9c32022-10-10 12:31:21 -04005121 if (copy_to_sockptr(optval, scontext, scontext_len))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123out_len:
Paul Mooreb10b9c32022-10-10 12:31:21 -04005124 if (copy_to_sockptr(optlen, &scontext_len, sizeof(scontext_len)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 return err;
5128}
5129
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005130static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005131{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005132 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05005133 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04005134 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07005135
Paul Mooreaa862902008-10-10 10:16:29 -04005136 if (skb && skb->protocol == htons(ETH_P_IP))
5137 family = PF_INET;
5138 else if (skb && skb->protocol == htons(ETH_P_IPV6))
5139 family = PF_INET6;
5140 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05005141 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05005142 else
5143 goto out;
5144
Paul Moore899134f2016-03-28 15:19:10 -04005145 if (sock && family == PF_UNIX) {
5146 isec = inode_security_novalidate(SOCK_INODE(sock));
5147 peer_secid = isec->sid;
5148 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05005149 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005150
Paul Moore75e22912008-01-29 08:38:04 -05005151out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005152 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05005153 if (peer_secid == SECSID_NULL)
5154 return -EINVAL;
5155 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005156}
5157
Al Viro7d877f32005-10-21 03:20:43 -04005158static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159{
Paul Moore84914b72010-04-22 14:46:18 -04005160 struct sk_security_struct *sksec;
5161
5162 sksec = kzalloc(sizeof(*sksec), priority);
5163 if (!sksec)
5164 return -ENOMEM;
5165
5166 sksec->peer_sid = SECINITSID_UNLABELED;
5167 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04005168 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04005169 selinux_netlbl_sk_security_reset(sksec);
5170 sk->sk_security = sksec;
5171
5172 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173}
5174
5175static void selinux_sk_free_security(struct sock *sk)
5176{
Paul Moore84914b72010-04-22 14:46:18 -04005177 struct sk_security_struct *sksec = sk->sk_security;
5178
5179 sk->sk_security = NULL;
5180 selinux_netlbl_sk_security_free(sksec);
5181 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182}
5183
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005184static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
5185{
Eric Parisdd3e7832010-04-07 15:08:46 -04005186 struct sk_security_struct *sksec = sk->sk_security;
5187 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005188
Eric Parisdd3e7832010-04-07 15:08:46 -04005189 newsksec->sid = sksec->sid;
5190 newsksec->peer_sid = sksec->peer_sid;
5191 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07005192
Eric Parisdd3e7832010-04-07 15:08:46 -04005193 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005194}
5195
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005196static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005197{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005198 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005199 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005200 else {
5201 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005202
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005203 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005204 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005205}
5206
Eric Paris828dfe12008-04-17 13:17:49 -04005207static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005208{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05005209 struct inode_security_struct *isec =
5210 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005211 struct sk_security_struct *sksec = sk->sk_security;
5212
Paul Moore2873ead2014-07-28 10:42:48 -04005213 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5214 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07005215 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05005216 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005217}
5218
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005219/*
5220 * Determines peer_secid for the asoc and updates socket's peer label
5221 * if it's the first association on the socket.
Richard Hainesd4529302018-02-13 20:57:18 +00005222 */
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005223static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
5224 struct sk_buff *skb)
Richard Hainesd4529302018-02-13 20:57:18 +00005225{
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005226 struct sock *sk = asoc->base.sk;
5227 u16 family = sk->sk_family;
5228 struct sk_security_struct *sksec = sk->sk_security;
Richard Hainesd4529302018-02-13 20:57:18 +00005229 struct common_audit_data ad;
5230 struct lsm_network_audit net = {0,};
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005231 int err;
Richard Hainesd4529302018-02-13 20:57:18 +00005232
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005233 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5234 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5235 family = PF_INET;
Richard Hainesd4529302018-02-13 20:57:18 +00005236
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005237 if (selinux_peerlbl_enabled()) {
5238 asoc->peer_secid = SECSID_NULL;
Richard Hainesd4529302018-02-13 20:57:18 +00005239
Richard Hainesd4529302018-02-13 20:57:18 +00005240 /* This will return peer_sid = SECSID_NULL if there are
5241 * no peer labels, see security_net_peersid_resolve().
5242 */
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005243 err = selinux_skb_peerlbl_sid(skb, family, &asoc->peer_secid);
Richard Hainesd4529302018-02-13 20:57:18 +00005244 if (err)
5245 return err;
5246
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005247 if (asoc->peer_secid == SECSID_NULL)
5248 asoc->peer_secid = SECINITSID_UNLABELED;
5249 } else {
5250 asoc->peer_secid = SECINITSID_UNLABELED;
Richard Hainesd4529302018-02-13 20:57:18 +00005251 }
5252
5253 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5254 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5255
5256 /* Here as first association on socket. As the peer SID
5257 * was allowed by peer recv (and the netif/node checks),
5258 * then it is approved by policy and used as the primary
5259 * peer SID for getpeercon(3).
5260 */
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005261 sksec->peer_sid = asoc->peer_secid;
5262 } else if (sksec->peer_sid != asoc->peer_secid) {
Richard Hainesd4529302018-02-13 20:57:18 +00005263 /* Other association peer SIDs are checked to enforce
5264 * consistency among the peer SIDs.
5265 */
5266 ad.type = LSM_AUDIT_DATA_NET;
5267 ad.u.net = &net;
Xin Longc081d532021-11-02 08:02:47 -04005268 ad.u.net->sk = asoc->base.sk;
Stephen Smalleye67b7982023-03-09 13:30:37 -05005269 err = avc_has_perm(sksec->peer_sid, asoc->peer_secid,
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005270 sksec->sclass, SCTP_SOCKET__ASSOCIATION,
5271 &ad);
Richard Hainesd4529302018-02-13 20:57:18 +00005272 if (err)
5273 return err;
5274 }
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005275 return 0;
5276}
5277
5278/* Called whenever SCTP receives an INIT or COOKIE ECHO chunk. This
5279 * happens on an incoming connect(2), sctp_connectx(3) or
5280 * sctp_sendmsg(3) (with no association already present).
5281 */
5282static int selinux_sctp_assoc_request(struct sctp_association *asoc,
5283 struct sk_buff *skb)
5284{
5285 struct sk_security_struct *sksec = asoc->base.sk->sk_security;
5286 u32 conn_sid;
5287 int err;
5288
5289 if (!selinux_policycap_extsockclass())
5290 return 0;
5291
5292 err = selinux_sctp_process_new_assoc(asoc, skb);
5293 if (err)
5294 return err;
Richard Hainesd4529302018-02-13 20:57:18 +00005295
5296 /* Compute the MLS component for the connection and store
Xin Longc081d532021-11-02 08:02:47 -04005297 * the information in asoc. This will be used by SCTP TCP type
Richard Hainesd4529302018-02-13 20:57:18 +00005298 * sockets and peeled off connections as they cause a new
5299 * socket to be generated. selinux_sctp_sk_clone() will then
5300 * plug this into the new socket.
5301 */
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005302 err = selinux_conn_sid(sksec->sid, asoc->peer_secid, &conn_sid);
Richard Hainesd4529302018-02-13 20:57:18 +00005303 if (err)
5304 return err;
5305
Xin Longc081d532021-11-02 08:02:47 -04005306 asoc->secid = conn_sid;
Richard Hainesd4529302018-02-13 20:57:18 +00005307
5308 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
Xin Longc081d532021-11-02 08:02:47 -04005309 return selinux_netlbl_sctp_assoc_request(asoc, skb);
Richard Hainesd4529302018-02-13 20:57:18 +00005310}
5311
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01005312/* Called when SCTP receives a COOKIE ACK chunk as the final
5313 * response to an association request (initited by us).
5314 */
5315static int selinux_sctp_assoc_established(struct sctp_association *asoc,
5316 struct sk_buff *skb)
5317{
5318 struct sk_security_struct *sksec = asoc->base.sk->sk_security;
5319
5320 if (!selinux_policycap_extsockclass())
5321 return 0;
5322
5323 /* Inherit secid from the parent socket - this will be picked up
5324 * by selinux_sctp_sk_clone() if the association gets peeled off
5325 * into a new socket.
5326 */
5327 asoc->secid = sksec->sid;
5328
5329 return selinux_sctp_process_new_assoc(asoc, skb);
5330}
5331
Richard Hainesd4529302018-02-13 20:57:18 +00005332/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5333 * based on their @optname.
5334 */
5335static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5336 struct sockaddr *address,
5337 int addrlen)
5338{
5339 int len, err = 0, walk_size = 0;
5340 void *addr_buf;
5341 struct sockaddr *addr;
5342 struct socket *sock;
5343
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005344 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005345 return 0;
5346
5347 /* Process one or more addresses that may be IPv4 or IPv6 */
5348 sock = sk->sk_socket;
5349 addr_buf = address;
5350
5351 while (walk_size < addrlen) {
Ondrej Mosnacekc1383252018-11-13 16:16:08 +01005352 if (walk_size + sizeof(sa_family_t) > addrlen)
5353 return -EINVAL;
5354
Richard Hainesd4529302018-02-13 20:57:18 +00005355 addr = addr_buf;
5356 switch (addr->sa_family) {
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005357 case AF_UNSPEC:
Richard Hainesd4529302018-02-13 20:57:18 +00005358 case AF_INET:
5359 len = sizeof(struct sockaddr_in);
5360 break;
5361 case AF_INET6:
5362 len = sizeof(struct sockaddr_in6);
5363 break;
5364 default:
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005365 return -EINVAL;
Richard Hainesd4529302018-02-13 20:57:18 +00005366 }
5367
Xin Long292c9972019-03-09 00:07:34 +08005368 if (walk_size + len > addrlen)
5369 return -EINVAL;
5370
Richard Hainesd4529302018-02-13 20:57:18 +00005371 err = -EINVAL;
5372 switch (optname) {
5373 /* Bind checks */
5374 case SCTP_PRIMARY_ADDR:
5375 case SCTP_SET_PEER_PRIMARY_ADDR:
5376 case SCTP_SOCKOPT_BINDX_ADD:
5377 err = selinux_socket_bind(sock, addr, len);
5378 break;
5379 /* Connect checks */
5380 case SCTP_SOCKOPT_CONNECTX:
5381 case SCTP_PARAM_SET_PRIMARY:
5382 case SCTP_PARAM_ADD_IP:
5383 case SCTP_SENDMSG_CONNECT:
5384 err = selinux_socket_connect_helper(sock, addr, len);
5385 if (err)
5386 return err;
5387
5388 /* As selinux_sctp_bind_connect() is called by the
5389 * SCTP protocol layer, the socket is already locked,
Randy Dunlapc76a2f92020-08-07 09:51:34 -07005390 * therefore selinux_netlbl_socket_connect_locked()
Richard Hainesd4529302018-02-13 20:57:18 +00005391 * is called here. The situations handled are:
5392 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5393 * whenever a new IP address is added or when a new
5394 * primary address is selected.
5395 * Note that an SCTP connect(2) call happens before
5396 * the SCTP protocol layer and is handled via
5397 * selinux_socket_connect().
5398 */
5399 err = selinux_netlbl_socket_connect_locked(sk, addr);
5400 break;
5401 }
5402
5403 if (err)
5404 return err;
5405
5406 addr_buf += len;
5407 walk_size += len;
5408 }
5409
5410 return 0;
5411}
5412
5413/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
Xin Longc081d532021-11-02 08:02:47 -04005414static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
Richard Hainesd4529302018-02-13 20:57:18 +00005415 struct sock *newsk)
5416{
5417 struct sk_security_struct *sksec = sk->sk_security;
5418 struct sk_security_struct *newsksec = newsk->sk_security;
5419
5420 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5421 * the non-sctp clone version.
5422 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005423 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005424 return selinux_sk_clone_security(sk, newsk);
5425
Paul Moore32a370a2021-11-12 12:07:02 -05005426 newsksec->sid = asoc->secid;
Xin Longc081d532021-11-02 08:02:47 -04005427 newsksec->peer_sid = asoc->peer_secid;
Richard Hainesd4529302018-02-13 20:57:18 +00005428 newsksec->sclass = sksec->sclass;
5429 selinux_netlbl_sctp_sk_clone(sk, newsk);
5430}
5431
Paolo Abeni85c32222023-04-20 19:17:14 +02005432static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
5433{
5434 struct sk_security_struct *ssksec = ssk->sk_security;
5435 struct sk_security_struct *sksec = sk->sk_security;
5436
5437 ssksec->sclass = sksec->sclass;
5438 ssksec->sid = sksec->sid;
5439
5440 /* replace the existing subflow label deleting the existing one
5441 * and re-recreating a new label using the updated context
5442 */
5443 selinux_netlbl_sk_security_free(ssksec);
5444 return selinux_netlbl_socket_post_create(ssk, ssk->sk_family);
5445}
5446
Florian Westphal41dd9592020-11-30 16:36:29 +01005447static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
Adrian Bunk9a673e52006-08-15 00:03:53 -07005448 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005449{
5450 struct sk_security_struct *sksec = sk->sk_security;
5451 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05005452 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05005453 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005454 u32 peersid;
5455
Paul Mooreaa862902008-10-10 10:16:29 -04005456 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05005457 if (err)
5458 return err;
Paul Moore446b8022013-12-04 16:10:51 -05005459 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5460 if (err)
5461 return err;
5462 req->secid = connsid;
5463 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07005464
Paul Moore389fb8002009-03-27 17:10:34 -04005465 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005466}
5467
Adrian Bunk9a673e52006-08-15 00:03:53 -07005468static void selinux_inet_csk_clone(struct sock *newsk,
5469 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005470{
5471 struct sk_security_struct *newsksec = newsk->sk_security;
5472
5473 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005474 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005475 /* NOTE: Ideally, we should also get the isec->sid for the
5476 new socket in sync, but we don't have the isec available yet.
5477 So we will wait until sock_graft to do it, by which
5478 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07005479
Paul Moore9f2ad662006-11-17 17:38:53 -05005480 /* We don't need to take any sort of lock here as we are the only
5481 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04005482 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005483}
5484
Paul Moore014ab192008-10-10 10:16:33 -04005485static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005486{
Paul Mooreaa862902008-10-10 10:16:29 -04005487 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005488 struct sk_security_struct *sksec = sk->sk_security;
5489
Paul Mooreaa862902008-10-10 10:16:29 -04005490 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5491 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5492 family = PF_INET;
5493
5494 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005495}
5496
Eric Paris2606fd12010-10-13 16:24:41 -04005497static int selinux_secmark_relabel_packet(u32 sid)
5498{
Christian Göttschea13479b2023-07-06 15:23:27 +02005499 const struct task_security_struct *tsec;
Eric Paris2606fd12010-10-13 16:24:41 -04005500 u32 tsid;
5501
Christian Göttschea13479b2023-07-06 15:23:27 +02005502 tsec = selinux_cred(current_cred());
5503 tsid = tsec->sid;
Eric Paris2606fd12010-10-13 16:24:41 -04005504
Stephen Smalleye67b7982023-03-09 13:30:37 -05005505 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005506 NULL);
Eric Paris2606fd12010-10-13 16:24:41 -04005507}
5508
5509static void selinux_secmark_refcount_inc(void)
5510{
5511 atomic_inc(&selinux_secmark_refcount);
5512}
5513
5514static void selinux_secmark_refcount_dec(void)
5515{
5516 atomic_dec(&selinux_secmark_refcount);
5517}
5518
Adrian Bunk9a673e52006-08-15 00:03:53 -07005519static void selinux_req_classify_flow(const struct request_sock *req,
Paul Moore3df98d72020-09-27 22:38:26 -04005520 struct flowi_common *flic)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005521{
Paul Moore3df98d72020-09-27 22:38:26 -04005522 flic->flowic_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005523}
5524
Paul Moore5dbbaf22013-01-14 07:12:19 +00005525static int selinux_tun_dev_alloc_security(void **security)
5526{
5527 struct tun_security_struct *tunsec;
5528
5529 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5530 if (!tunsec)
5531 return -ENOMEM;
5532 tunsec->sid = current_sid();
5533
5534 *security = tunsec;
5535 return 0;
5536}
5537
5538static void selinux_tun_dev_free_security(void *security)
5539{
5540 kfree(security);
5541}
5542
Paul Mooreed6d76e2009-08-28 18:12:49 -04005543static int selinux_tun_dev_create(void)
5544{
5545 u32 sid = current_sid();
5546
5547 /* we aren't taking into account the "sockcreate" SID since the socket
5548 * that is being created here is not a socket in the traditional sense,
5549 * instead it is a private sock, accessible only to the kernel, and
5550 * representing a wide range of network traffic spanning multiple
5551 * connections unlike traditional sockets - check the TUN driver to
5552 * get a better understanding of why this socket is special */
5553
Stephen Smalleye67b7982023-03-09 13:30:37 -05005554 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005555 NULL);
5556}
5557
Paul Moore5dbbaf22013-01-14 07:12:19 +00005558static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005559{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005560 struct tun_security_struct *tunsec = security;
5561
Stephen Smalleye67b7982023-03-09 13:30:37 -05005562 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005563 TUN_SOCKET__ATTACH_QUEUE, NULL);
5564}
5565
5566static int selinux_tun_dev_attach(struct sock *sk, void *security)
5567{
5568 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005569 struct sk_security_struct *sksec = sk->sk_security;
5570
5571 /* we don't currently perform any NetLabel based labeling here and it
5572 * isn't clear that we would want to do so anyway; while we could apply
5573 * labeling without the support of the TUN user the resulting labeled
5574 * traffic from the other end of the connection would almost certainly
5575 * cause confusion to the TUN user that had no idea network labeling
5576 * protocols were being used */
5577
Paul Moore5dbbaf22013-01-14 07:12:19 +00005578 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005579 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005580
5581 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005582}
5583
Paul Moore5dbbaf22013-01-14 07:12:19 +00005584static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005585{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005586 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005587 u32 sid = current_sid();
5588 int err;
5589
Stephen Smalleye67b7982023-03-09 13:30:37 -05005590 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005591 TUN_SOCKET__RELABELFROM, NULL);
5592 if (err)
5593 return err;
Stephen Smalleye67b7982023-03-09 13:30:37 -05005594 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005595 TUN_SOCKET__RELABELTO, NULL);
5596 if (err)
5597 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005598 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005599
5600 return 0;
5601}
5602
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603#ifdef CONFIG_NETFILTER
5604
Florian Westphal4342f702021-10-11 22:22:29 +02005605static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
5606 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607{
Paul Moore1d1e1de2021-10-11 17:50:48 -04005608 int ifindex;
5609 u16 family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005610 char *addrp;
5611 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005612 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005613 struct lsm_network_audit net = {0,};
Paul Moore1d1e1de2021-10-11 17:50:48 -04005614 int secmark_active, peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005615
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005616 if (!selinux_policycap_netpeer())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005617 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005618
Paul Mooreeffad8d2008-01-29 08:49:27 -05005619 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005620 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005621 if (!secmark_active && !peerlbl_active)
5622 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005623
Paul Moore1d1e1de2021-10-11 17:50:48 -04005624 family = state->pf;
Paul Moored8395c82008-10-10 10:16:30 -04005625 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5626 return NF_DROP;
5627
Paul Moore1d1e1de2021-10-11 17:50:48 -04005628 ifindex = state->in->ifindex;
Eric Paris50c205f2012-04-04 15:01:43 -04005629 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005630 ad.u.net = &net;
Paul Moore1d1e1de2021-10-11 17:50:48 -04005631 ad.u.net->netif = ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005632 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005633 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5634 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
Paul Mooredfaebe92008-10-10 10:16:31 -04005636 if (peerlbl_active) {
Paul Moore1d1e1de2021-10-11 17:50:48 -04005637 int err;
5638
5639 err = selinux_inet_sys_rcv_skb(state->net, ifindex,
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005640 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005641 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005642 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005643 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005644 }
5645 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005646
5647 if (secmark_active)
Stephen Smalleye67b7982023-03-09 13:30:37 -05005648 if (avc_has_perm(peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005649 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5650 return NF_DROP;
5651
Paul Moore1d1e1de2021-10-11 17:50:48 -04005652 if (netlbl_enabled())
Paul Moore948bf852008-10-10 10:16:32 -04005653 /* we do this in the FORWARD path and not the POST_ROUTING
5654 * path because we want to make sure we apply the necessary
5655 * labeling before IPsec is applied so we can leverage AH
5656 * protection */
5657 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5658 return NF_DROP;
5659
Paul Mooreeffad8d2008-01-29 08:49:27 -05005660 return NF_ACCEPT;
5661}
5662
Florian Westphal4342f702021-10-11 22:22:29 +02005663static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
5664 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005665{
Paul Moore47180062013-12-04 16:10:45 -05005666 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005667 u32 sid;
5668
5669 if (!netlbl_enabled())
5670 return NF_ACCEPT;
5671
5672 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5673 * because we want to make sure we apply the necessary labeling
5674 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005675 sk = skb->sk;
5676 if (sk) {
5677 struct sk_security_struct *sksec;
5678
Eric Dumazete446f9d2015-10-08 05:01:55 -07005679 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005680 /* if the socket is the listening state then this
5681 * packet is a SYN-ACK packet which means it needs to
5682 * be labeled based on the connection/request_sock and
5683 * not the parent socket. unfortunately, we can't
5684 * lookup the request_sock yet as it isn't queued on
5685 * the parent socket until after the SYN-ACK is sent.
5686 * the "solution" is to simply pass the packet as-is
5687 * as any IP option based labeling should be copied
5688 * from the initial connection request (in the IP
5689 * layer). it is far from ideal, but until we get a
5690 * security label in the packet itself this is the
5691 * best we can do. */
5692 return NF_ACCEPT;
5693
5694 /* standard practice, label using the parent socket */
5695 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005696 sid = sksec->sid;
5697 } else
5698 sid = SECINITSID_KERNEL;
Paul Moore1d1e1de2021-10-11 17:50:48 -04005699 if (selinux_netlbl_skbuff_setsid(skb, state->pf, sid) != 0)
Paul Moore948bf852008-10-10 10:16:32 -04005700 return NF_DROP;
5701
5702 return NF_ACCEPT;
5703}
5704
Huw Davies2917f572016-06-27 15:06:15 -04005705
Paul Mooreeffad8d2008-01-29 08:49:27 -05005706static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
Paul Moore1d1e1de2021-10-11 17:50:48 -04005707 const struct nf_hook_state *state)
James Morris4e5ab4c2006-06-09 00:33:33 -07005708{
Paul Moore1d1e1de2021-10-11 17:50:48 -04005709 struct sock *sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005710 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005711 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005712 struct lsm_network_audit net = {0,};
Tom Rix732bc2f2021-12-24 07:07:39 -08005713 u8 proto = 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07005714
Paul Moore1d1e1de2021-10-11 17:50:48 -04005715 sk = skb_to_full_sk(skb);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005716 if (sk == NULL)
5717 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005718 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005719
Eric Paris50c205f2012-04-04 15:01:43 -04005720 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005721 ad.u.net = &net;
Paul Moore1d1e1de2021-10-11 17:50:48 -04005722 ad.u.net->netif = state->out->ifindex;
5723 ad.u.net->family = state->pf;
5724 if (selinux_parse_skb(skb, &ad, NULL, 0, &proto))
Paul Moored8395c82008-10-10 10:16:30 -04005725 return NF_DROP;
5726
Paul Moore58bfbb52009-03-27 17:10:41 -04005727 if (selinux_secmark_enabled())
Stephen Smalleye67b7982023-03-09 13:30:37 -05005728 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005729 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005730 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005731
Steffen Klassertb9679a72011-02-23 12:55:21 +01005732 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5733 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005734
Paul Mooreeffad8d2008-01-29 08:49:27 -05005735 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736}
5737
Florian Westphal4342f702021-10-11 22:22:29 +02005738static unsigned int selinux_ip_postroute(void *priv,
5739 struct sk_buff *skb,
5740 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741{
Paul Moore1d1e1de2021-10-11 17:50:48 -04005742 u16 family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005743 u32 secmark_perm;
5744 u32 peer_sid;
Paul Moore1d1e1de2021-10-11 17:50:48 -04005745 int ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005746 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005747 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005748 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005749 char *addrp;
Paul Moore1d1e1de2021-10-11 17:50:48 -04005750 int secmark_active, peerlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005751
Paul Mooreeffad8d2008-01-29 08:49:27 -05005752 /* If any sort of compatibility mode is enabled then handoff processing
5753 * to the selinux_ip_postroute_compat() function to deal with the
5754 * special handling. We do this in an attempt to keep this function
5755 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005756 if (!selinux_policycap_netpeer())
Paul Moore1d1e1de2021-10-11 17:50:48 -04005757 return selinux_ip_postroute_compat(skb, state);
Paul Moorec0828e52013-12-10 14:58:01 -05005758
Paul Mooreeffad8d2008-01-29 08:49:27 -05005759 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005760 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005761 if (!secmark_active && !peerlbl_active)
5762 return NF_ACCEPT;
5763
Eric Dumazet54abc682015-11-08 10:54:07 -08005764 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005765
Paul Mooreeffad8d2008-01-29 08:49:27 -05005766#ifdef CONFIG_XFRM
5767 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5768 * packet transformation so allow the packet to pass without any checks
5769 * since we'll have another chance to perform access control checks
5770 * when the packet is on it's final way out.
5771 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005772 * is NULL, in this case go ahead and apply access control.
5773 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5774 * TCP listening state we cannot wait until the XFRM processing
5775 * is done as we will miss out on the SA label if we do;
5776 * unfortunately, this means more work, but it is only once per
5777 * connection. */
5778 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005779 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005780 return NF_ACCEPT;
5781#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005782
Paul Moore1d1e1de2021-10-11 17:50:48 -04005783 family = state->pf;
Paul Moored8395c82008-10-10 10:16:30 -04005784 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005785 /* Without an associated socket the packet is either coming
5786 * from the kernel or it is being forwarded; check the packet
5787 * to determine which and if the packet is being forwarded
5788 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005789 if (skb->skb_iif) {
5790 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005791 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005792 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005793 } else {
5794 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005795 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005796 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005797 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005798 /* Locally generated packet but the associated socket is in the
5799 * listening state which means this is a SYN-ACK packet. In
5800 * this particular case the correct security label is assigned
5801 * to the connection/request_sock but unfortunately we can't
5802 * query the request_sock as it isn't queued on the parent
5803 * socket until after the SYN-ACK packet is sent; the only
5804 * viable choice is to regenerate the label like we do in
5805 * selinux_inet_conn_request(). See also selinux_ip_output()
5806 * for similar problems. */
5807 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005808 struct sk_security_struct *sksec;
5809
Eric Dumazete446f9d2015-10-08 05:01:55 -07005810 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005811 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5812 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005813 /* At this point, if the returned skb peerlbl is SECSID_NULL
5814 * and the packet has been through at least one XFRM
5815 * transformation then we must be dealing with the "final"
5816 * form of labeled IPsec packet; since we've already applied
5817 * all of our access controls on this packet we can safely
5818 * pass the packet. */
5819 if (skb_sid == SECSID_NULL) {
5820 switch (family) {
5821 case PF_INET:
5822 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5823 return NF_ACCEPT;
5824 break;
5825 case PF_INET6:
5826 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5827 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005828 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005829 default:
5830 return NF_DROP_ERR(-ECONNREFUSED);
5831 }
5832 }
Paul Moore446b8022013-12-04 16:10:51 -05005833 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5834 return NF_DROP;
5835 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005836 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005837 /* Locally generated packet, fetch the security label from the
5838 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005839 struct sk_security_struct *sksec = sk->sk_security;
5840 peer_sid = sksec->sid;
5841 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005842 }
5843
Paul Moore1d1e1de2021-10-11 17:50:48 -04005844 ifindex = state->out->ifindex;
Eric Paris50c205f2012-04-04 15:01:43 -04005845 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005846 ad.u.net = &net;
5847 ad.u.net->netif = ifindex;
5848 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005849 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005850 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005851
Paul Mooreeffad8d2008-01-29 08:49:27 -05005852 if (secmark_active)
Stephen Smalleye67b7982023-03-09 13:30:37 -05005853 if (avc_has_perm(peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005854 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005855 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005856
5857 if (peerlbl_active) {
5858 u32 if_sid;
5859 u32 node_sid;
5860
Paul Moore1d1e1de2021-10-11 17:50:48 -04005861 if (sel_netif_sid(state->net, ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005862 return NF_DROP;
Stephen Smalleye67b7982023-03-09 13:30:37 -05005863 if (avc_has_perm(peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005864 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005865 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005866
5867 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005868 return NF_DROP;
Stephen Smalleye67b7982023-03-09 13:30:37 -05005869 if (avc_has_perm(peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005870 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005871 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005872 }
5873
5874 return NF_ACCEPT;
5875}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876#endif /* CONFIG_NETFILTER */
5877
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5879{
Paul Moorefb739742020-04-28 09:59:02 -04005880 int rc = 0;
5881 unsigned int msg_len;
5882 unsigned int data_len = skb->len;
5883 unsigned char *data = skb->data;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005884 struct nlmsghdr *nlh;
5885 struct sk_security_struct *sksec = sk->sk_security;
Paul Moorefb739742020-04-28 09:59:02 -04005886 u16 sclass = sksec->sclass;
5887 u32 perm;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005888
Paul Moorefb739742020-04-28 09:59:02 -04005889 while (data_len >= nlmsg_total_size(0)) {
5890 nlh = (struct nlmsghdr *)data;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005891
Paul Moorefb739742020-04-28 09:59:02 -04005892 /* NOTE: the nlmsg_len field isn't reliably set by some netlink
5893 * users which means we can't reject skb's with bogus
5894 * length fields; our solution is to follow what
5895 * netlink_rcv_skb() does and simply skip processing at
5896 * messages with length fields that are clearly junk
5897 */
5898 if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
5899 return 0;
5900
5901 rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
5902 if (rc == 0) {
5903 rc = sock_has_perm(sk, perm);
5904 if (rc)
5905 return rc;
5906 } else if (rc == -EINVAL) {
5907 /* -EINVAL is a missing msg/perm mapping */
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005908 pr_warn_ratelimited("SELinux: unrecognized netlink"
Paul Moorefb739742020-04-28 09:59:02 -04005909 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5910 " pid=%d comm=%s\n",
5911 sk->sk_protocol, nlh->nlmsg_type,
5912 secclass_map[sclass - 1].name,
5913 task_pid_nr(current), current->comm);
Stephen Smalleye67b7982023-03-09 13:30:37 -05005914 if (enforcing_enabled() &&
5915 !security_get_allow_unknown())
Paul Moorefb739742020-04-28 09:59:02 -04005916 return rc;
5917 rc = 0;
5918 } else if (rc == -ENOENT) {
5919 /* -ENOENT is a missing socket/class mapping, ignore */
5920 rc = 0;
5921 } else {
5922 return rc;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005923 }
5924
Paul Moorefb739742020-04-28 09:59:02 -04005925 /* move to the next message after applying netlink padding */
5926 msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
5927 if (msg_len >= data_len)
5928 return 0;
5929 data_len -= msg_len;
5930 data += msg_len;
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005931 }
5932
Paul Moorefb739742020-04-28 09:59:02 -04005933 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934}
5935
Casey Schauflerecd5f822018-11-20 11:55:02 -08005936static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005938 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005939 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940}
5941
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005943 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005946 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005947 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948
Casey Schaufler7c653822018-09-21 17:19:45 -07005949 isec = selinux_ipc(ipc_perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Eric Paris50c205f2012-04-04 15:01:43 -04005951 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 ad.u.ipc_id = ipc_perms->key;
5953
Stephen Smalleye67b7982023-03-09 13:30:37 -05005954 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955}
5956
5957static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5958{
Huaisheng Yeb82f3f62020-01-10 17:58:56 +08005959 struct msg_security_struct *msec;
5960
5961 msec = selinux_msg_msg(msg);
5962 msec->sid = SECINITSID_UNLABELED;
5963
5964 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965}
5966
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967/* message queue security operations */
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005968static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005971 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005972 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973
Casey Schauflerecd5f822018-11-20 11:55:02 -08005974 isec = selinux_ipc(msq);
5975 ipc_init_security(isec, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
Eric Paris50c205f2012-04-04 15:01:43 -04005977 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005978 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979
Stephen Smalleye67b7982023-03-09 13:30:37 -05005980 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Xu Panda09b71ad2022-09-12 09:17:19 +00005981 MSGQ__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982}
5983
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005984static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005987 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005988 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989
Casey Schaufler7c653822018-09-21 17:19:45 -07005990 isec = selinux_ipc(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Eric Paris50c205f2012-04-04 15:01:43 -04005992 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005993 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994
Stephen Smalleye67b7982023-03-09 13:30:37 -05005995 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996 MSGQ__ASSOCIATE, &ad);
5997}
5998
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005999static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000{
Christian Göttschea13479b2023-07-06 15:23:27 +02006001 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Eric Paris828dfe12008-04-17 13:17:49 -04006003 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004 case IPC_INFO:
6005 case MSG_INFO:
6006 /* No specific object, just general system-wide information. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006007 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006008 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009 case IPC_STAT:
6010 case MSG_STAT:
Davidlohr Bueso23c8cec2018-04-10 16:35:30 -07006011 case MSG_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
6013 break;
6014 case IPC_SET:
6015 perms = MSGQ__SETATTR;
6016 break;
6017 case IPC_RMID:
6018 perms = MSGQ__DESTROY;
6019 break;
6020 default:
6021 return 0;
6022 }
6023
Christian Göttschea13479b2023-07-06 15:23:27 +02006024 return ipc_has_perm(msq, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025}
6026
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006027static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029 struct ipc_security_struct *isec;
6030 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006031 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006032 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033 int rc;
6034
Casey Schaufler7c653822018-09-21 17:19:45 -07006035 isec = selinux_ipc(msq);
6036 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
6038 /*
6039 * First time through, need to assign label to the message
6040 */
6041 if (msec->sid == SECINITSID_UNLABELED) {
6042 /*
6043 * Compute new sid based on current process and
6044 * message queue this message will be stored in
6045 */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006046 rc = security_transition_sid(sid, isec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006047 SECCLASS_MSG, NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048 if (rc)
6049 return rc;
6050 }
6051
Eric Paris50c205f2012-04-04 15:01:43 -04006052 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006053 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054
6055 /* Can this process write to the queue? */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006056 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057 MSGQ__WRITE, &ad);
6058 if (!rc)
6059 /* Can this process send the message */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006060 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
David Howells275bb412008-11-14 10:39:19 +11006061 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006062 if (!rc)
6063 /* Can the message be put in the queue? */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006064 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
David Howells275bb412008-11-14 10:39:19 +11006065 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
6067 return rc;
6068}
6069
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006070static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071 struct task_struct *target,
6072 long type, int mode)
6073{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074 struct ipc_security_struct *isec;
6075 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006076 struct common_audit_data ad;
Paul Moorea3727a82021-09-23 09:50:11 -04006077 u32 sid = task_sid_obj(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078 int rc;
6079
Casey Schaufler7c653822018-09-21 17:19:45 -07006080 isec = selinux_ipc(msq);
6081 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082
Eric Paris50c205f2012-04-04 15:01:43 -04006083 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006084 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085
Stephen Smalleye67b7982023-03-09 13:30:37 -05006086 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087 SECCLASS_MSGQ, MSGQ__READ, &ad);
6088 if (!rc)
Stephen Smalleye67b7982023-03-09 13:30:37 -05006089 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090 SECCLASS_MSG, MSG__RECEIVE, &ad);
6091 return rc;
6092}
6093
6094/* Shared Memory security operations */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006095static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006098 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006099 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Casey Schauflerecd5f822018-11-20 11:55:02 -08006101 isec = selinux_ipc(shp);
6102 ipc_init_security(isec, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
Eric Paris50c205f2012-04-04 15:01:43 -04006104 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006105 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106
Stephen Smalleye67b7982023-03-09 13:30:37 -05006107 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Xu Panda09b71ad2022-09-12 09:17:19 +00006108 SHM__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109}
6110
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006111static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006114 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006115 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116
Casey Schaufler7c653822018-09-21 17:19:45 -07006117 isec = selinux_ipc(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
Eric Paris50c205f2012-04-04 15:01:43 -04006119 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006120 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Stephen Smalleye67b7982023-03-09 13:30:37 -05006122 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123 SHM__ASSOCIATE, &ad);
6124}
6125
6126/* Note, at this point, shp is locked down */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006127static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128{
Christian Göttschea13479b2023-07-06 15:23:27 +02006129 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130
Eric Paris828dfe12008-04-17 13:17:49 -04006131 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132 case IPC_INFO:
6133 case SHM_INFO:
6134 /* No specific object, just general system-wide information. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006135 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006136 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137 case IPC_STAT:
6138 case SHM_STAT:
Davidlohr Buesoc21a6972018-04-10 16:35:23 -07006139 case SHM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 perms = SHM__GETATTR | SHM__ASSOCIATE;
6141 break;
6142 case IPC_SET:
6143 perms = SHM__SETATTR;
6144 break;
6145 case SHM_LOCK:
6146 case SHM_UNLOCK:
6147 perms = SHM__LOCK;
6148 break;
6149 case IPC_RMID:
6150 perms = SHM__DESTROY;
6151 break;
6152 default:
6153 return 0;
6154 }
6155
Christian Göttschea13479b2023-07-06 15:23:27 +02006156 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006157}
6158
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006159static int selinux_shm_shmat(struct kern_ipc_perm *shp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160 char __user *shmaddr, int shmflg)
6161{
6162 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
6164 if (shmflg & SHM_RDONLY)
6165 perms = SHM__READ;
6166 else
6167 perms = SHM__READ | SHM__WRITE;
6168
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006169 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006170}
6171
6172/* Semaphore security operations */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006173static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006176 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006177 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178
Casey Schauflerecd5f822018-11-20 11:55:02 -08006179 isec = selinux_ipc(sma);
6180 ipc_init_security(isec, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181
Eric Paris50c205f2012-04-04 15:01:43 -04006182 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006183 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006184
Stephen Smalleye67b7982023-03-09 13:30:37 -05006185 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Xu Panda09b71ad2022-09-12 09:17:19 +00006186 SEM__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187}
6188
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006189static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006192 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006193 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194
Casey Schaufler7c653822018-09-21 17:19:45 -07006195 isec = selinux_ipc(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196
Eric Paris50c205f2012-04-04 15:01:43 -04006197 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006198 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199
Stephen Smalleye67b7982023-03-09 13:30:37 -05006200 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201 SEM__ASSOCIATE, &ad);
6202}
6203
6204/* Note, at this point, sma is locked down */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006205static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206{
6207 int err;
6208 u32 perms;
6209
Eric Paris828dfe12008-04-17 13:17:49 -04006210 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211 case IPC_INFO:
6212 case SEM_INFO:
6213 /* No specific object, just general system-wide information. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006214 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006215 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216 case GETPID:
6217 case GETNCNT:
6218 case GETZCNT:
6219 perms = SEM__GETATTR;
6220 break;
6221 case GETVAL:
6222 case GETALL:
6223 perms = SEM__READ;
6224 break;
6225 case SETVAL:
6226 case SETALL:
6227 perms = SEM__WRITE;
6228 break;
6229 case IPC_RMID:
6230 perms = SEM__DESTROY;
6231 break;
6232 case IPC_SET:
6233 perms = SEM__SETATTR;
6234 break;
6235 case IPC_STAT:
6236 case SEM_STAT:
Davidlohr Buesoa280d6d2018-04-10 16:35:26 -07006237 case SEM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238 perms = SEM__GETATTR | SEM__ASSOCIATE;
6239 break;
6240 default:
6241 return 0;
6242 }
6243
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006244 err = ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245 return err;
6246}
6247
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006248static int selinux_sem_semop(struct kern_ipc_perm *sma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249 struct sembuf *sops, unsigned nsops, int alter)
6250{
6251 u32 perms;
6252
6253 if (alter)
6254 perms = SEM__READ | SEM__WRITE;
6255 else
6256 perms = SEM__READ;
6257
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006258 return ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259}
6260
6261static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6262{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263 u32 av = 0;
6264
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265 av = 0;
6266 if (flag & S_IRUGO)
6267 av |= IPC__UNIX_READ;
6268 if (flag & S_IWUGO)
6269 av |= IPC__UNIX_WRITE;
6270
6271 if (av == 0)
6272 return 0;
6273
Stephen Smalley6af963f2005-05-01 08:58:39 -07006274 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006275}
6276
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006277static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6278{
Casey Schaufler7c653822018-09-21 17:19:45 -07006279 struct ipc_security_struct *isec = selinux_ipc(ipcp);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006280 *secid = isec->sid;
6281}
6282
Eric Paris828dfe12008-04-17 13:17:49 -04006283static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006284{
6285 if (inode)
6286 inode_doinit_with_dentry(inode, dentry);
6287}
6288
6289static int selinux_getprocattr(struct task_struct *p,
Al Viroc8e477c2022-01-30 19:57:52 -05006290 const char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291{
David Howells275bb412008-11-14 10:39:19 +11006292 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00006293 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294 int error;
Al Viro04ff9702007-03-12 16:17:58 +00006295 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296
David Howells275bb412008-11-14 10:39:19 +11006297 rcu_read_lock();
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006298 __tsec = selinux_cred(__task_cred(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006300 if (current != p) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05006301 error = avc_has_perm(current_sid(), __tsec->sid,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006302 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6303 if (error)
6304 goto bad;
6305 }
6306
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11006308 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11006310 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11006312 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11006314 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006315 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11006316 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07006317 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11006318 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006319 else {
6320 error = -EINVAL;
6321 goto bad;
6322 }
David Howells275bb412008-11-14 10:39:19 +11006323 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006324
6325 if (!sid)
6326 return 0;
6327
Stephen Smalleye67b7982023-03-09 13:30:37 -05006328 error = security_sid_to_context(sid, value, &len);
Al Viro04ff9702007-03-12 16:17:58 +00006329 if (error)
6330 return error;
6331 return len;
David Howells275bb412008-11-14 10:39:19 +11006332
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006333bad:
David Howells275bb412008-11-14 10:39:19 +11006334 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006335 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336}
6337
Stephen Smalleyb21507e2017-01-09 10:07:31 -05006338static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006339{
6340 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11006341 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006342 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343 int error;
6344 char *str = value;
6345
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346 /*
6347 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006348 */
6349 if (!strcmp(name, "exec"))
Stephen Smalleye67b7982023-03-09 13:30:37 -05006350 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006351 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006352 else if (!strcmp(name, "fscreate"))
Stephen Smalleye67b7982023-03-09 13:30:37 -05006353 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006354 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006355 else if (!strcmp(name, "keycreate"))
Stephen Smalleye67b7982023-03-09 13:30:37 -05006356 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006357 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07006358 else if (!strcmp(name, "sockcreate"))
Stephen Smalleye67b7982023-03-09 13:30:37 -05006359 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006360 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361 else if (!strcmp(name, "current"))
Stephen Smalleye67b7982023-03-09 13:30:37 -05006362 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006363 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364 else
6365 error = -EINVAL;
6366 if (error)
6367 return error;
6368
6369 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05006370 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006371 if (str[size-1] == '\n') {
6372 str[size-1] = 0;
6373 size--;
6374 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05006375 error = security_context_to_sid(value, size,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006376 &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006377 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04006378 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04006379 struct audit_buffer *ab;
6380 size_t audit_size;
6381
6382 /* We strip a nul only if it is at the end, otherwise the
6383 * context contains a nul and we should audit that */
6384 if (str[size - 1] == '\0')
6385 audit_size = size - 1;
6386 else
6387 audit_size = size;
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04006388 ab = audit_log_start(audit_context(),
6389 GFP_ATOMIC,
6390 AUDIT_SELINUX_ERR);
Austin Kim893c47d2021-07-14 01:11:27 +01006391 if (!ab)
6392 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006393 audit_log_format(ab, "op=fscreate invalid_context=");
6394 audit_log_n_untrustedstring(ab, value, audit_size);
6395 audit_log_end(ab);
6396
Stephen Smalley12b29f32008-05-07 13:03:20 -04006397 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006398 }
Stephen Smalleye67b7982023-03-09 13:30:37 -05006399 error = security_context_to_sid_force(value, size,
6400 &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006402 if (error)
6403 return error;
6404 }
6405
David Howellsd84f4f92008-11-14 10:39:23 +11006406 new = prepare_creds();
6407 if (!new)
6408 return -ENOMEM;
6409
Linus Torvalds1da177e2005-04-16 15:20:36 -07006410 /* Permission checking based on the specified context is
6411 performed during the actual operation (execve,
6412 open/mkdir/...), when we know the full context of the
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05006413 operation. See selinux_bprm_creds_for_exec for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006414 checks and may_create for the file creation checks. The
6415 operation will then fail if the context is not permitted. */
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006416 tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11006417 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006418 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006419 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006421 } else if (!strcmp(name, "keycreate")) {
Ondrej Mosnacek464c2582019-06-12 10:12:26 +02006422 if (sid) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05006423 error = avc_has_perm(mysid, sid,
Ondrej Mosnacek464c2582019-06-12 10:12:26 +02006424 SECCLASS_KEY, KEY__CREATE, NULL);
6425 if (error)
6426 goto abort_change;
6427 }
Michael LeMay4eb582c2006-06-26 00:24:57 -07006428 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006429 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006430 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006431 } else if (!strcmp(name, "current")) {
6432 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006433 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006434 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006435
David Howellsd84f4f92008-11-14 10:39:23 +11006436 /* Only allow single threaded processes to change context */
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006437 if (!current_is_single_threaded()) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05006438 error = security_bounded_transition(tsec->sid, sid);
David Howellsd84f4f92008-11-14 10:39:23 +11006439 if (error)
6440 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006442
6443 /* Check permissions for the transition. */
Stephen Smalleye67b7982023-03-09 13:30:37 -05006444 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006445 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006447 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006448
6449 /* Check for ptracing, and update the task SID if ok.
6450 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006451 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006452 if (ptsid != 0) {
Stephen Smalleye67b7982023-03-09 13:30:37 -05006453 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
David Howellsd84f4f92008-11-14 10:39:23 +11006454 PROCESS__PTRACE, NULL);
6455 if (error)
6456 goto abort_change;
6457 }
6458
6459 tsec->sid = sid;
6460 } else {
6461 error = -EINVAL;
6462 goto abort_change;
6463 }
6464
6465 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006466 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006467
6468abort_change:
6469 abort_creds(new);
6470 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006471}
6472
David Quigley746df9b2013-05-22 12:50:35 -04006473static int selinux_ismaclabel(const char *name)
6474{
6475 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6476}
6477
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006478static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6479{
Stephen Smalleye67b7982023-03-09 13:30:37 -05006480 return security_sid_to_context(secid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006481 secdata, seclen);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006482}
6483
David Howells7bf570d2008-04-29 20:52:51 +01006484static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006485{
Stephen Smalleye67b7982023-03-09 13:30:37 -05006486 return security_context_to_sid(secdata, seclen,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006487 secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006488}
6489
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006490static void selinux_release_secctx(char *secdata, u32 seclen)
6491{
Paul Moore088999e2007-08-01 11:12:58 -04006492 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006493}
6494
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006495static void selinux_inode_invalidate_secctx(struct inode *inode)
6496{
Casey Schaufler80788c22018-09-21 17:19:11 -07006497 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006498
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006499 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006500 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006501 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006502}
6503
David P. Quigley1ee65e32009-09-03 14:25:57 -04006504/*
6505 * called with inode->i_mutex locked
6506 */
6507static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6508{
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01006509 int rc = selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX,
6510 ctx, ctxlen, 0);
6511 /* Do not return error when suppressing label (SBLABEL_MNT not set). */
6512 return rc == -EOPNOTSUPP ? 0 : rc;
David P. Quigley1ee65e32009-09-03 14:25:57 -04006513}
6514
6515/*
6516 * called with inode->i_mutex locked
6517 */
6518static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6519{
Christian Brauner39f60c12023-01-13 12:49:23 +01006520 return __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX,
Tycho Andersenc7c7a1a12021-01-21 14:19:28 +01006521 ctx, ctxlen, 0);
David P. Quigley1ee65e32009-09-03 14:25:57 -04006522}
6523
6524static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6525{
6526 int len = 0;
Christian Brauner4609e1f2023-01-13 12:49:22 +01006527 len = selinux_inode_getsecurity(&nop_mnt_idmap, inode,
Christian Brauner71bc3562021-01-21 14:19:29 +01006528 XATTR_SELINUX_SUFFIX, ctx, true);
David P. Quigley1ee65e32009-09-03 14:25:57 -04006529 if (len < 0)
6530 return len;
6531 *ctxlen = len;
6532 return 0;
6533}
Michael LeMayd7200242006-06-22 14:47:17 -07006534#ifdef CONFIG_KEYS
6535
David Howellsd84f4f92008-11-14 10:39:23 +11006536static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006537 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006538{
David Howellsd84f4f92008-11-14 10:39:23 +11006539 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006540 struct key_security_struct *ksec;
6541
6542 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6543 if (!ksec)
6544 return -ENOMEM;
6545
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006546 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11006547 if (tsec->keycreate_sid)
6548 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006549 else
David Howellsd84f4f92008-11-14 10:39:23 +11006550 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006551
David Howells275bb412008-11-14 10:39:19 +11006552 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006553 return 0;
6554}
6555
6556static void selinux_key_free(struct key *k)
6557{
6558 struct key_security_struct *ksec = k->security;
6559
6560 k->security = NULL;
6561 kfree(ksec);
6562}
6563
6564static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006565 const struct cred *cred,
David Howells8c0637e2020-05-12 15:16:29 +01006566 enum key_need_perm need_perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006567{
6568 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006569 struct key_security_struct *ksec;
David Howells8c0637e2020-05-12 15:16:29 +01006570 u32 perm, sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006571
David Howells8c0637e2020-05-12 15:16:29 +01006572 switch (need_perm) {
6573 case KEY_NEED_VIEW:
6574 perm = KEY__VIEW;
6575 break;
6576 case KEY_NEED_READ:
6577 perm = KEY__READ;
6578 break;
6579 case KEY_NEED_WRITE:
6580 perm = KEY__WRITE;
6581 break;
6582 case KEY_NEED_SEARCH:
6583 perm = KEY__SEARCH;
6584 break;
6585 case KEY_NEED_LINK:
6586 perm = KEY__LINK;
6587 break;
6588 case KEY_NEED_SETATTR:
6589 perm = KEY__SETATTR;
6590 break;
6591 case KEY_NEED_UNLINK:
6592 case KEY_SYSADMIN_OVERRIDE:
6593 case KEY_AUTHTOKEN_OVERRIDE:
6594 case KEY_DEFER_PERM_CHECK:
Michael LeMayd7200242006-06-22 14:47:17 -07006595 return 0;
David Howells8c0637e2020-05-12 15:16:29 +01006596 default:
6597 WARN_ON(1);
6598 return -EPERM;
6599
6600 }
Michael LeMayd7200242006-06-22 14:47:17 -07006601
David Howellsd84f4f92008-11-14 10:39:23 +11006602 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006603 key = key_ref_to_ptr(key_ref);
6604 ksec = key->security;
6605
Stephen Smalleye67b7982023-03-09 13:30:37 -05006606 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006607}
6608
David Howells70a5bb72008-04-29 01:01:26 -07006609static int selinux_key_getsecurity(struct key *key, char **_buffer)
6610{
6611 struct key_security_struct *ksec = key->security;
6612 char *context = NULL;
6613 unsigned len;
6614 int rc;
6615
Stephen Smalleye67b7982023-03-09 13:30:37 -05006616 rc = security_sid_to_context(ksec->sid,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006617 &context, &len);
David Howells70a5bb72008-04-29 01:01:26 -07006618 if (!rc)
6619 rc = len;
6620 *_buffer = context;
6621 return rc;
6622}
David Howells3e412cc2020-01-14 17:07:13 +00006623
6624#ifdef CONFIG_KEY_NOTIFICATIONS
6625static int selinux_watch_key(struct key *key)
6626{
6627 struct key_security_struct *ksec = key->security;
6628 u32 sid = current_sid();
6629
Stephen Smalleye67b7982023-03-09 13:30:37 -05006630 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL);
David Howells3e412cc2020-01-14 17:07:13 +00006631}
6632#endif
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006633#endif
David Howells70a5bb72008-04-29 01:01:26 -07006634
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006635#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006636static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6637{
6638 struct common_audit_data ad;
6639 int err;
6640 u32 sid = 0;
6641 struct ib_security_struct *sec = ib_sec;
6642 struct lsm_ibpkey_audit ibpkey;
6643
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006644 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006645 if (err)
6646 return err;
6647
6648 ad.type = LSM_AUDIT_DATA_IBPKEY;
6649 ibpkey.subnet_prefix = subnet_prefix;
6650 ibpkey.pkey = pkey_val;
6651 ad.u.ibpkey = &ibpkey;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006652 return avc_has_perm(sec->sid, sid,
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006653 SECCLASS_INFINIBAND_PKEY,
6654 INFINIBAND_PKEY__ACCESS, &ad);
6655}
6656
Daniel Jurgensab861df2017-05-19 15:48:58 +03006657static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6658 u8 port_num)
6659{
6660 struct common_audit_data ad;
6661 int err;
6662 u32 sid = 0;
6663 struct ib_security_struct *sec = ib_sec;
6664 struct lsm_ibendport_audit ibendport;
6665
Stephen Smalleye67b7982023-03-09 13:30:37 -05006666 err = security_ib_endport_sid(dev_name, port_num,
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006667 &sid);
Daniel Jurgensab861df2017-05-19 15:48:58 +03006668
6669 if (err)
6670 return err;
6671
6672 ad.type = LSM_AUDIT_DATA_IBENDPORT;
Ondrej Mosnacek869cbee2021-05-12 16:32:10 +02006673 ibendport.dev_name = dev_name;
Daniel Jurgensab861df2017-05-19 15:48:58 +03006674 ibendport.port = port_num;
6675 ad.u.ibendport = &ibendport;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006676 return avc_has_perm(sec->sid, sid,
Daniel Jurgensab861df2017-05-19 15:48:58 +03006677 SECCLASS_INFINIBAND_ENDPORT,
6678 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6679}
6680
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006681static int selinux_ib_alloc_security(void **ib_sec)
6682{
6683 struct ib_security_struct *sec;
6684
6685 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6686 if (!sec)
6687 return -ENOMEM;
6688 sec->sid = current_sid();
6689
6690 *ib_sec = sec;
6691 return 0;
6692}
6693
6694static void selinux_ib_free_security(void *ib_sec)
6695{
6696 kfree(ib_sec);
6697}
Michael LeMayd7200242006-06-22 14:47:17 -07006698#endif
6699
Chenbo Fengec27c352017-10-18 13:00:25 -07006700#ifdef CONFIG_BPF_SYSCALL
6701static int selinux_bpf(int cmd, union bpf_attr *attr,
6702 unsigned int size)
6703{
6704 u32 sid = current_sid();
6705 int ret;
6706
6707 switch (cmd) {
6708 case BPF_MAP_CREATE:
Stephen Smalleye67b7982023-03-09 13:30:37 -05006709 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
Chenbo Fengec27c352017-10-18 13:00:25 -07006710 NULL);
6711 break;
6712 case BPF_PROG_LOAD:
Stephen Smalleye67b7982023-03-09 13:30:37 -05006713 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
Chenbo Fengec27c352017-10-18 13:00:25 -07006714 NULL);
6715 break;
6716 default:
6717 ret = 0;
6718 break;
6719 }
6720
6721 return ret;
6722}
6723
6724static u32 bpf_map_fmode_to_av(fmode_t fmode)
6725{
6726 u32 av = 0;
6727
6728 if (fmode & FMODE_READ)
6729 av |= BPF__MAP_READ;
6730 if (fmode & FMODE_WRITE)
6731 av |= BPF__MAP_WRITE;
6732 return av;
6733}
6734
Chenbo Fengf66e4482017-10-18 13:00:26 -07006735/* This function will check the file pass through unix socket or binder to see
Jonas Lindner9691e4f2022-06-09 00:36:16 +02006736 * if it is a bpf related object. And apply corresponding checks on the bpf
Chenbo Fengf66e4482017-10-18 13:00:26 -07006737 * object based on the type. The bpf maps and programs, not like other files and
6738 * socket, are using a shared anonymous inode inside the kernel as their inode.
6739 * So checking that inode cannot identify if the process have privilege to
6740 * access the bpf object and that's why we have to add this additional check in
6741 * selinux_file_receive and selinux_binder_transfer_files.
6742 */
6743static int bpf_fd_pass(struct file *file, u32 sid)
6744{
6745 struct bpf_security_struct *bpfsec;
6746 struct bpf_prog *prog;
6747 struct bpf_map *map;
6748 int ret;
6749
6750 if (file->f_op == &bpf_map_fops) {
6751 map = file->private_data;
6752 bpfsec = map->security;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006753 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006754 bpf_map_fmode_to_av(file->f_mode), NULL);
6755 if (ret)
6756 return ret;
6757 } else if (file->f_op == &bpf_prog_fops) {
6758 prog = file->private_data;
6759 bpfsec = prog->aux->security;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006760 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006761 BPF__PROG_RUN, NULL);
6762 if (ret)
6763 return ret;
6764 }
6765 return 0;
6766}
6767
Chenbo Fengec27c352017-10-18 13:00:25 -07006768static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6769{
6770 u32 sid = current_sid();
6771 struct bpf_security_struct *bpfsec;
6772
6773 bpfsec = map->security;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006774 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006775 bpf_map_fmode_to_av(fmode), NULL);
6776}
6777
6778static int selinux_bpf_prog(struct bpf_prog *prog)
6779{
6780 u32 sid = current_sid();
6781 struct bpf_security_struct *bpfsec;
6782
6783 bpfsec = prog->aux->security;
Stephen Smalleye67b7982023-03-09 13:30:37 -05006784 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006785 BPF__PROG_RUN, NULL);
6786}
6787
6788static int selinux_bpf_map_alloc(struct bpf_map *map)
6789{
6790 struct bpf_security_struct *bpfsec;
6791
6792 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6793 if (!bpfsec)
6794 return -ENOMEM;
6795
6796 bpfsec->sid = current_sid();
6797 map->security = bpfsec;
6798
6799 return 0;
6800}
6801
6802static void selinux_bpf_map_free(struct bpf_map *map)
6803{
6804 struct bpf_security_struct *bpfsec = map->security;
6805
6806 map->security = NULL;
6807 kfree(bpfsec);
6808}
6809
6810static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6811{
6812 struct bpf_security_struct *bpfsec;
6813
6814 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6815 if (!bpfsec)
6816 return -ENOMEM;
6817
6818 bpfsec->sid = current_sid();
6819 aux->security = bpfsec;
6820
6821 return 0;
6822}
6823
6824static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6825{
6826 struct bpf_security_struct *bpfsec = aux->security;
6827
6828 aux->security = NULL;
6829 kfree(bpfsec);
6830}
6831#endif
6832
Paul Mooref22f9aa2023-03-17 12:43:07 -04006833struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
Casey Schauflerbbd36622018-11-12 09:30:56 -08006834 .lbs_cred = sizeof(struct task_security_struct),
Casey Schaufler33bf60c2018-11-12 12:02:49 -08006835 .lbs_file = sizeof(struct file_security_struct),
Casey Schauflerafb1cbe32018-09-21 17:19:29 -07006836 .lbs_inode = sizeof(struct inode_security_struct),
Casey Schauflerecd5f822018-11-20 11:55:02 -08006837 .lbs_ipc = sizeof(struct ipc_security_struct),
6838 .lbs_msg_msg = sizeof(struct msg_security_struct),
Casey Schaufler1aea7802021-04-22 17:41:15 +02006839 .lbs_superblock = sizeof(struct superblock_security_struct),
Casey Schauflerbbd36622018-11-12 09:30:56 -08006840};
6841
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006842#ifdef CONFIG_PERF_EVENTS
6843static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
6844{
6845 u32 requested, sid = current_sid();
6846
6847 if (type == PERF_SECURITY_OPEN)
6848 requested = PERF_EVENT__OPEN;
6849 else if (type == PERF_SECURITY_CPU)
6850 requested = PERF_EVENT__CPU;
6851 else if (type == PERF_SECURITY_KERNEL)
6852 requested = PERF_EVENT__KERNEL;
6853 else if (type == PERF_SECURITY_TRACEPOINT)
6854 requested = PERF_EVENT__TRACEPOINT;
6855 else
6856 return -EINVAL;
6857
Stephen Smalleye67b7982023-03-09 13:30:37 -05006858 return avc_has_perm(sid, sid, SECCLASS_PERF_EVENT,
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006859 requested, NULL);
6860}
6861
6862static int selinux_perf_event_alloc(struct perf_event *event)
6863{
6864 struct perf_event_security_struct *perfsec;
6865
6866 perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
6867 if (!perfsec)
6868 return -ENOMEM;
6869
6870 perfsec->sid = current_sid();
6871 event->security = perfsec;
6872
6873 return 0;
6874}
6875
6876static void selinux_perf_event_free(struct perf_event *event)
6877{
6878 struct perf_event_security_struct *perfsec = event->security;
6879
6880 event->security = NULL;
6881 kfree(perfsec);
6882}
6883
6884static int selinux_perf_event_read(struct perf_event *event)
6885{
6886 struct perf_event_security_struct *perfsec = event->security;
6887 u32 sid = current_sid();
6888
Stephen Smalleye67b7982023-03-09 13:30:37 -05006889 return avc_has_perm(sid, perfsec->sid,
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006890 SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
6891}
6892
6893static int selinux_perf_event_write(struct perf_event *event)
6894{
6895 struct perf_event_security_struct *perfsec = event->security;
6896 u32 sid = current_sid();
6897
Stephen Smalleye67b7982023-03-09 13:30:37 -05006898 return avc_has_perm(sid, perfsec->sid,
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006899 SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
6900}
6901#endif
6902
Paul Moore740b0342021-02-23 18:16:45 -05006903#ifdef CONFIG_IO_URING
6904/**
6905 * selinux_uring_override_creds - check the requested cred override
6906 * @new: the target creds
6907 *
6908 * Check to see if the current task is allowed to override it's credentials
6909 * to service an io_uring operation.
6910 */
6911static int selinux_uring_override_creds(const struct cred *new)
6912{
Stephen Smalleye67b7982023-03-09 13:30:37 -05006913 return avc_has_perm(current_sid(), cred_sid(new),
Paul Moore740b0342021-02-23 18:16:45 -05006914 SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL);
6915}
6916
6917/**
6918 * selinux_uring_sqpoll - check if a io_uring polling thread can be created
6919 *
6920 * Check to see if the current task is allowed to create a new io_uring
6921 * kernel polling thread.
6922 */
6923static int selinux_uring_sqpoll(void)
6924{
Christian Göttschea13479b2023-07-06 15:23:27 +02006925 u32 sid = current_sid();
Paul Moore740b0342021-02-23 18:16:45 -05006926
Stephen Smalleye67b7982023-03-09 13:30:37 -05006927 return avc_has_perm(sid, sid,
Paul Moore740b0342021-02-23 18:16:45 -05006928 SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
6929}
Paul Mooref4d653d2022-08-10 15:55:36 -04006930
6931/**
6932 * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed
6933 * @ioucmd: the io_uring command structure
6934 *
6935 * Check to see if the current domain is allowed to execute an
6936 * IORING_OP_URING_CMD against the device/file specified in @ioucmd.
6937 *
6938 */
6939static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
6940{
6941 struct file *file = ioucmd->file;
6942 struct inode *inode = file_inode(file);
6943 struct inode_security_struct *isec = selinux_inode(inode);
6944 struct common_audit_data ad;
6945
6946 ad.type = LSM_AUDIT_DATA_FILE;
6947 ad.u.file = file;
6948
Stephen Smalleye67b7982023-03-09 13:30:37 -05006949 return avc_has_perm(current_sid(), isec->sid,
Paul Mooref4d653d2022-08-10 15:55:36 -04006950 SECCLASS_IO_URING, IO_URING__CMD, &ad);
6951}
Paul Moore740b0342021-02-23 18:16:45 -05006952#endif /* CONFIG_IO_URING */
6953
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01006954/*
6955 * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
6956 * 1. any hooks that don't belong to (2.) or (3.) below,
6957 * 2. hooks that both access structures allocated by other hooks, and allocate
6958 * structures that can be later accessed by other hooks (mostly "cloning"
6959 * hooks),
6960 * 3. hooks that only allocate structures that can be later accessed by other
6961 * hooks ("allocating" hooks).
6962 *
6963 * Please follow block comment delimiters in the list to keep this order.
6964 *
6965 * This ordering is needed for SELinux runtime disable to work at least somewhat
6966 * safely. Breaking the ordering rules above might lead to NULL pointer derefs
6967 * when disabling SELinux at runtime.
6968 */
Paul Mooref22f9aa2023-03-17 12:43:07 -04006969static struct security_hook_list selinux_hooks[] __ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006970 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6971 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6972 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6973 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006974
Casey Schauflere20b0432015-05-02 15:11:36 -07006975 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6976 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6977 LSM_HOOK_INIT(capget, selinux_capget),
6978 LSM_HOOK_INIT(capset, selinux_capset),
6979 LSM_HOOK_INIT(capable, selinux_capable),
6980 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6981 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6982 LSM_HOOK_INIT(syslog, selinux_syslog),
6983 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006984
Casey Schauflere20b0432015-05-02 15:11:36 -07006985 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006986
Eric W. Biedermanb8bff592020-03-22 15:46:24 -05006987 LSM_HOOK_INIT(bprm_creds_for_exec, selinux_bprm_creds_for_exec),
Casey Schauflere20b0432015-05-02 15:11:36 -07006988 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6989 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006990
Al Viro204cc0c2018-12-13 13:41:47 -05006991 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
Olga Kornievskaia69c4a422021-02-26 22:37:55 -05006992 LSM_HOOK_INIT(sb_mnt_opts_compat, selinux_sb_mnt_opts_compat),
Casey Schauflere20b0432015-05-02 15:11:36 -07006993 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6994 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6995 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6996 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6997 LSM_HOOK_INIT(sb_mount, selinux_mount),
6998 LSM_HOOK_INIT(sb_umount, selinux_umount),
6999 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
7000 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007001
Stephen Smalley98aa003452020-01-17 15:24:07 -05007002 LSM_HOOK_INIT(move_mount, selinux_move_mount),
7003
Casey Schauflere20b0432015-05-02 15:11:36 -07007004 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04007005 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05007006
Casey Schauflere20b0432015-05-02 15:11:36 -07007007 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
7008 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
Daniel Colascione29cd6592021-01-08 14:22:22 -08007009 LSM_HOOK_INIT(inode_init_security_anon, selinux_inode_init_security_anon),
Casey Schauflere20b0432015-05-02 15:11:36 -07007010 LSM_HOOK_INIT(inode_create, selinux_inode_create),
7011 LSM_HOOK_INIT(inode_link, selinux_inode_link),
7012 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
7013 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
7014 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
7015 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
7016 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
7017 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
7018 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
7019 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
7020 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
7021 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
7022 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
7023 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
7024 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
7025 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
7026 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
7027 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
Christian Brauner1bdeb212022-09-22 17:17:08 +02007028 LSM_HOOK_INIT(inode_set_acl, selinux_inode_set_acl),
7029 LSM_HOOK_INIT(inode_get_acl, selinux_inode_get_acl),
7030 LSM_HOOK_INIT(inode_remove_acl, selinux_inode_remove_acl),
Casey Schauflere20b0432015-05-02 15:11:36 -07007031 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
7032 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
7033 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
7034 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04007035 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04007036 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Aaron Goidelac5656d2019-08-12 11:20:00 -04007037 LSM_HOOK_INIT(path_notify, selinux_path_notify),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007038
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01007039 LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
7040
Casey Schauflere20b0432015-05-02 15:11:36 -07007041 LSM_HOOK_INIT(file_permission, selinux_file_permission),
7042 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
Casey Schauflere20b0432015-05-02 15:11:36 -07007043 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
7044 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
7045 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
7046 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
7047 LSM_HOOK_INIT(file_lock, selinux_file_lock),
7048 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
7049 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
7050 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
7051 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052
Casey Schauflere20b0432015-05-02 15:11:36 -07007053 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007054
Tetsuo Handaa79be232017-03-28 23:08:45 +09007055 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07007056 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
7057 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
Matthew Garrett3ec30112018-01-08 13:36:19 -08007058 LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
Casey Schauflere20b0432015-05-02 15:11:36 -07007059 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
7060 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
7061 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04007062 LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07007063 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07007064 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
7065 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
7066 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
Paul Moore63269482021-09-29 11:01:21 -04007067 LSM_HOOK_INIT(current_getsecid_subj, selinux_current_getsecid_subj),
Paul Mooreeb1231f2021-02-18 15:13:40 -05007068 LSM_HOOK_INIT(task_getsecid_obj, selinux_task_getsecid_obj),
Casey Schauflere20b0432015-05-02 15:11:36 -07007069 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
7070 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
7071 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05007072 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07007073 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
7074 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
7075 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
7076 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
7077 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07007078 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Frederick Lawlered5d44d2022-08-15 11:20:28 -05007079 LSM_HOOK_INIT(userns_create, selinux_userns_create),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09007080
Casey Schauflere20b0432015-05-02 15:11:36 -07007081 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
7082 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007083
Casey Schauflere20b0432015-05-02 15:11:36 -07007084 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
7085 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
7086 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
7087 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007088
Casey Schauflere20b0432015-05-02 15:11:36 -07007089 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
7090 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
7091 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007092
Casey Schauflere20b0432015-05-02 15:11:36 -07007093 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
7094 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
7095 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007096
Casey Schauflere20b0432015-05-02 15:11:36 -07007097 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007098
Casey Schauflere20b0432015-05-02 15:11:36 -07007099 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
7100 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Casey Schauflere20b0432015-05-02 15:11:36 -07007102 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
Casey Schauflere20b0432015-05-02 15:11:36 -07007103 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
7104 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05007105 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07007106 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
7107 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Casey Schauflere20b0432015-05-02 15:11:36 -07007109 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
7110 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07007111
Casey Schauflere20b0432015-05-02 15:11:36 -07007112 LSM_HOOK_INIT(socket_create, selinux_socket_create),
7113 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
David Herrmann0b811db2018-05-04 16:28:21 +02007114 LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
Casey Schauflere20b0432015-05-02 15:11:36 -07007115 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
7116 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
7117 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
7118 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
7119 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
7120 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
7121 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
7122 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
7123 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
7124 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
7125 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
7126 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
7127 LSM_HOOK_INIT(socket_getpeersec_stream,
7128 selinux_socket_getpeersec_stream),
7129 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
Casey Schauflere20b0432015-05-02 15:11:36 -07007130 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
7131 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
7132 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
7133 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
Richard Hainesd4529302018-02-13 20:57:18 +00007134 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
7135 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
7136 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
Ondrej Mosnacek3eb8eaf2022-02-12 18:59:22 +01007137 LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
Paolo Abeni85c32222023-04-20 19:17:14 +02007138 LSM_HOOK_INIT(mptcp_add_subflow, selinux_mptcp_add_subflow),
Casey Schauflere20b0432015-05-02 15:11:36 -07007139 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
7140 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
7141 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
7142 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
7143 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
7144 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
7145 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
Casey Schauflere20b0432015-05-02 15:11:36 -07007146 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
7147 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
7148 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
7149 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
7150 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007151#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03007152 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03007153 LSM_HOOK_INIT(ib_endport_manage_subnet,
7154 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007155 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
7156#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08007157#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07007158 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
7159 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
Casey Schauflere20b0432015-05-02 15:11:36 -07007160 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
7161 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
7162 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
7163 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
7164 selinux_xfrm_state_pol_flow_match),
7165 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007166#endif
Michael LeMayd7200242006-06-22 14:47:17 -07007167
7168#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07007169 LSM_HOOK_INIT(key_free, selinux_key_free),
7170 LSM_HOOK_INIT(key_permission, selinux_key_permission),
7171 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
David Howells3e412cc2020-01-14 17:07:13 +00007172#ifdef CONFIG_KEY_NOTIFICATIONS
7173 LSM_HOOK_INIT(watch_key, selinux_watch_key),
7174#endif
Michael LeMayd7200242006-06-22 14:47:17 -07007175#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007176
7177#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07007178 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
7179 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
7180 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007181#endif
Chenbo Fengec27c352017-10-18 13:00:25 -07007182
7183#ifdef CONFIG_BPF_SYSCALL
7184 LSM_HOOK_INIT(bpf, selinux_bpf),
7185 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
7186 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
Chenbo Fengec27c352017-10-18 13:00:25 -07007187 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
7188 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
7189#endif
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007190
7191#ifdef CONFIG_PERF_EVENTS
7192 LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007193 LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
7194 LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
7195 LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
7196#endif
Stephen Smalley59438b462019-11-27 12:04:36 -05007197
Paul Moore740b0342021-02-23 18:16:45 -05007198#ifdef CONFIG_IO_URING
7199 LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds),
7200 LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll),
Paul Mooref4d653d2022-08-10 15:55:36 -04007201 LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd),
Paul Moore740b0342021-02-23 18:16:45 -05007202#endif
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007203
7204 /*
7205 * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE
7206 */
7207 LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
7208 LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
7209 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007210#ifdef CONFIG_SECURITY_NETWORK_XFRM
7211 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
7212#endif
7213
7214 /*
7215 * PUT "ALLOCATING" HOOKS HERE
7216 */
7217 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
7218 LSM_HOOK_INIT(msg_queue_alloc_security,
7219 selinux_msg_queue_alloc_security),
7220 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
7221 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
7222 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
7223 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
7224 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
7225 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
7226 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
7227 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
7228#ifdef CONFIG_SECURITY_INFINIBAND
7229 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
7230#endif
7231#ifdef CONFIG_SECURITY_NETWORK_XFRM
7232 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
7233 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
7234 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
7235 selinux_xfrm_state_alloc_acquire),
7236#endif
7237#ifdef CONFIG_KEYS
7238 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
7239#endif
7240#ifdef CONFIG_AUDIT
7241 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
7242#endif
7243#ifdef CONFIG_BPF_SYSCALL
7244 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
7245 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
7246#endif
7247#ifdef CONFIG_PERF_EVENTS
7248 LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
7249#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250};
7251
7252static __init int selinux_init(void)
7253{
peter enderborgc103a912018-06-12 10:09:03 +02007254 pr_info("SELinux: Initializing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007256 memset(&selinux_state, 0, sizeof(selinux_state));
Stephen Smalleye67b7982023-03-09 13:30:37 -05007257 enforcing_set(selinux_enforcing_boot);
Stephen Smalleye67b7982023-03-09 13:30:37 -05007258 selinux_avc_init();
Ondrej Mosnacek4b36cb72020-01-17 14:15:14 +01007259 mutex_init(&selinux_state.status_lock);
Stephen Smalley9ff9abc2020-08-26 13:28:53 -04007260 mutex_init(&selinux_state.policy_mutex);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007261
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11007263 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04007265 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
7266
Linus Torvalds1da177e2005-04-16 15:20:36 -07007267 avc_init();
7268
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007269 avtab_cache_init();
7270
7271 ebitmap_cache_init();
7272
7273 hashtab_cache_init();
7274
Casey Schauflerd69dece52017-01-18 17:09:05 -08007275 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276
Paul Moore615e51f2014-06-26 14:33:56 -04007277 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
7278 panic("SELinux: Unable to register AVC netcache callback\n");
7279
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03007280 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
7281 panic("SELinux: Unable to register AVC LSM notifier callback\n");
7282
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007283 if (selinux_enforcing_boot)
peter enderborgc103a912018-06-12 10:09:03 +02007284 pr_debug("SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04007285 else
peter enderborgc103a912018-06-12 10:09:03 +02007286 pr_debug("SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07007287
Al Virod7167b12019-09-07 07:23:15 -04007288 fs_validate_description("selinux", selinux_fs_parameters);
David Howells442155c2018-11-01 23:07:24 +00007289
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290 return 0;
7291}
7292
Al Viroe8c26252010-03-23 06:36:54 -04007293static void delayed_superblock_init(struct super_block *sb, void *unused)
7294{
Al Viro204cc0c2018-12-13 13:41:47 -05007295 selinux_set_mnt_opts(sb, NULL, 0, NULL);
Al Viroe8c26252010-03-23 06:36:54 -04007296}
7297
Linus Torvalds1da177e2005-04-16 15:20:36 -07007298void selinux_complete_init(void)
7299{
peter enderborgc103a912018-06-12 10:09:03 +02007300 pr_debug("SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007301
7302 /* Set up any superblocks initialized prior to the policy load. */
peter enderborgc103a912018-06-12 10:09:03 +02007303 pr_debug("SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04007304 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007305}
7306
7307/* SELinux requires early initialization in order to label
7308 all processes and objects when they are created. */
Kees Cook3d6e5f62018-10-10 17:18:23 -07007309DEFINE_LSM(selinux) = {
Kees Cook07aed2f2018-10-10 17:18:24 -07007310 .name = "selinux",
Kees Cook14bd99c2018-09-19 19:57:06 -07007311 .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007312 .enabled = &selinux_enabled_boot,
Casey Schauflerbbd36622018-11-12 09:30:56 -08007313 .blobs = &selinux_blob_sizes,
Kees Cook3d6e5f62018-10-10 17:18:23 -07007314 .init = selinux_init,
7315};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007316
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007317#if defined(CONFIG_NETFILTER)
Florian Westphal591bb272017-07-26 11:40:52 +02007318static const struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05007319 {
Florian Westphal4342f702021-10-11 22:22:29 +02007320 .hook = selinux_ip_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007321 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007322 .hooknum = NF_INET_POST_ROUTING,
7323 .priority = NF_IP_PRI_SELINUX_LAST,
7324 },
7325 {
Florian Westphal4342f702021-10-11 22:22:29 +02007326 .hook = selinux_ip_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007327 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007328 .hooknum = NF_INET_FORWARD,
7329 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04007330 },
7331 {
Florian Westphal4342f702021-10-11 22:22:29 +02007332 .hook = selinux_ip_output,
Alban Crequy2597a832012-05-14 03:56:39 +00007333 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04007334 .hooknum = NF_INET_LOCAL_OUT,
7335 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007336 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04007337#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05007338 {
Florian Westphal4342f702021-10-11 22:22:29 +02007339 .hook = selinux_ip_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007340 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007341 .hooknum = NF_INET_POST_ROUTING,
7342 .priority = NF_IP6_PRI_SELINUX_LAST,
7343 },
7344 {
Florian Westphal4342f702021-10-11 22:22:29 +02007345 .hook = selinux_ip_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007346 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007347 .hooknum = NF_INET_FORWARD,
7348 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007349 },
Huw Davies2917f572016-06-27 15:06:15 -04007350 {
Florian Westphal4342f702021-10-11 22:22:29 +02007351 .hook = selinux_ip_output,
Huw Davies2917f572016-06-27 15:06:15 -04007352 .pf = NFPROTO_IPV6,
7353 .hooknum = NF_INET_LOCAL_OUT,
7354 .priority = NF_IP6_PRI_SELINUX_FIRST,
7355 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07007356#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02007357};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007358
Florian Westphal8e71bf72017-04-21 11:49:09 +02007359static int __net_init selinux_nf_register(struct net *net)
7360{
7361 return nf_register_net_hooks(net, selinux_nf_ops,
7362 ARRAY_SIZE(selinux_nf_ops));
7363}
7364
7365static void __net_exit selinux_nf_unregister(struct net *net)
7366{
7367 nf_unregister_net_hooks(net, selinux_nf_ops,
7368 ARRAY_SIZE(selinux_nf_ops));
7369}
7370
7371static struct pernet_operations selinux_net_ops = {
7372 .init = selinux_nf_register,
7373 .exit = selinux_nf_unregister,
7374};
7375
Linus Torvalds1da177e2005-04-16 15:20:36 -07007376static int __init selinux_nf_ip_init(void)
7377{
Jiri Pirko25db6be2014-09-03 17:42:13 +02007378 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007379
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007380 if (!selinux_enabled_boot)
Jiri Pirko25db6be2014-09-03 17:42:13 +02007381 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05007382
peter enderborgc103a912018-06-12 10:09:03 +02007383 pr_debug("SELinux: Registering netfilter hooks\n");
Eric Parisfadcdb42007-02-22 18:11:31 -05007384
Florian Westphal8e71bf72017-04-21 11:49:09 +02007385 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07007386 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02007387 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007388
Jiri Pirko25db6be2014-09-03 17:42:13 +02007389 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007391__initcall(selinux_nf_ip_init);
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007392#endif /* CONFIG_NETFILTER */