blob: 61085eb3cd24a16b70b36bb909da1ff7bf5756c5 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * NSA Security-Enhanced Linux (SELinux) security module
4 *
5 * This file contains the SELinux hook function implementations.
6 *
Stephen Smalley7efbb602017-08-17 13:32:36 -04007 * Authors: Stephen Smalley, <sds@tycho.nsa.gov>
Eric Paris828dfe12008-04-17 13:17:49 -04008 * Chris Vance, <cvance@nai.com>
9 * Wayne Salamon, <wsalamon@nai.com>
10 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
12 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100013 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
14 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040016 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040017 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000018 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090019 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040020 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Daniel Jurgens3a976fa2017-05-19 15:48:56 +030021 * Copyright (C) 2016 Mellanox Technologies
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050025#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070027#include <linux/tracehook.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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95#include "avc.h"
96#include "objsec.h"
97#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050098#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040099#include "netport.h"
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300100#include "ibpkey.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -0800101#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -0500102#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +0200103#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +1000104#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500106struct selinux_state selinux_state;
107
Paul Moored621d352008-01-29 08:43:36 -0500108/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000109static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500112static int selinux_enforcing_boot __initdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114static int __init enforcing_setup(char *str)
115{
Eric Parisf5269712008-05-14 11:27:45 -0400116 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900117 if (!kstrtoul(str, 0, &enforcing))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500118 selinux_enforcing_boot = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 return 1;
120}
121__setup("enforcing=", enforcing_setup);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500122#else
123#define selinux_enforcing_boot 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124#endif
125
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500126int selinux_enabled_boot __initdata = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128static int __init selinux_enabled_setup(char *str)
129{
Eric Parisf5269712008-05-14 11:27:45 -0400130 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900131 if (!kstrtoul(str, 0, &enabled))
Stephen Smalley6c5a6822019-12-17 09:15:10 -0500132 selinux_enabled_boot = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 return 1;
134}
135__setup("selinux=", selinux_enabled_setup);
136#endif
137
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500138static unsigned int selinux_checkreqprot_boot =
139 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
140
141static int __init checkreqprot_setup(char *str)
142{
143 unsigned long checkreqprot;
144
145 if (!kstrtoul(str, 0, &checkreqprot))
146 selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
147 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{
David Howells3b11a1d2008-11-14 10:39:26 +1100210 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 struct task_security_struct *tsec;
212
Casey Schauflerbbd36622018-11-12 09:30:56 -0800213 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +1100214 tsec->osid = tsec->sid = SECINITSID_KERNEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215}
216
David Howells275bb412008-11-14 10:39:19 +1100217/*
David Howells88e67f32008-11-14 10:39:21 +1100218 * get the security ID of a set of credentials
219 */
220static inline u32 cred_sid(const struct cred *cred)
221{
222 const struct task_security_struct *tsec;
223
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700224 tsec = selinux_cred(cred);
David Howells88e67f32008-11-14 10:39:21 +1100225 return tsec->sid;
226}
227
228/*
David Howells3b11a1d2008-11-14 10:39:26 +1100229 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100230 */
231static inline u32 task_sid(const struct task_struct *task)
232{
David Howells275bb412008-11-14 10:39:19 +1100233 u32 sid;
234
235 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100236 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100237 rcu_read_unlock();
238 return sid;
239}
240
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500241static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
242
243/*
244 * Try reloading inode security labels that have been marked as invalid. The
245 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100246 * allowed; when set to false, returns -ECHILD when the label is
Al Viroe9193282018-04-24 21:31:02 -0400247 * invalid. The @dentry parameter should be set to a dentry of the inode.
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500248 */
249static int __inode_security_revalidate(struct inode *inode,
Al Viroe9193282018-04-24 21:31:02 -0400250 struct dentry *dentry,
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500251 bool may_sleep)
252{
Casey Schaufler80788c22018-09-21 17:19:11 -0700253 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500254
255 might_sleep_if(may_sleep);
256
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100257 if (selinux_initialized(&selinux_state) &&
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500258 isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500259 if (!may_sleep)
260 return -ECHILD;
261
262 /*
263 * Try reloading the inode security label. This will fail if
264 * @opt_dentry is NULL and no dentry for this inode can be
265 * found; in that case, continue using the old label.
266 */
Al Viroe9193282018-04-24 21:31:02 -0400267 inode_doinit_with_dentry(inode, dentry);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500268 }
269 return 0;
270}
271
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500272static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
273{
Casey Schaufler80788c22018-09-21 17:19:11 -0700274 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500275}
276
277static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
278{
279 int error;
280
281 error = __inode_security_revalidate(inode, NULL, !rcu);
282 if (error)
283 return ERR_PTR(error);
Casey Schaufler80788c22018-09-21 17:19:11 -0700284 return selinux_inode(inode);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500285}
286
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500287/*
288 * Get the security label of an inode.
289 */
290static struct inode_security_struct *inode_security(struct inode *inode)
291{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500292 __inode_security_revalidate(inode, NULL, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700293 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500294}
295
Paul Moore2c971652016-04-19 16:36:28 -0400296static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
297{
298 struct inode *inode = d_backing_inode(dentry);
299
Casey Schaufler80788c22018-09-21 17:19:11 -0700300 return selinux_inode(inode);
Paul Moore2c971652016-04-19 16:36:28 -0400301}
302
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500303/*
304 * Get the security label of a dentry's backing inode.
305 */
306static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
307{
308 struct inode *inode = d_backing_inode(dentry);
309
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500310 __inode_security_revalidate(inode, dentry, true);
Casey Schaufler80788c22018-09-21 17:19:11 -0700311 return selinux_inode(inode);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500312}
313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314static void inode_free_security(struct inode *inode)
315{
Casey Schaufler80788c22018-09-21 17:19:11 -0700316 struct inode_security_struct *isec = selinux_inode(inode);
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700317 struct superblock_security_struct *sbsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Casey Schauflerafb1cbe32018-09-21 17:19:29 -0700319 if (!isec)
320 return;
321 sbsec = inode->i_sb->s_security;
Waiman Long9629d042015-07-10 17:19:56 -0400322 /*
323 * As not all inode security structures are in a list, we check for
324 * empty list outside of the lock to make sure that we won't waste
325 * time taking a lock doing nothing.
326 *
327 * The list_del_init() function can be safely called more than once.
328 * It should not be possible for this function to be called with
329 * concurrent list_add(), but for better safety against future changes
330 * in the code, we use list_empty_careful() here.
331 */
332 if (!list_empty_careful(&isec->list)) {
333 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400335 spin_unlock(&sbsec->isec_lock);
336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337}
338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339static void superblock_free_security(struct super_block *sb)
340{
341 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 sb->s_security = NULL;
343 kfree(sbsec);
344}
345
Al Virobd323652018-12-13 15:04:59 -0500346struct selinux_mnt_opts {
347 const char *fscontext, *context, *rootcontext, *defcontext;
348};
349
Al Viro204cc0c2018-12-13 13:41:47 -0500350static void selinux_free_mnt_opts(void *mnt_opts)
351{
Al Virobd323652018-12-13 15:04:59 -0500352 struct selinux_mnt_opts *opts = mnt_opts;
353 kfree(opts->fscontext);
354 kfree(opts->context);
355 kfree(opts->rootcontext);
356 kfree(opts->defcontext);
Al Viro204cc0c2018-12-13 13:41:47 -0500357 kfree(opts);
358}
359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360enum {
Eric Paris31e87932007-09-19 17:19:12 -0400361 Opt_error = -1,
David Howells442155c2018-11-01 23:07:24 +0000362 Opt_context = 0,
363 Opt_defcontext = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 Opt_fscontext = 2,
David Howells442155c2018-11-01 23:07:24 +0000365 Opt_rootcontext = 3,
366 Opt_seclabel = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Al Viroda3d76a2018-12-17 10:14:16 -0500369#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
Al Viro169d68efb2018-12-14 22:44:50 -0500370static struct {
371 const char *name;
372 int len;
373 int opt;
374 bool has_arg;
375} tokens[] = {
Al Viroda3d76a2018-12-17 10:14:16 -0500376 A(context, true),
377 A(fscontext, true),
378 A(defcontext, true),
379 A(rootcontext, true),
380 A(seclabel, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381};
Al Viro169d68efb2018-12-14 22:44:50 -0500382#undef A
383
384static int match_opt_prefix(char *s, int l, char **arg)
385{
386 int i;
387
388 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
389 size_t len = tokens[i].len;
390 if (len > l || memcmp(s, tokens[i].name, len))
391 continue;
392 if (tokens[i].has_arg) {
393 if (len == l || s[len] != '=')
394 continue;
395 *arg = s + len + 1;
396 } else if (len != l)
397 continue;
398 return tokens[i].opt;
399 }
400 return Opt_error;
401}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
404
Eric Parisc312feb2006-07-10 04:43:53 -0700405static int may_context_mount_sb_relabel(u32 sid,
406 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100407 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700408{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700409 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Parisc312feb2006-07-10 04:43:53 -0700410 int rc;
411
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500412 rc = avc_has_perm(&selinux_state,
413 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700414 FILESYSTEM__RELABELFROM, NULL);
415 if (rc)
416 return rc;
417
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500418 rc = avc_has_perm(&selinux_state,
419 tsec->sid, sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700420 FILESYSTEM__RELABELTO, NULL);
421 return rc;
422}
423
Eric Paris08089252006-07-10 04:43:55 -0700424static int may_context_mount_inode_relabel(u32 sid,
425 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100426 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700427{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700428 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Paris08089252006-07-10 04:43:55 -0700429 int rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500430 rc = avc_has_perm(&selinux_state,
431 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700432 FILESYSTEM__RELABELFROM, NULL);
433 if (rc)
434 return rc;
435
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500436 rc = avc_has_perm(&selinux_state,
437 sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700438 FILESYSTEM__ASSOCIATE, NULL);
439 return rc;
440}
441
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100442static int selinux_is_genfs_special_handling(struct super_block *sb)
Eric Parisb43e7252012-10-10 14:27:35 -0400443{
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100444 /* Special handling. Genfs but also in-core setxattr handler */
445 return !strcmp(sb->s_type->name, "sysfs") ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500446 !strcmp(sb->s_type->name, "pstore") ||
447 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500448 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500449 !strcmp(sb->s_type->name, "rootfs") ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500450 (selinux_policycap_cgroupseclabel() &&
Stephen Smalley2651225b2017-02-28 10:35:56 -0500451 (!strcmp(sb->s_type->name, "cgroup") ||
452 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400453}
454
Ondrej Mosnaceka83d6dd2018-12-21 21:18:52 +0100455static int selinux_is_sblabel_mnt(struct super_block *sb)
456{
457 struct superblock_security_struct *sbsec = sb->s_security;
458
459 /*
460 * IMPORTANT: Double-check logic in this function when adding a new
461 * SECURITY_FS_USE_* definition!
462 */
463 BUILD_BUG_ON(SECURITY_FS_USE_MAX != 7);
464
465 switch (sbsec->behavior) {
466 case SECURITY_FS_USE_XATTR:
467 case SECURITY_FS_USE_TRANS:
468 case SECURITY_FS_USE_TASK:
469 case SECURITY_FS_USE_NATIVE:
470 return 1;
471
472 case SECURITY_FS_USE_GENFS:
473 return selinux_is_genfs_special_handling(sb);
474
475 /* Never allow relabeling on context mounts */
476 case SECURITY_FS_USE_MNTPOINT:
477 case SECURITY_FS_USE_NONE:
478 default:
479 return 0;
480 }
481}
482
Eric Parisc9180a52007-11-30 13:00:35 -0500483static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 struct superblock_security_struct *sbsec = sb->s_security;
486 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000487 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 int rc = 0;
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
491 /* Make sure that the xattr handler exists and that no
492 error other than -ENODATA is returned by getxattr on
493 the root directory. -ENODATA is ok, as this may be
494 the first boot of the SELinux kernel before we have
495 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200496 if (!(root_inode->i_opflags & IOP_XATTR)) {
peter enderborgc103a912018-06-12 10:09:03 +0200497 pr_warn("SELinux: (dev %s, type %s) has no "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800498 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 rc = -EOPNOTSUPP;
500 goto out;
501 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200502
503 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 if (rc < 0 && rc != -ENODATA) {
505 if (rc == -EOPNOTSUPP)
peter enderborgc103a912018-06-12 10:09:03 +0200506 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800507 "%s) has no security xattr handler\n",
508 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 else
peter enderborgc103a912018-06-12 10:09:03 +0200510 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800511 "%s) getxattr errno %d\n", sb->s_id,
512 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 goto out;
514 }
515 }
516
Eric Pariseadcabc2012-08-24 15:59:14 -0400517 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400518
519 /*
520 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
521 * leave the flag untouched because sb_clone_mnt_opts might be handing
522 * us a superblock that needs the flag to be cleared.
523 */
Eric Parisb43e7252012-10-10 14:27:35 -0400524 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400525 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400526 else
527 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400528
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500530 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
532 /* Initialize any other inodes associated with the superblock, e.g.
533 inodes created prior to initial policy load or inodes created
534 during get_sb by a pseudo filesystem that directly
535 populates itself. */
536 spin_lock(&sbsec->isec_lock);
Al Viro8d641242018-12-10 15:34:12 -0500537 while (!list_empty(&sbsec->isec_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 struct inode_security_struct *isec =
Al Viro8d641242018-12-10 15:34:12 -0500539 list_first_entry(&sbsec->isec_head,
Eric Parisc9180a52007-11-30 13:00:35 -0500540 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400542 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 spin_unlock(&sbsec->isec_lock);
544 inode = igrab(inode);
545 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500546 if (!IS_PRIVATE(inode))
Paul Moorecb89e242020-01-10 16:32:10 -0500547 inode_doinit_with_dentry(inode, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 iput(inode);
549 }
550 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552 spin_unlock(&sbsec->isec_lock);
553out:
Eric Parisc9180a52007-11-30 13:00:35 -0500554 return rc;
555}
556
Eric Parisc9180a52007-11-30 13:00:35 -0500557static int bad_option(struct superblock_security_struct *sbsec, char flag,
558 u32 old_sid, u32 new_sid)
559{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500560 char mnt_flags = sbsec->flags & SE_MNTMASK;
561
Eric Parisc9180a52007-11-30 13:00:35 -0500562 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500563 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500564 if (!(sbsec->flags & flag) ||
565 (old_sid != new_sid))
566 return 1;
567
568 /* check if we were passed the same options twice,
569 * aka someone passed context=a,context=b
570 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500571 if (!(sbsec->flags & SE_SBINITIALIZED))
572 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500573 return 1;
574 return 0;
575}
Eric Parise0007522008-03-05 10:31:54 -0500576
Al Virobd323652018-12-13 15:04:59 -0500577static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
578{
579 int rc = security_context_str_to_sid(&selinux_state, s,
580 sid, GFP_KERNEL);
581 if (rc)
582 pr_warn("SELinux: security_context_str_to_sid"
583 "(%s) failed for (dev %s, type %s) errno=%d\n",
584 s, sb->s_id, sb->s_type->name, rc);
585 return rc;
586}
587
Eric Parisc9180a52007-11-30 13:00:35 -0500588/*
589 * Allow filesystems with binary mount data to explicitly set mount point
590 * labeling information.
591 */
Eric Parise0007522008-03-05 10:31:54 -0500592static int selinux_set_mnt_opts(struct super_block *sb,
Al Viro204cc0c2018-12-13 13:41:47 -0500593 void *mnt_opts,
David Quigley649f6e72013-05-22 12:50:36 -0400594 unsigned long kern_flags,
595 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500596{
David Howells275bb412008-11-14 10:39:19 +1100597 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500598 struct superblock_security_struct *sbsec = sb->s_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500599 struct dentry *root = sbsec->sb->s_root;
Al Virobd323652018-12-13 15:04:59 -0500600 struct selinux_mnt_opts *opts = mnt_opts;
Paul Moore2c971652016-04-19 16:36:28 -0400601 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500602 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
603 u32 defcontext_sid = 0;
Al Virobd323652018-12-13 15:04:59 -0500604 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500605
606 mutex_lock(&sbsec->lock);
607
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100608 if (!selinux_initialized(&selinux_state)) {
Al Virobd323652018-12-13 15:04:59 -0500609 if (!opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500610 /* Defer initialization until selinux_complete_init,
611 after the initial policy is loaded and the security
612 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500613 goto out;
614 }
615 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200616 pr_warn("SELinux: Unable to set superblock options "
Eric Paris744ba352008-04-17 11:52:44 -0400617 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500618 goto out;
619 }
David Quigley649f6e72013-05-22 12:50:36 -0400620 if (kern_flags && !set_kern_flags) {
621 /* Specifying internal flags without providing a place to
622 * place the results is not allowed */
623 rc = -EINVAL;
624 goto out;
625 }
Eric Parisc9180a52007-11-30 13:00:35 -0500626
627 /*
Eric Parise0007522008-03-05 10:31:54 -0500628 * Binary mount data FS will come through this function twice. Once
629 * from an explicit call and once from the generic calls from the vfs.
630 * Since the generic VFS calls will not contain any security mount data
631 * we need to skip the double mount verification.
632 *
633 * This does open a hole in which we will not notice if the first
634 * mount using this sb set explict options and a second mount using
635 * this sb does not set any security options. (The first options
636 * will be used for both mounts)
637 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500638 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Al Virobd323652018-12-13 15:04:59 -0500639 && !opts)
Eric Parisf5269712008-05-14 11:27:45 -0400640 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500641
Paul Moore2c971652016-04-19 16:36:28 -0400642 root_isec = backing_inode_security_novalidate(root);
643
Eric Parise0007522008-03-05 10:31:54 -0500644 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500645 * parse the mount options, check if they are valid sids.
646 * also check if someone is trying to mount the same sb more
647 * than once with different security options.
648 */
Al Virobd323652018-12-13 15:04:59 -0500649 if (opts) {
650 if (opts->fscontext) {
651 rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
652 if (rc)
653 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500654 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
655 fscontext_sid))
656 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500657 sbsec->flags |= FSCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500658 }
659 if (opts->context) {
660 rc = parse_sid(sb, opts->context, &context_sid);
661 if (rc)
662 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500663 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
664 context_sid))
665 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500666 sbsec->flags |= CONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500667 }
668 if (opts->rootcontext) {
669 rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
670 if (rc)
671 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500672 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
673 rootcontext_sid))
674 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500675 sbsec->flags |= ROOTCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500676 }
677 if (opts->defcontext) {
678 rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
679 if (rc)
680 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500681 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
682 defcontext_sid))
683 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500684 sbsec->flags |= DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500685 }
686 }
687
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500688 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500689 /* previously mounted with options, but not on this attempt? */
Al Virobd323652018-12-13 15:04:59 -0500690 if ((sbsec->flags & SE_MNTMASK) && !opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500691 goto out_double_mount;
692 rc = 0;
693 goto out;
694 }
695
James Morris089be432008-07-15 18:32:49 +1000696 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400697 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
698
Stephen Smalley8e014722015-06-04 16:22:17 -0400699 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700700 !strcmp(sb->s_type->name, "tracefs") ||
Hridya Valsaraju7a4b5192020-01-06 10:13:29 -0800701 !strcmp(sb->s_type->name, "binderfs") ||
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100702 !strcmp(sb->s_type->name, "pstore"))
703 sbsec->flags |= SE_SBGENFS;
704
705 if (!strcmp(sb->s_type->name, "sysfs") ||
Antonio Murdaca901ef842017-02-09 17:02:42 +0100706 !strcmp(sb->s_type->name, "cgroup") ||
707 !strcmp(sb->s_type->name, "cgroup2"))
Ondrej Mosnacekb7540262019-02-22 15:57:14 +0100708 sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR;
Eric Parisc9180a52007-11-30 13:00:35 -0500709
David Quigleyeb9ae682013-05-22 12:50:37 -0400710 if (!sbsec->behavior) {
711 /*
712 * Determine the labeling behavior to use for this
713 * filesystem type.
714 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500715 rc = security_fs_use(&selinux_state, sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400716 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +0200717 pr_warn("%s: security_fs_use(%s) returned %d\n",
David Quigleyeb9ae682013-05-22 12:50:37 -0400718 __func__, sb->s_type->name, rc);
719 goto out;
720 }
Eric Parisc9180a52007-11-30 13:00:35 -0500721 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500722
723 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500724 * If this is a user namespace mount and the filesystem type is not
725 * explicitly whitelisted, then no contexts are allowed on the command
726 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500727 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500728 if (sb->s_user_ns != &init_user_ns &&
729 strcmp(sb->s_type->name, "tmpfs") &&
730 strcmp(sb->s_type->name, "ramfs") &&
731 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500732 if (context_sid || fscontext_sid || rootcontext_sid ||
733 defcontext_sid) {
734 rc = -EACCES;
735 goto out;
736 }
737 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
738 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500739 rc = security_transition_sid(&selinux_state,
740 current_sid(),
741 current_sid(),
Seth Forsheeaad82892016-04-26 14:36:20 -0500742 SECCLASS_FILE, NULL,
743 &sbsec->mntpoint_sid);
744 if (rc)
745 goto out;
746 }
747 goto out_set_opts;
748 }
749
Eric Parisc9180a52007-11-30 13:00:35 -0500750 /* sets the context of the superblock for the fs being mounted. */
751 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100752 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500753 if (rc)
754 goto out;
755
756 sbsec->sid = fscontext_sid;
757 }
758
759 /*
760 * Switch to using mount point labeling behavior.
761 * sets the label used on all file below the mountpoint, and will set
762 * the superblock context if not already set.
763 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400764 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
765 sbsec->behavior = SECURITY_FS_USE_NATIVE;
766 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
767 }
768
Eric Parisc9180a52007-11-30 13:00:35 -0500769 if (context_sid) {
770 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100771 rc = may_context_mount_sb_relabel(context_sid, sbsec,
772 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500773 if (rc)
774 goto out;
775 sbsec->sid = context_sid;
776 } else {
David Howells275bb412008-11-14 10:39:19 +1100777 rc = may_context_mount_inode_relabel(context_sid, sbsec,
778 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500779 if (rc)
780 goto out;
781 }
782 if (!rootcontext_sid)
783 rootcontext_sid = context_sid;
784
785 sbsec->mntpoint_sid = context_sid;
786 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
787 }
788
789 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100790 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
791 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500792 if (rc)
793 goto out;
794
795 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500796 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500797 }
798
799 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400800 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
801 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500802 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200803 pr_warn("SELinux: defcontext option is "
Eric Parisc9180a52007-11-30 13:00:35 -0500804 "invalid for this filesystem type\n");
805 goto out;
806 }
807
808 if (defcontext_sid != sbsec->def_sid) {
809 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100810 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500811 if (rc)
812 goto out;
813 }
814
815 sbsec->def_sid = defcontext_sid;
816 }
817
Seth Forsheeaad82892016-04-26 14:36:20 -0500818out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500819 rc = sb_finish_set_opts(sb);
820out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700821 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500823out_double_mount:
824 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200825 pr_warn("SELinux: mount invalid. Same superblock, different "
Al Virobd323652018-12-13 15:04:59 -0500826 "security settings for (dev %s, type %s)\n", sb->s_id,
827 sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500828 goto out;
829}
830
Jeff Layton094f7b62013-04-01 08:14:24 -0400831static int selinux_cmp_sb_context(const struct super_block *oldsb,
832 const struct super_block *newsb)
833{
834 struct superblock_security_struct *old = oldsb->s_security;
835 struct superblock_security_struct *new = newsb->s_security;
836 char oldflags = old->flags & SE_MNTMASK;
837 char newflags = new->flags & SE_MNTMASK;
838
839 if (oldflags != newflags)
840 goto mismatch;
841 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
842 goto mismatch;
843 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
844 goto mismatch;
845 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
846 goto mismatch;
847 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500848 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
849 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400850 if (oldroot->sid != newroot->sid)
851 goto mismatch;
852 }
853 return 0;
854mismatch:
peter enderborgc103a912018-06-12 10:09:03 +0200855 pr_warn("SELinux: mount invalid. Same superblock, "
Jeff Layton094f7b62013-04-01 08:14:24 -0400856 "different security settings for (dev %s, "
857 "type %s)\n", newsb->s_id, newsb->s_type->name);
858 return -EBUSY;
859}
860
861static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400862 struct super_block *newsb,
863 unsigned long kern_flags,
864 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500865{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400866 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500867 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
868 struct superblock_security_struct *newsbsec = newsb->s_security;
869
870 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
871 int set_context = (oldsbsec->flags & CONTEXT_MNT);
872 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
873
Eric Paris0f5e6422008-04-21 16:24:11 -0400874 /*
875 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400876 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400877 */
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +0100878 if (!selinux_initialized(&selinux_state))
Jeff Layton094f7b62013-04-01 08:14:24 -0400879 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500880
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400881 /*
882 * Specifying internal flags without providing a place to
883 * place the results is not allowed.
884 */
885 if (kern_flags && !set_kern_flags)
886 return -EINVAL;
887
Eric Parisc9180a52007-11-30 13:00:35 -0500888 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500889 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500890
Jeff Layton094f7b62013-04-01 08:14:24 -0400891 /* if fs is reusing a sb, make sure that the contexts match */
J. Bruce Fields3815a242019-03-05 16:17:58 -0500892 if (newsbsec->flags & SE_SBINITIALIZED) {
893 if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
894 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
Jeff Layton094f7b62013-04-01 08:14:24 -0400895 return selinux_cmp_sb_context(oldsb, newsb);
J. Bruce Fields3815a242019-03-05 16:17:58 -0500896 }
Eric Paris5a552612008-04-09 14:08:35 -0400897
Eric Parisc9180a52007-11-30 13:00:35 -0500898 mutex_lock(&newsbsec->lock);
899
900 newsbsec->flags = oldsbsec->flags;
901
902 newsbsec->sid = oldsbsec->sid;
903 newsbsec->def_sid = oldsbsec->def_sid;
904 newsbsec->behavior = oldsbsec->behavior;
905
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400906 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
907 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500908 rc = security_fs_use(&selinux_state, newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400909 if (rc)
910 goto out;
911 }
912
913 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
914 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
915 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
916 }
917
Eric Parisc9180a52007-11-30 13:00:35 -0500918 if (set_context) {
919 u32 sid = oldsbsec->mntpoint_sid;
920
921 if (!set_fscontext)
922 newsbsec->sid = sid;
923 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500924 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500925 newisec->sid = sid;
926 }
927 newsbsec->mntpoint_sid = sid;
928 }
929 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500930 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
931 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500932
933 newisec->sid = oldisec->sid;
934 }
935
936 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400937out:
Eric Parisc9180a52007-11-30 13:00:35 -0500938 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400939 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500940}
941
Al Viroba641862018-12-14 20:28:15 -0500942static int selinux_add_opt(int token, const char *s, void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500943{
Al Viroba641862018-12-14 20:28:15 -0500944 struct selinux_mnt_opts *opts = *mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500945
Al Viroda3d76a2018-12-17 10:14:16 -0500946 if (token == Opt_seclabel) /* eaten and completely ignored */
Al Viro169d68efb2018-12-14 22:44:50 -0500947 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500948
Al Viroba641862018-12-14 20:28:15 -0500949 if (!opts) {
950 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
951 if (!opts)
952 return -ENOMEM;
953 *mnt_opts = opts;
954 }
955 if (!s)
956 return -ENOMEM;
957 switch (token) {
958 case Opt_context:
959 if (opts->context || opts->defcontext)
960 goto Einval;
961 opts->context = s;
962 break;
963 case Opt_fscontext:
964 if (opts->fscontext)
965 goto Einval;
966 opts->fscontext = s;
967 break;
968 case Opt_rootcontext:
969 if (opts->rootcontext)
970 goto Einval;
971 opts->rootcontext = s;
972 break;
973 case Opt_defcontext:
974 if (opts->context || opts->defcontext)
975 goto Einval;
976 opts->defcontext = s;
977 break;
978 }
979 return 0;
980Einval:
981 pr_warn(SEL_MOUNT_FAIL_MSG);
Al Viroba641862018-12-14 20:28:15 -0500982 return -EINVAL;
983}
Eric Parisc9180a52007-11-30 13:00:35 -0500984
Al Viro757cbe52018-12-14 23:42:21 -0500985static int selinux_add_mnt_opt(const char *option, const char *val, int len,
986 void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500987{
Al Viro757cbe52018-12-14 23:42:21 -0500988 int token = Opt_error;
989 int rc, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500990
Al Viro757cbe52018-12-14 23:42:21 -0500991 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
992 if (strcmp(option, tokens[i].name) == 0) {
993 token = tokens[i].opt;
Eric Parisc9180a52007-11-30 13:00:35 -0500994 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500995 }
996 }
997
Al Viro757cbe52018-12-14 23:42:21 -0500998 if (token == Opt_error)
999 return -EINVAL;
Eric Parise0007522008-03-05 10:31:54 -05001000
Gen Zhange2e0e092019-06-12 21:28:21 +08001001 if (token != Opt_seclabel) {
Al Viro757cbe52018-12-14 23:42:21 -05001002 val = kmemdup_nul(val, len, GFP_KERNEL);
Gen Zhange2e0e092019-06-12 21:28:21 +08001003 if (!val) {
1004 rc = -ENOMEM;
1005 goto free_opt;
1006 }
1007 }
Al Viro757cbe52018-12-14 23:42:21 -05001008 rc = selinux_add_opt(token, val, mnt_opts);
1009 if (unlikely(rc)) {
1010 kfree(val);
Gen Zhange2e0e092019-06-12 21:28:21 +08001011 goto free_opt;
1012 }
1013 return rc;
1014
1015free_opt:
1016 if (*mnt_opts) {
1017 selinux_free_mnt_opts(*mnt_opts);
1018 *mnt_opts = NULL;
Al Viro757cbe52018-12-14 23:42:21 -05001019 }
1020 return rc;
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
Al Viroe3489f82018-12-13 00:24:36 -05001029 rc = security_sid_to_context(&selinux_state, sid,
1030 &context, &len);
1031 if (!rc) {
1032 bool has_comma = context && strchr(context, ',');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
David Howells442155c2018-11-01 23:07:24 +00001034 seq_putc(m, '=');
Eric Paris2069f452008-07-04 09:47:13 +10001035 if (has_comma)
1036 seq_putc(m, '\"');
Al Viroe3489f82018-12-13 00:24:36 -05001037 seq_escape(m, context, "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001038 if (has_comma)
1039 seq_putc(m, '\"');
1040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return rc;
1043}
Eric Paris2069f452008-07-04 09:47:13 +10001044
1045static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1046{
Al Viroe3489f82018-12-13 00:24:36 -05001047 struct superblock_security_struct *sbsec = sb->s_security;
Eric Paris2069f452008-07-04 09:47:13 +10001048 int rc;
1049
Al Viroe3489f82018-12-13 00:24:36 -05001050 if (!(sbsec->flags & SE_SBINITIALIZED))
1051 return 0;
1052
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01001053 if (!selinux_initialized(&selinux_state))
Al Viroe3489f82018-12-13 00:24:36 -05001054 return 0;
1055
1056 if (sbsec->flags & FSCONTEXT_MNT) {
1057 seq_putc(m, ',');
1058 seq_puts(m, FSCONTEXT_STR);
1059 rc = show_sid(m, sbsec->sid);
1060 if (rc)
1061 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001062 }
Al Viroe3489f82018-12-13 00:24:36 -05001063 if (sbsec->flags & CONTEXT_MNT) {
1064 seq_putc(m, ',');
1065 seq_puts(m, CONTEXT_STR);
1066 rc = show_sid(m, sbsec->mntpoint_sid);
1067 if (rc)
1068 return rc;
1069 }
1070 if (sbsec->flags & DEFCONTEXT_MNT) {
1071 seq_putc(m, ',');
1072 seq_puts(m, DEFCONTEXT_STR);
1073 rc = show_sid(m, sbsec->def_sid);
1074 if (rc)
1075 return rc;
1076 }
1077 if (sbsec->flags & ROOTCONTEXT_MNT) {
1078 struct dentry *root = sbsec->sb->s_root;
1079 struct inode_security_struct *isec = backing_inode_security(root);
1080 seq_putc(m, ',');
1081 seq_puts(m, ROOTCONTEXT_STR);
1082 rc = show_sid(m, isec->sid);
1083 if (rc)
1084 return rc;
1085 }
1086 if (sbsec->flags & SBLABEL_MNT) {
1087 seq_putc(m, ',');
David Howells442155c2018-11-01 23:07:24 +00001088 seq_puts(m, SECLABEL_STR);
Al Viroe3489f82018-12-13 00:24:36 -05001089 }
1090 return 0;
Eric Paris2069f452008-07-04 09:47:13 +10001091}
1092
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093static inline u16 inode_mode_to_security_class(umode_t mode)
1094{
1095 switch (mode & S_IFMT) {
1096 case S_IFSOCK:
1097 return SECCLASS_SOCK_FILE;
1098 case S_IFLNK:
1099 return SECCLASS_LNK_FILE;
1100 case S_IFREG:
1101 return SECCLASS_FILE;
1102 case S_IFBLK:
1103 return SECCLASS_BLK_FILE;
1104 case S_IFDIR:
1105 return SECCLASS_DIR;
1106 case S_IFCHR:
1107 return SECCLASS_CHR_FILE;
1108 case S_IFIFO:
1109 return SECCLASS_FIFO_FILE;
1110
1111 }
1112
1113 return SECCLASS_FILE;
1114}
1115
James Morris13402582005-09-30 14:24:34 -04001116static inline int default_protocol_stream(int protocol)
1117{
1118 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1119}
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{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001128 int 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;
1269#if PF_MAX > 45
Stephen Smalleyda69a532017-01-09 10:07:30 -05001270#error New address family defined, please update this function.
1271#endif
1272 }
1273 }
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 return SECCLASS_SOCKET;
1276}
1277
Stephen Smalley134509d2015-06-04 16:22:17 -04001278static int selinux_genfs_get_sid(struct dentry *dentry,
1279 u16 tclass,
1280 u16 flags,
1281 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001283 int rc;
Al Virofc640052016-04-10 01:33:30 -04001284 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001285 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Eric Paris828dfe12008-04-17 13:17:49 -04001287 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 if (!buffer)
1289 return -ENOMEM;
1290
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001291 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1292 if (IS_ERR(path))
1293 rc = PTR_ERR(path);
1294 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001295 if (flags & SE_SBPROC) {
1296 /* each process gets a /proc/PID/ entry. Strip off the
1297 * PID part to get a valid selinux labeling.
1298 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1299 while (path[1] >= '0' && path[1] <= '9') {
1300 path[1] = '/';
1301 path++;
1302 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001303 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001304 rc = security_genfs_sid(&selinux_state, sb->s_type->name,
1305 path, tclass, sid);
Stephen Smalley7bb185e2018-09-04 16:51:36 -04001306 if (rc == -ENOENT) {
1307 /* No match in policy, mark as unlabeled. */
1308 *sid = SECINITSID_UNLABELED;
1309 rc = 0;
1310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 free_page((unsigned long)buffer);
1313 return rc;
1314}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001316static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
1317 u32 def_sid, u32 *sid)
1318{
1319#define INITCONTEXTLEN 255
1320 char *context;
1321 unsigned int len;
1322 int rc;
1323
1324 len = INITCONTEXTLEN;
1325 context = kmalloc(len + 1, GFP_NOFS);
1326 if (!context)
1327 return -ENOMEM;
1328
1329 context[len] = '\0';
1330 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1331 if (rc == -ERANGE) {
1332 kfree(context);
1333
1334 /* Need a larger buffer. Query for the right size. */
1335 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
1336 if (rc < 0)
1337 return rc;
1338
1339 len = rc;
1340 context = kmalloc(len + 1, GFP_NOFS);
1341 if (!context)
1342 return -ENOMEM;
1343
1344 context[len] = '\0';
1345 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
1346 context, len);
1347 }
1348 if (rc < 0) {
1349 kfree(context);
1350 if (rc != -ENODATA) {
1351 pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n",
1352 __func__, -rc, inode->i_sb->s_id, inode->i_ino);
1353 return rc;
1354 }
1355 *sid = def_sid;
1356 return 0;
1357 }
1358
1359 rc = security_context_to_sid_default(&selinux_state, context, rc, sid,
1360 def_sid, GFP_NOFS);
1361 if (rc) {
1362 char *dev = inode->i_sb->s_id;
1363 unsigned long ino = inode->i_ino;
1364
1365 if (rc == -EINVAL) {
1366 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",
1367 ino, dev, context);
1368 } else {
1369 pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n",
1370 __func__, context, -rc, dev, ino);
1371 }
1372 }
1373 kfree(context);
1374 return 0;
1375}
1376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377/* The inode's security attributes must be initialized before first use. */
1378static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1379{
1380 struct superblock_security_struct *sbsec = NULL;
Casey Schaufler80788c22018-09-21 17:19:11 -07001381 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001382 u32 task_sid, sid = 0;
1383 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 struct dentry *dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001387 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001388 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001390 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001391 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001392 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001394 if (isec->sclass == SECCLASS_FILE)
1395 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001398 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 /* Defer initialization until selinux_complete_init,
1400 after the initial policy is loaded and the security
1401 server is ready to handle calls. */
1402 spin_lock(&sbsec->isec_lock);
1403 if (list_empty(&isec->list))
1404 list_add(&isec->list, &sbsec->isec_head);
1405 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001406 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 }
1408
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001409 sclass = isec->sclass;
1410 task_sid = isec->task_sid;
1411 sid = isec->sid;
1412 isec->initialized = LABEL_PENDING;
1413 spin_unlock(&isec->lock);
1414
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001416 case SECURITY_FS_USE_NATIVE:
1417 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001419 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001420 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 break;
1422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 /* Need a dentry, since the xattr API requires one.
1424 Life would be simpler if we could just pass the inode. */
1425 if (opt_dentry) {
1426 /* Called from d_instantiate or d_splice_alias. */
1427 dentry = dget(opt_dentry);
1428 } else {
Al Virob1271252018-04-25 10:28:38 -04001429 /*
1430 * Called from selinux_complete_init, try to find a dentry.
1431 * Some filesystems really want a connected one, so try
1432 * that first. We could split SECURITY_FS_USE_XATTR in
1433 * two, depending upon that...
1434 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001436 if (!dentry)
1437 dentry = d_find_any_alias(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 }
1439 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001440 /*
1441 * this is can be hit on boot when a file is accessed
1442 * before the policy is loaded. When we load policy we
1443 * may find inodes that have no dentry on the
1444 * sbsec->isec_head list. No reason to complain as these
1445 * will get fixed up the next time we go through
1446 * inode_doinit with a dentry, before these inodes could
1447 * be used again by userspace.
1448 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001449 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 }
1451
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001452 rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
1453 &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 dput(dentry);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001455 if (rc)
1456 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 break;
1458 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001459 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 break;
1461 case SECURITY_FS_USE_TRANS:
1462 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001463 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 /* Try to obtain a transition SID. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001466 rc = security_transition_sid(&selinux_state, task_sid, sid,
1467 sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001469 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001471 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001472 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001473 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001475 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001476 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Stephen Smalley134509d2015-06-04 16:22:17 -04001478 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001479 /* We must have a dentry to determine the label on
1480 * procfs inodes */
Al Virob1271252018-04-25 10:28:38 -04001481 if (opt_dentry) {
Paul Mooref64410e2014-03-19 16:46:18 -04001482 /* Called from d_instantiate or
1483 * d_splice_alias. */
1484 dentry = dget(opt_dentry);
Al Virob1271252018-04-25 10:28:38 -04001485 } else {
Paul Mooref64410e2014-03-19 16:46:18 -04001486 /* Called from selinux_complete_init, try to
Al Virob1271252018-04-25 10:28:38 -04001487 * find a dentry. Some filesystems really want
1488 * a connected one, so try that first.
1489 */
Paul Mooref64410e2014-03-19 16:46:18 -04001490 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001491 if (!dentry)
1492 dentry = d_find_any_alias(inode);
1493 }
Paul Mooref64410e2014-03-19 16:46:18 -04001494 /*
1495 * This can be hit on boot when a file is accessed
1496 * before the policy is loaded. When we load policy we
1497 * may find inodes that have no dentry on the
1498 * sbsec->isec_head list. No reason to complain as
1499 * these will get fixed up the next time we go through
1500 * inode_doinit() with a dentry, before these inodes
1501 * could be used again by userspace.
1502 */
1503 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001504 goto out;
1505 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001506 sbsec->flags, &sid);
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001507 if (rc) {
1508 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001509 goto out;
Ondrej Mosnacekb7540262019-02-22 15:57:14 +01001510 }
1511
1512 if ((sbsec->flags & SE_SBGENFS_XATTR) &&
1513 (inode->i_opflags & IOP_XATTR)) {
1514 rc = inode_doinit_use_xattr(inode, dentry,
1515 sid, &sid);
1516 if (rc) {
1517 dput(dentry);
1518 goto out;
1519 }
1520 }
1521 dput(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 }
1523 break;
1524 }
1525
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001526out:
1527 spin_lock(&isec->lock);
1528 if (isec->initialized == LABEL_PENDING) {
1529 if (!sid || rc) {
1530 isec->initialized = LABEL_INVALID;
1531 goto out_unlock;
1532 }
1533
1534 isec->initialized = LABEL_INITIALIZED;
1535 isec->sid = sid;
1536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Eric Paris23970742006-09-25 23:32:01 -07001538out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001539 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 return rc;
1541}
1542
1543/* Convert a Linux signal to an access vector. */
1544static inline u32 signal_to_av(int sig)
1545{
1546 u32 perm = 0;
1547
1548 switch (sig) {
1549 case SIGCHLD:
1550 /* Commonly granted from child to parent. */
1551 perm = PROCESS__SIGCHLD;
1552 break;
1553 case SIGKILL:
1554 /* Cannot be caught or ignored */
1555 perm = PROCESS__SIGKILL;
1556 break;
1557 case SIGSTOP:
1558 /* Cannot be caught or ignored */
1559 perm = PROCESS__SIGSTOP;
1560 break;
1561 default:
1562 /* All other signals. */
1563 perm = PROCESS__SIGNAL;
1564 break;
1565 }
1566
1567 return perm;
1568}
1569
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001570#if CAP_LAST_CAP > 63
1571#error Fix SELinux to handle capabilities > 63.
1572#endif
1573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001575static int cred_has_capability(const struct cred *cred,
Micah Mortonc1a85a02019-01-07 16:10:53 -08001576 int cap, unsigned int opts, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577{
Thomas Liu2bf49692009-07-14 12:14:09 -04001578 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001579 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001580 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001581 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001582 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001583 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Eric Paris50c205f2012-04-04 15:01:43 -04001585 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 ad.u.cap = cap;
1587
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001588 switch (CAP_TO_INDEX(cap)) {
1589 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001590 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001591 break;
1592 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001593 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001594 break;
1595 default:
peter enderborgc103a912018-06-12 10:09:03 +02001596 pr_err("SELinux: out of range capability %d\n", cap);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001597 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001598 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001599 }
Eric Paris06112162008-11-11 22:02:50 +11001600
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001601 rc = avc_has_perm_noaudit(&selinux_state,
1602 sid, sid, sclass, av, 0, &avd);
Micah Mortonc1a85a02019-01-07 16:10:53 -08001603 if (!(opts & CAP_OPT_NOAUDIT)) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001604 int rc2 = avc_audit(&selinux_state,
1605 sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001606 if (rc2)
1607 return rc2;
1608 }
Eric Paris06112162008-11-11 22:02:50 +11001609 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610}
1611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612/* Check whether a task has a particular permission to an inode.
1613 The 'adp' parameter is optional and allows other audit
1614 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001615static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 struct inode *inode,
1617 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001618 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001621 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
David Howellse0e81732009-09-02 09:13:40 +01001623 validate_creds(cred);
1624
Eric Paris828dfe12008-04-17 13:17:49 -04001625 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001626 return 0;
1627
David Howells88e67f32008-11-14 10:39:21 +11001628 sid = cred_sid(cred);
Casey Schaufler80788c22018-09-21 17:19:11 -07001629 isec = selinux_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001631 return avc_has_perm(&selinux_state,
1632 sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633}
1634
1635/* Same as inode_has_perm, but pass explicit audit data containing
1636 the dentry to help the auditing code to more easily generate the
1637 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001638static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 struct dentry *dentry,
1640 u32 av)
1641{
David Howellsc6f493d2015-03-17 22:26:22 +00001642 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001643 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001644
Eric Paris50c205f2012-04-04 15:01:43 -04001645 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001646 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001647 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001648 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001649}
1650
1651/* Same as inode_has_perm, but pass explicit audit data containing
1652 the path to help the auditing code to more easily generate the
1653 pathname if needed. */
1654static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001655 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001656 u32 av)
1657{
David Howellsc6f493d2015-03-17 22:26:22 +00001658 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001659 struct common_audit_data ad;
1660
Eric Paris50c205f2012-04-04 15:01:43 -04001661 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001662 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001663 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001664 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665}
1666
David Howells13f8e982013-06-13 23:37:55 +01001667/* Same as path_has_perm, but uses the inode from the file struct. */
1668static inline int file_path_has_perm(const struct cred *cred,
1669 struct file *file,
1670 u32 av)
1671{
1672 struct common_audit_data ad;
1673
Vivek Goyal43af5de2016-09-09 11:37:49 -04001674 ad.type = LSM_AUDIT_DATA_FILE;
1675 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001676 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001677}
1678
Chenbo Fengf66e4482017-10-18 13:00:26 -07001679#ifdef CONFIG_BPF_SYSCALL
1680static int bpf_fd_pass(struct file *file, u32 sid);
1681#endif
1682
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683/* Check whether a task can use an open file descriptor to
1684 access an inode in a given way. Check access to the
1685 descriptor itself, and then use dentry_has_perm to
1686 check a particular permission to the file.
1687 Access to the descriptor is implicitly granted if it
1688 has the same SID as the process. If av is zero, then
1689 access to the file is not checked, e.g. for cases
1690 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001691static int file_has_perm(const struct cred *cred,
1692 struct file *file,
1693 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694{
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07001695 struct file_security_struct *fsec = selinux_file(file);
Al Viro496ad9a2013-01-23 17:07:38 -05001696 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001697 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001698 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 int rc;
1700
Vivek Goyal43af5de2016-09-09 11:37:49 -04001701 ad.type = LSM_AUDIT_DATA_FILE;
1702 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
David Howells275bb412008-11-14 10:39:19 +11001704 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001705 rc = avc_has_perm(&selinux_state,
1706 sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 SECCLASS_FD,
1708 FD__USE,
1709 &ad);
1710 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001711 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 }
1713
Chenbo Fengf66e4482017-10-18 13:00:26 -07001714#ifdef CONFIG_BPF_SYSCALL
1715 rc = bpf_fd_pass(file, cred_sid(cred));
1716 if (rc)
1717 return rc;
1718#endif
1719
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001721 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001723 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
David Howells88e67f32008-11-14 10:39:21 +11001725out:
1726 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727}
1728
David Howellsc3c188b2015-07-10 17:19:58 -04001729/*
1730 * Determine the label for an inode that might be unioned.
1731 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001732static int
1733selinux_determine_inode_label(const struct task_security_struct *tsec,
1734 struct inode *dir,
1735 const struct qstr *name, u16 tclass,
1736 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001737{
1738 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001739
1740 if ((sbsec->flags & SE_SBINITIALIZED) &&
1741 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1742 *_new_isid = sbsec->mntpoint_sid;
1743 } else if ((sbsec->flags & SBLABEL_MNT) &&
1744 tsec->create_sid) {
1745 *_new_isid = tsec->create_sid;
1746 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001747 const struct inode_security_struct *dsec = inode_security(dir);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001748 return security_transition_sid(&selinux_state, tsec->sid,
1749 dsec->sid, tclass,
David Howellsc3c188b2015-07-10 17:19:58 -04001750 name, _new_isid);
1751 }
1752
1753 return 0;
1754}
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756/* Check whether a task can create a file. */
1757static int may_create(struct inode *dir,
1758 struct dentry *dentry,
1759 u16 tclass)
1760{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07001761 const struct task_security_struct *tsec = selinux_cred(current_cred());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 struct inode_security_struct *dsec;
1763 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001764 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001765 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 int rc;
1767
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001768 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 sbsec = dir->i_sb->s_security;
1770
David Howells275bb412008-11-14 10:39:19 +11001771 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001772
Eric Paris50c205f2012-04-04 15:01:43 -04001773 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001774 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001776 rc = avc_has_perm(&selinux_state,
1777 sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 DIR__ADD_NAME | DIR__SEARCH,
1779 &ad);
1780 if (rc)
1781 return rc;
1782
Yang Guo210a2922019-12-12 10:02:24 +08001783 rc = selinux_determine_inode_label(tsec, dir, &dentry->d_name, tclass,
1784 &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001785 if (rc)
1786 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001788 rc = avc_has_perm(&selinux_state,
1789 sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 if (rc)
1791 return rc;
1792
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001793 return avc_has_perm(&selinux_state,
1794 newsid, sbsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 SECCLASS_FILESYSTEM,
1796 FILESYSTEM__ASSOCIATE, &ad);
1797}
1798
Eric Paris828dfe12008-04-17 13:17:49 -04001799#define MAY_LINK 0
1800#define MAY_UNLINK 1
1801#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803/* Check whether a task can link, unlink, or rmdir a file/directory. */
1804static int may_link(struct inode *dir,
1805 struct dentry *dentry,
1806 int kind)
1807
1808{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001810 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001811 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 u32 av;
1813 int rc;
1814
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001815 dsec = inode_security(dir);
1816 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Eric Paris50c205f2012-04-04 15:01:43 -04001818 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001819 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 av = DIR__SEARCH;
1822 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001823 rc = avc_has_perm(&selinux_state,
1824 sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 if (rc)
1826 return rc;
1827
1828 switch (kind) {
1829 case MAY_LINK:
1830 av = FILE__LINK;
1831 break;
1832 case MAY_UNLINK:
1833 av = FILE__UNLINK;
1834 break;
1835 case MAY_RMDIR:
1836 av = DIR__RMDIR;
1837 break;
1838 default:
peter enderborgc103a912018-06-12 10:09:03 +02001839 pr_warn("SELinux: %s: unrecognized kind %d\n",
Eric Paris744ba352008-04-17 11:52:44 -04001840 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 return 0;
1842 }
1843
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001844 rc = avc_has_perm(&selinux_state,
1845 sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 return rc;
1847}
1848
1849static inline int may_rename(struct inode *old_dir,
1850 struct dentry *old_dentry,
1851 struct inode *new_dir,
1852 struct dentry *new_dentry)
1853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001855 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001856 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 u32 av;
1858 int old_is_dir, new_is_dir;
1859 int rc;
1860
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001861 old_dsec = inode_security(old_dir);
1862 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001863 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001864 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Eric Paris50c205f2012-04-04 15:01:43 -04001866 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
Eric Parisa2694342011-04-25 13:10:27 -04001868 ad.u.dentry = old_dentry;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001869 rc = avc_has_perm(&selinux_state,
1870 sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1872 if (rc)
1873 return rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001874 rc = avc_has_perm(&selinux_state,
1875 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 old_isec->sclass, FILE__RENAME, &ad);
1877 if (rc)
1878 return rc;
1879 if (old_is_dir && new_dir != old_dir) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001880 rc = avc_has_perm(&selinux_state,
1881 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 old_isec->sclass, DIR__REPARENT, &ad);
1883 if (rc)
1884 return rc;
1885 }
1886
Eric Parisa2694342011-04-25 13:10:27 -04001887 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001889 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 av |= DIR__REMOVE_NAME;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001891 rc = avc_has_perm(&selinux_state,
1892 sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 if (rc)
1894 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001895 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001896 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001897 new_is_dir = d_is_dir(new_dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001898 rc = avc_has_perm(&selinux_state,
1899 sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 new_isec->sclass,
1901 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1902 if (rc)
1903 return rc;
1904 }
1905
1906 return 0;
1907}
1908
1909/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001910static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 struct super_block *sb,
1912 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001913 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001916 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 sbsec = sb->s_security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001919 return avc_has_perm(&selinux_state,
1920 sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921}
1922
1923/* Convert a Linux mode and permission mask to an access vector. */
1924static inline u32 file_mask_to_av(int mode, int mask)
1925{
1926 u32 av = 0;
1927
Al Virodba19c62011-07-25 20:49:29 -04001928 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 if (mask & MAY_EXEC)
1930 av |= FILE__EXECUTE;
1931 if (mask & MAY_READ)
1932 av |= FILE__READ;
1933
1934 if (mask & MAY_APPEND)
1935 av |= FILE__APPEND;
1936 else if (mask & MAY_WRITE)
1937 av |= FILE__WRITE;
1938
1939 } else {
1940 if (mask & MAY_EXEC)
1941 av |= DIR__SEARCH;
1942 if (mask & MAY_WRITE)
1943 av |= DIR__WRITE;
1944 if (mask & MAY_READ)
1945 av |= DIR__READ;
1946 }
1947
1948 return av;
1949}
1950
1951/* Convert a Linux file to an access vector. */
1952static inline u32 file_to_av(struct file *file)
1953{
1954 u32 av = 0;
1955
1956 if (file->f_mode & FMODE_READ)
1957 av |= FILE__READ;
1958 if (file->f_mode & FMODE_WRITE) {
1959 if (file->f_flags & O_APPEND)
1960 av |= FILE__APPEND;
1961 else
1962 av |= FILE__WRITE;
1963 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001964 if (!av) {
1965 /*
1966 * Special file opened with flags 3 for ioctl-only use.
1967 */
1968 av = FILE__IOCTL;
1969 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
1971 return av;
1972}
1973
Eric Paris8b6a5a32008-10-29 17:06:46 -04001974/*
1975 * Convert a file to an access vector and include the correct open
1976 * open permission.
1977 */
1978static inline u32 open_file_to_av(struct file *file)
1979{
1980 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04001981 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04001982
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001983 if (selinux_policycap_openperm() &&
1984 inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04001985 av |= FILE__OPEN;
1986
Eric Paris8b6a5a32008-10-29 17:06:46 -04001987 return av;
1988}
1989
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990/* Hook functions begin here. */
1991
Stephen Smalley79af7302015-01-21 10:54:10 -05001992static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1993{
1994 u32 mysid = current_sid();
1995 u32 mgrsid = task_sid(mgr);
1996
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001997 return avc_has_perm(&selinux_state,
1998 mysid, mgrsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05001999 BINDER__SET_CONTEXT_MGR, NULL);
2000}
2001
2002static int selinux_binder_transaction(struct task_struct *from,
2003 struct task_struct *to)
2004{
2005 u32 mysid = current_sid();
2006 u32 fromsid = task_sid(from);
2007 u32 tosid = task_sid(to);
2008 int rc;
2009
2010 if (mysid != fromsid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002011 rc = avc_has_perm(&selinux_state,
2012 mysid, fromsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002013 BINDER__IMPERSONATE, NULL);
2014 if (rc)
2015 return rc;
2016 }
2017
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002018 return avc_has_perm(&selinux_state,
2019 fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
Stephen Smalley79af7302015-01-21 10:54:10 -05002020 NULL);
2021}
2022
2023static int selinux_binder_transfer_binder(struct task_struct *from,
2024 struct task_struct *to)
2025{
2026 u32 fromsid = task_sid(from);
2027 u32 tosid = task_sid(to);
2028
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002029 return avc_has_perm(&selinux_state,
2030 fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002031 NULL);
2032}
2033
2034static int selinux_binder_transfer_file(struct task_struct *from,
2035 struct task_struct *to,
2036 struct file *file)
2037{
2038 u32 sid = task_sid(to);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07002039 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002040 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002041 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002042 struct common_audit_data ad;
2043 int rc;
2044
2045 ad.type = LSM_AUDIT_DATA_PATH;
2046 ad.u.path = file->f_path;
2047
2048 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002049 rc = avc_has_perm(&selinux_state,
2050 sid, fsec->sid,
Stephen Smalley79af7302015-01-21 10:54:10 -05002051 SECCLASS_FD,
2052 FD__USE,
2053 &ad);
2054 if (rc)
2055 return rc;
2056 }
2057
Chenbo Fengf66e4482017-10-18 13:00:26 -07002058#ifdef CONFIG_BPF_SYSCALL
2059 rc = bpf_fd_pass(file, sid);
2060 if (rc)
2061 return rc;
2062#endif
2063
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002064 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002065 return 0;
2066
Paul Moore20cdef82016-04-04 14:14:42 -04002067 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002068 return avc_has_perm(&selinux_state,
2069 sid, isec->sid, isec->sclass, file_to_av(file),
Stephen Smalley79af7302015-01-21 10:54:10 -05002070 &ad);
2071}
2072
Ingo Molnar9e488582009-05-07 19:26:19 +10002073static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002074 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002076 u32 sid = current_sid();
2077 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002078
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002079 if (mode & PTRACE_MODE_READ)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002080 return avc_has_perm(&selinux_state,
2081 sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002082
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002083 return avc_has_perm(&selinux_state,
2084 sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002085}
2086
2087static int selinux_ptrace_traceme(struct task_struct *parent)
2088{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002089 return avc_has_perm(&selinux_state,
2090 task_sid(parent), current_sid(), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002091 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092}
2093
2094static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002095 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002097 return avc_has_perm(&selinux_state,
2098 current_sid(), task_sid(target), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002099 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100}
2101
David Howellsd84f4f92008-11-14 10:39:23 +11002102static int selinux_capset(struct cred *new, const struct cred *old,
2103 const kernel_cap_t *effective,
2104 const kernel_cap_t *inheritable,
2105 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002107 return avc_has_perm(&selinux_state,
2108 cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002109 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110}
2111
James Morris5626d3e2009-01-30 10:05:06 +11002112/*
2113 * (This comment used to live with the selinux_task_setuid hook,
2114 * which was removed).
2115 *
2116 * Since setuid only affects the current process, and since the SELinux
2117 * controls are not based on the Linux identity attributes, SELinux does not
2118 * need to control this operation. However, SELinux does control the use of
2119 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2120 */
2121
Eric Paris6a9de492012-01-03 12:25:14 -05002122static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002123 int cap, unsigned int opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124{
Micah Mortonc1a85a02019-01-07 16:10:53 -08002125 return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126}
2127
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2129{
David Howells88e67f32008-11-14 10:39:21 +11002130 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 int rc = 0;
2132
2133 if (!sb)
2134 return 0;
2135
2136 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002137 case Q_SYNC:
2138 case Q_QUOTAON:
2139 case Q_QUOTAOFF:
2140 case Q_SETINFO:
2141 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002142 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002143 break;
2144 case Q_GETFMT:
2145 case Q_GETINFO:
2146 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002147 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002148 break;
2149 default:
2150 rc = 0; /* let the kernel handle invalid cmds */
2151 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 }
2153 return rc;
2154}
2155
2156static int selinux_quota_on(struct dentry *dentry)
2157{
David Howells88e67f32008-11-14 10:39:21 +11002158 const struct cred *cred = current_cred();
2159
Eric Paris2875fa02011-04-28 16:04:24 -04002160 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161}
2162
Eric Paris12b30522010-11-15 18:36:29 -05002163static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002166 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2167 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002168 return avc_has_perm(&selinux_state,
2169 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002170 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002171 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2172 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2173 /* Set level of messages printed to console */
2174 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002175 return avc_has_perm(&selinux_state,
2176 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002177 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2178 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002180 /* All other syslog types */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002181 return avc_has_perm(&selinux_state,
2182 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002183 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184}
2185
2186/*
2187 * Check that a process has enough memory to allocate a new virtual
2188 * mapping. 0 means there is enough memory for the allocation to
2189 * succeed and -ENOMEM implies there is not.
2190 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 * Do not audit the selinux permission check, as this is applied to all
2192 * processes that allocate mappings.
2193 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002194static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195{
2196 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002198 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Micah Mortonc1a85a02019-01-07 16:10:53 -08002199 CAP_OPT_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 if (rc == 0)
2201 cap_sys_admin = 1;
2202
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002203 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204}
2205
2206/* binprm security operations */
2207
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002208static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002209{
2210 u32 sid = 0;
2211 struct task_struct *tracer;
2212
2213 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002214 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002215 if (tracer)
2216 sid = task_sid(tracer);
2217 rcu_read_unlock();
2218
2219 return sid;
2220}
2221
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002222static int check_nnp_nosuid(const struct linux_binprm *bprm,
2223 const struct task_security_struct *old_tsec,
2224 const struct task_security_struct *new_tsec)
2225{
2226 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002227 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002228 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002229 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002230
2231 if (!nnp && !nosuid)
2232 return 0; /* neither NNP nor nosuid */
2233
2234 if (new_tsec->sid == old_tsec->sid)
2235 return 0; /* No change in credentials */
2236
2237 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002238 * If the policy enables the nnp_nosuid_transition policy capability,
2239 * then we permit transitions under NNP or nosuid if the
2240 * policy allows the corresponding permission between
2241 * the old and new contexts.
2242 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002243 if (selinux_policycap_nnp_nosuid_transition()) {
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002244 av = 0;
2245 if (nnp)
2246 av |= PROCESS2__NNP_TRANSITION;
2247 if (nosuid)
2248 av |= PROCESS2__NOSUID_TRANSITION;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002249 rc = avc_has_perm(&selinux_state,
2250 old_tsec->sid, new_tsec->sid,
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002251 SECCLASS_PROCESS2, av, NULL);
2252 if (!rc)
2253 return 0;
2254 }
2255
2256 /*
2257 * We also permit NNP or nosuid transitions to bounded SIDs,
2258 * i.e. SIDs that are guaranteed to only be allowed a subset
2259 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002260 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002261 rc = security_bounded_transition(&selinux_state, old_tsec->sid,
2262 new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002263 if (!rc)
2264 return 0;
2265
2266 /*
2267 * On failure, preserve the errno values for NNP vs nosuid.
2268 * NNP: Operation not permitted for caller.
2269 * nosuid: Permission denied to file.
2270 */
2271 if (nnp)
2272 return -EPERM;
2273 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002274}
2275
David Howellsa6f76f22008-11-14 10:39:24 +11002276static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277{
David Howellsa6f76f22008-11-14 10:39:24 +11002278 const struct task_security_struct *old_tsec;
2279 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002281 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002282 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 int rc;
2284
David Howellsa6f76f22008-11-14 10:39:24 +11002285 /* SELinux context only depends on initial program or script and not
2286 * the script interpreter */
Kees Cookddb4a142017-07-18 15:25:23 -07002287 if (bprm->called_set_creds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 return 0;
2289
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002290 old_tsec = selinux_cred(current_cred());
2291 new_tsec = selinux_cred(bprm->cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002292 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
2294 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002295 new_tsec->sid = old_tsec->sid;
2296 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
Michael LeMay28eba5b2006-06-27 02:53:42 -07002298 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002299 new_tsec->create_sid = 0;
2300 new_tsec->keycreate_sid = 0;
2301 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
David Howellsa6f76f22008-11-14 10:39:24 +11002303 if (old_tsec->exec_sid) {
2304 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002306 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002307
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002308 /* Fail on NNP or nosuid if not an allowed transition. */
2309 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2310 if (rc)
2311 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 } else {
2313 /* Check for a default transition on this program. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002314 rc = security_transition_sid(&selinux_state, old_tsec->sid,
2315 isec->sid, SECCLASS_PROCESS, NULL,
Eric Paris652bb9b2011-02-01 11:05:40 -05002316 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 if (rc)
2318 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002319
2320 /*
2321 * Fallback to old SID on NNP or nosuid if not an allowed
2322 * transition.
2323 */
2324 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2325 if (rc)
2326 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 }
2328
Vivek Goyal43af5de2016-09-09 11:37:49 -04002329 ad.type = LSM_AUDIT_DATA_FILE;
2330 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
David Howellsa6f76f22008-11-14 10:39:24 +11002332 if (new_tsec->sid == old_tsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002333 rc = avc_has_perm(&selinux_state,
2334 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 Smalley6b6bc622018-03-05 11:47:56 -05002340 rc = avc_has_perm(&selinux_state,
2341 old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2343 if (rc)
2344 return rc;
2345
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002346 rc = avc_has_perm(&selinux_state,
2347 new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2349 if (rc)
2350 return rc;
2351
David Howellsa6f76f22008-11-14 10:39:24 +11002352 /* Check for shared state */
2353 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002354 rc = avc_has_perm(&selinux_state,
2355 old_tsec->sid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002356 SECCLASS_PROCESS, PROCESS__SHARE,
2357 NULL);
2358 if (rc)
2359 return -EPERM;
2360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
David Howellsa6f76f22008-11-14 10:39:24 +11002362 /* Make sure that anyone attempting to ptrace over a task that
2363 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002364 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002365 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002366 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002367 rc = avc_has_perm(&selinux_state,
2368 ptsid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002369 SECCLASS_PROCESS,
2370 PROCESS__PTRACE, NULL);
2371 if (rc)
2372 return -EPERM;
2373 }
2374 }
2375
2376 /* Clear any possibly unsafe personality bits on exec: */
2377 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 /* Enable secure mode for SIDs transitions unless
2380 the noatsecure permission is granted between
2381 the two SIDs, i.e. ahp returns 0. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002382 rc = avc_has_perm(&selinux_state,
2383 old_tsec->sid, new_tsec->sid,
Kees Cook62874c32017-07-18 15:25:25 -07002384 SECCLASS_PROCESS, PROCESS__NOATSECURE,
2385 NULL);
2386 bprm->secureexec |= !!rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388
Kees Cook62874c32017-07-18 15:25:25 -07002389 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390}
2391
Al Viroc3c073f2012-08-21 22:32:06 -04002392static int match_file(const void *p, struct file *file, unsigned fd)
2393{
2394 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2395}
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002398static inline void flush_unauthorized_files(const struct cred *cred,
2399 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002402 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002403 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002404 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002406 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002408 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002409 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002410 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002411
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002413 Use file_path_has_perm on the tty path directly
2414 rather than using file_has_perm, as this particular
2415 open file may belong to another process and we are
2416 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002417 file_priv = list_first_entry(&tty->tty_files,
2418 struct tty_file_private, list);
2419 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002420 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002421 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 }
Peter Hurley4a510962016-01-09 21:35:23 -08002423 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002424 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002426 /* Reset controlling tty. */
2427 if (drop_tty)
2428 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
2430 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002431 n = iterate_fd(files, 0, match_file, cred);
2432 if (!n) /* none found? */
2433 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
Al Viroc3c073f2012-08-21 22:32:06 -04002435 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002436 if (IS_ERR(devnull))
2437 devnull = NULL;
2438 /* replace all the matching ones with this */
2439 do {
2440 replace_fd(n - 1, devnull, 0);
2441 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2442 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002443 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444}
2445
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446/*
David Howellsa6f76f22008-11-14 10:39:24 +11002447 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 */
David Howellsa6f76f22008-11-14 10:39:24 +11002449static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450{
David Howellsa6f76f22008-11-14 10:39:24 +11002451 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 int rc, i;
2454
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002455 new_tsec = selinux_cred(bprm->cred);
David Howellsa6f76f22008-11-14 10:39:24 +11002456 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 return;
2458
2459 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002460 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
David Howellsa6f76f22008-11-14 10:39:24 +11002462 /* Always clear parent death signal on SID transitions. */
2463 current->pdeath_signal = 0;
2464
2465 /* Check whether the new SID can inherit resource limits from the old
2466 * SID. If not, reset all soft limits to the lower of the current
2467 * task's hard limit and the init task's soft limit.
2468 *
2469 * Note that the setting of hard limits (even to lower them) can be
2470 * controlled by the setrlimit check. The inclusion of the init task's
2471 * soft limit into the computation is to avoid resetting soft limits
2472 * higher than the default soft limit for cases where the default is
2473 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2474 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002475 rc = avc_has_perm(&selinux_state,
2476 new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
David Howellsa6f76f22008-11-14 10:39:24 +11002477 PROCESS__RLIMITINH, NULL);
2478 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002479 /* protect against do_prlimit() */
2480 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002481 for (i = 0; i < RLIM_NLIMITS; i++) {
2482 rlim = current->signal->rlim + i;
2483 initrlim = init_task.signal->rlim + i;
2484 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2485 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002486 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002487 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2488 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002489 }
2490}
2491
2492/*
2493 * Clean up the process immediately after the installation of new credentials
2494 * due to exec
2495 */
2496static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2497{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002498 const struct task_security_struct *tsec = selinux_cred(current_cred());
David Howellsa6f76f22008-11-14 10:39:24 +11002499 u32 osid, sid;
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002500 int rc;
David Howellsa6f76f22008-11-14 10:39:24 +11002501
David Howellsa6f76f22008-11-14 10:39:24 +11002502 osid = tsec->osid;
2503 sid = tsec->sid;
2504
2505 if (sid == osid)
2506 return;
2507
2508 /* Check whether the new SID can inherit signal state from the old SID.
2509 * If not, clear itimers to avoid subsequent signal generation and
2510 * flush and unblock signals.
2511 *
2512 * This must occur _after_ the task SID has been updated so that any
2513 * kill done after the flush will be checked against the new SID.
2514 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002515 rc = avc_has_perm(&selinux_state,
2516 osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 if (rc) {
Arnd Bergmannddbc7d02019-10-25 21:37:43 +02002518 clear_itimer();
2519
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002521 if (!fatal_signal_pending(current)) {
2522 flush_sigqueue(&current->pending);
2523 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002524 flush_signal_handlers(current, 1);
2525 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002526 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 spin_unlock_irq(&current->sighand->siglock);
2529 }
2530
David Howellsa6f76f22008-11-14 10:39:24 +11002531 /* Wake up the parent if it is waiting so that it can recheck
2532 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002533 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002534 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002535 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536}
2537
2538/* superblock security operations */
2539
2540static int selinux_sb_alloc_security(struct super_block *sb)
2541{
Paul Moorecb89e242020-01-10 16:32:10 -05002542 struct superblock_security_struct *sbsec;
2543
2544 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
2545 if (!sbsec)
2546 return -ENOMEM;
2547
2548 mutex_init(&sbsec->lock);
2549 INIT_LIST_HEAD(&sbsec->isec_head);
2550 spin_lock_init(&sbsec->isec_lock);
2551 sbsec->sb = sb;
2552 sbsec->sid = SECINITSID_UNLABELED;
2553 sbsec->def_sid = SECINITSID_FILE;
2554 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
2555 sb->s_security = sbsec;
2556
2557 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558}
2559
2560static void selinux_sb_free_security(struct super_block *sb)
2561{
2562 superblock_free_security(sb);
2563}
2564
Al Viro99dbbb52018-12-14 21:56:23 -05002565static inline int opt_len(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566{
Al Viro99dbbb52018-12-14 21:56:23 -05002567 bool open_quote = false;
2568 int len;
2569 char c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Al Viro99dbbb52018-12-14 21:56:23 -05002571 for (len = 0; (c = s[len]) != '\0'; len++) {
2572 if (c == '"')
Cory Olmo3528a952006-09-29 01:58:44 -07002573 open_quote = !open_quote;
Al Viro99dbbb52018-12-14 21:56:23 -05002574 if (c == ',' && !open_quote)
2575 break;
2576 }
2577 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578}
2579
Al Viro204cc0c2018-12-13 13:41:47 -05002580static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002581{
Al Viro99dbbb52018-12-14 21:56:23 -05002582 char *from = options;
2583 char *to = options;
2584 bool first = true;
Gen Zhangfec63752019-06-12 21:55:38 +08002585 int rc;
Al Viro5b400232018-12-12 20:13:29 -05002586
Al Viro99dbbb52018-12-14 21:56:23 -05002587 while (1) {
2588 int len = opt_len(from);
Gen Zhangfec63752019-06-12 21:55:38 +08002589 int token;
Al Viro99dbbb52018-12-14 21:56:23 -05002590 char *arg = NULL;
2591
2592 token = match_opt_prefix(from, len, &arg);
2593
2594 if (token != Opt_error) {
2595 char *p, *q;
2596
2597 /* strip quotes */
2598 if (arg) {
2599 for (p = q = arg; p < from + len; p++) {
2600 char c = *p;
2601 if (c != '"')
2602 *q++ = c;
2603 }
2604 arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
Gen Zhangfec63752019-06-12 21:55:38 +08002605 if (!arg) {
2606 rc = -ENOMEM;
2607 goto free_opt;
2608 }
Al Viro99dbbb52018-12-14 21:56:23 -05002609 }
2610 rc = selinux_add_opt(token, arg, mnt_opts);
2611 if (unlikely(rc)) {
2612 kfree(arg);
Gen Zhangfec63752019-06-12 21:55:38 +08002613 goto free_opt;
Al Viro99dbbb52018-12-14 21:56:23 -05002614 }
2615 } else {
2616 if (!first) { // copy with preceding comma
2617 from--;
2618 len++;
2619 }
2620 if (to != from)
2621 memmove(to, from, len);
2622 to += len;
2623 first = false;
2624 }
2625 if (!from[len])
2626 break;
2627 from += len + 1;
2628 }
2629 *to = '\0';
2630 return 0;
Gen Zhangfec63752019-06-12 21:55:38 +08002631
2632free_opt:
2633 if (*mnt_opts) {
2634 selinux_free_mnt_opts(*mnt_opts);
2635 *mnt_opts = NULL;
2636 }
2637 return rc;
Al Viro5b400232018-12-12 20:13:29 -05002638}
2639
Al Viro204cc0c2018-12-13 13:41:47 -05002640static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002641{
Al Virobd323652018-12-13 15:04:59 -05002642 struct selinux_mnt_opts *opts = mnt_opts;
Eric Paris026eb162011-03-03 16:09:14 -05002643 struct superblock_security_struct *sbsec = sb->s_security;
Al Virobd323652018-12-13 15:04:59 -05002644 u32 sid;
2645 int rc;
Eric Paris026eb162011-03-03 16:09:14 -05002646
2647 if (!(sbsec->flags & SE_SBINITIALIZED))
2648 return 0;
2649
Al Viro204cc0c2018-12-13 13:41:47 -05002650 if (!opts)
Eric Paris026eb162011-03-03 16:09:14 -05002651 return 0;
2652
Al Virobd323652018-12-13 15:04:59 -05002653 if (opts->fscontext) {
2654 rc = parse_sid(sb, opts->fscontext, &sid);
2655 if (rc)
Al Viroc039bc32018-12-01 23:06:57 -05002656 return rc;
Al Virobd323652018-12-13 15:04:59 -05002657 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2658 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002659 }
Al Virobd323652018-12-13 15:04:59 -05002660 if (opts->context) {
2661 rc = parse_sid(sb, opts->context, &sid);
2662 if (rc)
2663 return rc;
2664 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2665 goto out_bad_option;
2666 }
2667 if (opts->rootcontext) {
2668 struct inode_security_struct *root_isec;
2669 root_isec = backing_inode_security(sb->s_root);
2670 rc = parse_sid(sb, opts->rootcontext, &sid);
2671 if (rc)
2672 return rc;
2673 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2674 goto out_bad_option;
2675 }
2676 if (opts->defcontext) {
2677 rc = parse_sid(sb, opts->defcontext, &sid);
2678 if (rc)
2679 return rc;
2680 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2681 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002682 }
Al Viroc039bc32018-12-01 23:06:57 -05002683 return 0;
Eric Paris026eb162011-03-03 16:09:14 -05002684
Eric Paris026eb162011-03-03 16:09:14 -05002685out_bad_option:
peter enderborgc103a912018-06-12 10:09:03 +02002686 pr_warn("SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002687 "during remount (dev %s, type=%s)\n", sb->s_id,
2688 sb->s_type->name);
Al Viroc039bc32018-12-01 23:06:57 -05002689 return -EINVAL;
Eric Paris026eb162011-03-03 16:09:14 -05002690}
2691
Al Viroa10d7c22018-12-05 11:58:35 -05002692static int selinux_sb_kern_mount(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
David Howells88e67f32008-11-14 10:39:21 +11002694 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002695 struct common_audit_data ad;
James Morris74192242008-12-19 11:41:10 +11002696
Eric Paris50c205f2012-04-04 15:01:43 -04002697 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002698 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002699 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700}
2701
David Howells726c3342006-06-23 02:02:58 -07002702static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
David Howells88e67f32008-11-14 10:39:21 +11002704 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002705 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
Eric Paris50c205f2012-04-04 15:01:43 -04002707 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002708 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002709 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710}
2711
Al Viro808d4e32012-10-11 11:42:01 -04002712static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002713 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002714 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002715 unsigned long flags,
2716 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717{
David Howells88e67f32008-11-14 10:39:21 +11002718 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002721 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002722 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 else
Eric Paris2875fa02011-04-28 16:04:24 -04002724 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725}
2726
2727static int selinux_umount(struct vfsmount *mnt, int flags)
2728{
David Howells88e67f32008-11-14 10:39:21 +11002729 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
David Howells88e67f32008-11-14 10:39:21 +11002731 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002732 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733}
2734
Al Viro0b520752018-12-23 16:02:47 -05002735static int selinux_fs_context_dup(struct fs_context *fc,
2736 struct fs_context *src_fc)
2737{
2738 const struct selinux_mnt_opts *src = src_fc->security;
2739 struct selinux_mnt_opts *opts;
2740
2741 if (!src)
2742 return 0;
2743
2744 fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
2745 if (!fc->security)
2746 return -ENOMEM;
2747
2748 opts = fc->security;
2749
2750 if (src->fscontext) {
2751 opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
2752 if (!opts->fscontext)
2753 return -ENOMEM;
2754 }
2755 if (src->context) {
2756 opts->context = kstrdup(src->context, GFP_KERNEL);
2757 if (!opts->context)
2758 return -ENOMEM;
2759 }
2760 if (src->rootcontext) {
2761 opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
2762 if (!opts->rootcontext)
2763 return -ENOMEM;
2764 }
2765 if (src->defcontext) {
2766 opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
2767 if (!opts->defcontext)
2768 return -ENOMEM;
2769 }
2770 return 0;
2771}
2772
David Howells442155c2018-11-01 23:07:24 +00002773static const struct fs_parameter_spec selinux_param_specs[] = {
2774 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
2782static const struct fs_parameter_description selinux_fs_parameters = {
2783 .name = "SELinux",
2784 .specs = selinux_param_specs,
2785};
2786
2787static int selinux_fs_context_parse_param(struct fs_context *fc,
2788 struct fs_parameter *param)
2789{
2790 struct fs_parse_result result;
2791 int opt, rc;
2792
2793 opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
2794 if (opt < 0)
2795 return opt;
2796
2797 rc = selinux_add_opt(opt, param->string, &fc->security);
2798 if (!rc) {
2799 param->string = NULL;
2800 rc = 1;
2801 }
2802 return rc;
2803}
2804
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805/* inode security operations */
2806
2807static int selinux_inode_alloc_security(struct inode *inode)
2808{
Paul Moorecb89e242020-01-10 16:32:10 -05002809 struct inode_security_struct *isec = selinux_inode(inode);
2810 u32 sid = current_sid();
2811
2812 spin_lock_init(&isec->lock);
2813 INIT_LIST_HEAD(&isec->list);
2814 isec->inode = inode;
2815 isec->sid = SECINITSID_UNLABELED;
2816 isec->sclass = SECCLASS_FILE;
2817 isec->task_sid = sid;
2818 isec->initialized = LABEL_INVALID;
2819
2820 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821}
2822
2823static void selinux_inode_free_security(struct inode *inode)
2824{
2825 inode_free_security(inode);
2826}
2827
David Quigleyd47be3d2013-05-22 12:50:34 -04002828static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002829 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002830 u32 *ctxlen)
2831{
David Quigleyd47be3d2013-05-22 12:50:34 -04002832 u32 newsid;
2833 int rc;
2834
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002835 rc = selinux_determine_inode_label(selinux_cred(current_cred()),
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002836 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002837 inode_mode_to_security_class(mode),
2838 &newsid);
2839 if (rc)
2840 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002841
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002842 return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
2843 ctxlen);
David Quigleyd47be3d2013-05-22 12:50:34 -04002844}
2845
Vivek Goyala518b0a2016-07-13 10:44:53 -04002846static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2847 struct qstr *name,
2848 const struct cred *old,
2849 struct cred *new)
2850{
2851 u32 newsid;
2852 int rc;
2853 struct task_security_struct *tsec;
2854
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002855 rc = selinux_determine_inode_label(selinux_cred(old),
Vivek Goyala518b0a2016-07-13 10:44:53 -04002856 d_inode(dentry->d_parent), name,
2857 inode_mode_to_security_class(mode),
2858 &newsid);
2859 if (rc)
2860 return rc;
2861
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002862 tsec = selinux_cred(new);
Vivek Goyala518b0a2016-07-13 10:44:53 -04002863 tsec->create_sid = newsid;
2864 return 0;
2865}
2866
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002867static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002868 const struct qstr *qstr,
2869 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002870 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002871{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002872 const struct task_security_struct *tsec = selinux_cred(current_cred());
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002873 struct superblock_security_struct *sbsec;
Corentin LABBEc0d4f462017-10-04 20:32:17 +02002874 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002875 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002876 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002877
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002878 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002879
David Howells275bb412008-11-14 10:39:19 +11002880 newsid = tsec->create_sid;
2881
Yang Guo210a2922019-12-12 10:02:24 +08002882 rc = selinux_determine_inode_label(tsec, dir, qstr,
David Howellsc3c188b2015-07-10 17:19:58 -04002883 inode_mode_to_security_class(inode->i_mode),
2884 &newsid);
2885 if (rc)
2886 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002887
Eric Paris296fddf2006-09-25 23:32:00 -07002888 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002889 if (sbsec->flags & SE_SBINITIALIZED) {
Casey Schaufler80788c22018-09-21 17:19:11 -07002890 struct inode_security_struct *isec = selinux_inode(inode);
Eric Paris296fddf2006-09-25 23:32:00 -07002891 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2892 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002893 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002894 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002895
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01002896 if (!selinux_initialized(&selinux_state) ||
2897 !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002898 return -EOPNOTSUPP;
2899
Tetsuo Handa95489062013-07-25 05:44:02 +09002900 if (name)
2901 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002902
2903 if (value && len) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002904 rc = security_sid_to_context_force(&selinux_state, newsid,
2905 &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002906 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002907 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002908 *value = context;
2909 *len = clen;
2910 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002911
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002912 return 0;
2913}
2914
Al Viro4acdaf22011-07-26 01:42:34 -04002915static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916{
2917 return may_create(dir, dentry, SECCLASS_FILE);
2918}
2919
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2921{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 return may_link(dir, old_dentry, MAY_LINK);
2923}
2924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2926{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 return may_link(dir, dentry, MAY_UNLINK);
2928}
2929
2930static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2931{
2932 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2933}
2934
Al Viro18bb1db2011-07-26 01:41:39 -04002935static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936{
2937 return may_create(dir, dentry, SECCLASS_DIR);
2938}
2939
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2941{
2942 return may_link(dir, dentry, MAY_RMDIR);
2943}
2944
Al Viro1a67aaf2011-07-26 01:52:52 -04002945static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2948}
2949
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002951 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952{
2953 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2954}
2955
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956static int selinux_inode_readlink(struct dentry *dentry)
2957{
David Howells88e67f32008-11-14 10:39:21 +11002958 const struct cred *cred = current_cred();
2959
Eric Paris2875fa02011-04-28 16:04:24 -04002960 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961}
2962
NeilBrownbda0be72015-03-23 13:37:39 +11002963static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2964 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965{
David Howells88e67f32008-11-14 10:39:21 +11002966 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002967 struct common_audit_data ad;
2968 struct inode_security_struct *isec;
2969 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
NeilBrownbda0be72015-03-23 13:37:39 +11002971 validate_creds(cred);
2972
2973 ad.type = LSM_AUDIT_DATA_DENTRY;
2974 ad.u.dentry = dentry;
2975 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002976 isec = inode_security_rcu(inode, rcu);
2977 if (IS_ERR(isec))
2978 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002979
Stephen Smalley1a370792019-11-22 12:22:44 -05002980 return avc_has_perm_flags(&selinux_state,
2981 sid, isec->sid, isec->sclass, FILE__READ, &ad,
2982 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983}
2984
Eric Parisd4cf970d2012-04-04 15:01:42 -04002985static noinline int audit_inode_permission(struct inode *inode,
2986 u32 perms, u32 audited, u32 denied,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05002987 int result)
Eric Parisd4cf970d2012-04-04 15:01:42 -04002988{
2989 struct common_audit_data ad;
Casey Schaufler80788c22018-09-21 17:19:11 -07002990 struct inode_security_struct *isec = selinux_inode(inode);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002991 int rc;
2992
Eric Paris50c205f2012-04-04 15:01:43 -04002993 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002994 ad.u.inode = inode;
2995
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002996 rc = slow_avc_audit(&selinux_state,
2997 current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley0188d5c2019-11-22 12:22:45 -05002998 audited, denied, result, &ad);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002999 if (rc)
3000 return rc;
3001 return 0;
3002}
3003
Al Viroe74f71e2011-06-20 19:38:15 -04003004static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005{
David Howells88e67f32008-11-14 10:39:21 +11003006 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003007 u32 perms;
3008 bool from_access;
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003009 bool no_block = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003010 struct inode_security_struct *isec;
3011 u32 sid;
3012 struct av_decision avd;
3013 int rc, rc2;
3014 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
Eric Parisb782e0a2010-07-23 11:44:03 -04003016 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003017 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3018
Eric Parisb782e0a2010-07-23 11:44:03 -04003019 /* No permission to check. Existence test. */
3020 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Eric Paris2e334052012-04-04 15:01:42 -04003023 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003024
Eric Paris2e334052012-04-04 15:01:42 -04003025 if (unlikely(IS_PRIVATE(inode)))
3026 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003027
3028 perms = file_mask_to_av(inode->i_mode, mask);
3029
Eric Paris2e334052012-04-04 15:01:42 -04003030 sid = cred_sid(cred);
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003031 isec = inode_security_rcu(inode, no_block);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003032 if (IS_ERR(isec))
3033 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003034
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003035 rc = avc_has_perm_noaudit(&selinux_state,
Stephen Smalley3a28cff2018-12-12 10:10:55 -05003036 sid, isec->sid, isec->sclass, perms,
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003037 no_block ? AVC_NONBLOCKING : 0,
Stephen Smalley3a28cff2018-12-12 10:10:55 -05003038 &avd);
Eric Paris2e334052012-04-04 15:01:42 -04003039 audited = avc_audit_required(perms, &avd, rc,
3040 from_access ? FILE__AUDIT_ACCESS : 0,
3041 &denied);
3042 if (likely(!audited))
3043 return rc;
3044
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003045 /* fall back to ref-walk if we have to generate audit */
Stephen Smalley5298d0b2019-11-22 16:16:56 -05003046 if (no_block)
Stephen Smalley0188d5c2019-11-22 12:22:45 -05003047 return -ECHILD;
3048
3049 rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
Eric Paris2e334052012-04-04 15:01:42 -04003050 if (rc2)
3051 return rc2;
3052 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053}
3054
3055static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3056{
David Howells88e67f32008-11-14 10:39:21 +11003057 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003058 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003059 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003060 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003062 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3063 if (ia_valid & ATTR_FORCE) {
3064 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3065 ATTR_FORCE);
3066 if (!ia_valid)
3067 return 0;
3068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003070 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3071 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003072 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003074 if (selinux_policycap_openperm() &&
Stephen Smalleyccb54472017-05-12 12:41:24 -04003075 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3076 (ia_valid & ATTR_SIZE) &&
3077 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003078 av |= FILE__OPEN;
3079
3080 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081}
3082
Al Viro3f7036a2015-03-08 19:28:30 -04003083static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
Al Viro3f7036a2015-03-08 19:28:30 -04003085 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086}
3087
Stephen Smalleydb590002017-04-20 11:31:30 -04003088static bool has_cap_mac_admin(bool audit)
3089{
3090 const struct cred *cred = current_cred();
Micah Mortonc1a85a02019-01-07 16:10:53 -08003091 unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
Stephen Smalleydb590002017-04-20 11:31:30 -04003092
Micah Mortonc1a85a02019-01-07 16:10:53 -08003093 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
Stephen Smalleydb590002017-04-20 11:31:30 -04003094 return false;
Micah Mortonc1a85a02019-01-07 16:10:53 -08003095 if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
Stephen Smalleydb590002017-04-20 11:31:30 -04003096 return false;
3097 return true;
3098}
3099
David Howells8f0cfa52008-04-29 00:59:41 -07003100static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3101 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102{
David Howellsc6f493d2015-03-17 22:26:22 +00003103 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003104 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003106 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003107 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 int rc = 0;
3109
Eric W. Biederman6b240302017-10-02 09:38:20 -05003110 if (strcmp(name, XATTR_NAME_SELINUX)) {
3111 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3112 if (rc)
3113 return rc;
3114
3115 /* Not an attribute we recognize, so just check the
3116 ordinary setattr permission. */
3117 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01003120 if (!selinux_initialized(&selinux_state))
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003121 return (inode_owner_or_capable(inode) ? 0 : -EPERM);
3122
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003124 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 return -EOPNOTSUPP;
3126
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003127 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 return -EPERM;
3129
Eric Paris50c205f2012-04-04 15:01:43 -04003130 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003131 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
Paul Moore20cdef82016-04-04 14:14:42 -04003133 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003134 rc = avc_has_perm(&selinux_state,
3135 sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 FILE__RELABELFROM, &ad);
3137 if (rc)
3138 return rc;
3139
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003140 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3141 GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003142 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003143 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003144 struct audit_buffer *ab;
3145 size_t audit_size;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003146
3147 /* We strip a nul only if it is at the end, otherwise the
3148 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003149 if (value) {
Colin Ian Kingadd24372017-10-14 13:46:55 +01003150 const char *str = value;
3151
Al Viroe3fea3f2012-06-09 08:15:16 +01003152 if (str[size - 1] == '\0')
3153 audit_size = size - 1;
3154 else
3155 audit_size = size;
3156 } else {
Al Viroe3fea3f2012-06-09 08:15:16 +01003157 audit_size = 0;
3158 }
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04003159 ab = audit_log_start(audit_context(),
3160 GFP_ATOMIC, AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04003161 audit_log_format(ab, "op=setxattr invalid_context=");
3162 audit_log_n_untrustedstring(ab, value, audit_size);
3163 audit_log_end(ab);
3164
Stephen Smalley12b29f32008-05-07 13:03:20 -04003165 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003166 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003167 rc = security_context_to_sid_force(&selinux_state, value,
3168 size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003169 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 if (rc)
3171 return rc;
3172
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003173 rc = avc_has_perm(&selinux_state,
3174 sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 FILE__RELABELTO, &ad);
3176 if (rc)
3177 return rc;
3178
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003179 rc = security_validate_transition(&selinux_state, isec->sid, newsid,
3180 sid, isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 if (rc)
3182 return rc;
3183
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003184 return avc_has_perm(&selinux_state,
3185 newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 sbsec->sid,
3187 SECCLASS_FILESYSTEM,
3188 FILESYSTEM__ASSOCIATE,
3189 &ad);
3190}
3191
David Howells8f0cfa52008-04-29 00:59:41 -07003192static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003193 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003194 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195{
David Howellsc6f493d2015-03-17 22:26:22 +00003196 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003197 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 u32 newsid;
3199 int rc;
3200
3201 if (strcmp(name, XATTR_NAME_SELINUX)) {
3202 /* Not an attribute we recognize, so nothing to do. */
3203 return;
3204 }
3205
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01003206 if (!selinux_initialized(&selinux_state)) {
Jonathan Lebon3e3e24b2019-09-12 09:30:07 -04003207 /* If we haven't even been initialized, then we can't validate
3208 * against a policy, so leave the label as invalid. It may
3209 * resolve to a valid label on the next revalidation try if
3210 * we've since initialized.
3211 */
3212 return;
3213 }
3214
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003215 rc = security_context_to_sid_force(&selinux_state, value, size,
3216 &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +02003218 pr_err("SELinux: unable to map context to SID"
Stephen Smalley12b29f32008-05-07 13:03:20 -04003219 "for (%s, %lu), rc=%d\n",
3220 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 return;
3222 }
3223
Paul Moore20cdef82016-04-04 14:14:42 -04003224 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003225 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003226 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003228 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003229 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003230
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 return;
3232}
3233
David Howells8f0cfa52008-04-29 00:59:41 -07003234static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
David Howells88e67f32008-11-14 10:39:21 +11003236 const struct cred *cred = current_cred();
3237
Eric Paris2875fa02011-04-28 16:04:24 -04003238 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239}
3240
Eric Paris828dfe12008-04-17 13:17:49 -04003241static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
David Howells88e67f32008-11-14 10:39:21 +11003243 const struct cred *cred = current_cred();
3244
Eric Paris2875fa02011-04-28 16:04:24 -04003245 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246}
3247
David Howells8f0cfa52008-04-29 00:59:41 -07003248static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249{
Eric W. Biederman6b240302017-10-02 09:38:20 -05003250 if (strcmp(name, XATTR_NAME_SELINUX)) {
3251 int rc = cap_inode_removexattr(dentry, name);
3252 if (rc)
3253 return rc;
3254
3255 /* Not an attribute we recognize, so just check the
3256 ordinary setattr permission. */
3257 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
3260 /* No one is allowed to remove a SELinux security label.
3261 You can change the label, but all data must be labeled. */
3262 return -EACCES;
3263}
3264
Aaron Goidelac5656d2019-08-12 11:20:00 -04003265static int selinux_path_notify(const struct path *path, u64 mask,
3266 unsigned int obj_type)
3267{
3268 int ret;
3269 u32 perm;
3270
3271 struct common_audit_data ad;
3272
3273 ad.type = LSM_AUDIT_DATA_PATH;
3274 ad.u.path = *path;
3275
3276 /*
3277 * Set permission needed based on the type of mark being set.
3278 * Performs an additional check for sb watches.
3279 */
3280 switch (obj_type) {
3281 case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
3282 perm = FILE__WATCH_MOUNT;
3283 break;
3284 case FSNOTIFY_OBJ_TYPE_SB:
3285 perm = FILE__WATCH_SB;
3286 ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
3287 FILESYSTEM__WATCH, &ad);
3288 if (ret)
3289 return ret;
3290 break;
3291 case FSNOTIFY_OBJ_TYPE_INODE:
3292 perm = FILE__WATCH;
3293 break;
3294 default:
3295 return -EINVAL;
3296 }
3297
3298 /* blocking watches require the file:watch_with_perm permission */
3299 if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
3300 perm |= FILE__WATCH_WITH_PERM;
3301
3302 /* watches on read-like events need the file:watch_reads permission */
3303 if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3304 perm |= FILE__WATCH_READS;
3305
3306 return path_has_perm(current_cred(), path, perm);
3307}
3308
James Morrisd381d8a2005-10-30 14:59:22 -08003309/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003310 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003311 *
3312 * Permission check is handled by selinux_inode_getxattr hook.
3313 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003314static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315{
David P. Quigley42492592008-02-04 22:29:39 -08003316 u32 size;
3317 int error;
3318 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003319 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003321 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3322 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003324 /*
3325 * If the caller has CAP_MAC_ADMIN, then get the raw context
3326 * value even if it is not defined by current policy; otherwise,
3327 * use the in-core value under current policy.
3328 * Use the non-auditing forms of the permission checks since
3329 * getxattr may be called by unprivileged processes commonly
3330 * and lack of permission just means that we fall back to the
3331 * in-core context value, not a denial.
3332 */
Paul Moore20cdef82016-04-04 14:14:42 -04003333 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003334 if (has_cap_mac_admin(false))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003335 error = security_sid_to_context_force(&selinux_state,
3336 isec->sid, &context,
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003337 &size);
3338 else
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003339 error = security_sid_to_context(&selinux_state, isec->sid,
3340 &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003341 if (error)
3342 return error;
3343 error = size;
3344 if (alloc) {
3345 *buffer = context;
3346 goto out_nofree;
3347 }
3348 kfree(context);
3349out_nofree:
3350 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351}
3352
3353static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003354 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355{
Paul Moore2c971652016-04-19 16:36:28 -04003356 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01003357 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 u32 newsid;
3359 int rc;
3360
3361 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3362 return -EOPNOTSUPP;
3363
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01003364 if (!(sbsec->flags & SBLABEL_MNT))
3365 return -EOPNOTSUPP;
3366
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 if (!value || !size)
3368 return -EACCES;
3369
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003370 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3371 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 if (rc)
3373 return rc;
3374
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003375 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003376 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003378 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003379 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 return 0;
3381}
3382
3383static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3384{
3385 const int len = sizeof(XATTR_NAME_SELINUX);
3386 if (buffer && len <= buffer_size)
3387 memcpy(buffer, XATTR_NAME_SELINUX, len);
3388 return len;
3389}
3390
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003391static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003392{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003393 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003394 *secid = isec->sid;
3395}
3396
Vivek Goyal56909eb2016-07-13 10:44:48 -04003397static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3398{
3399 u32 sid;
3400 struct task_security_struct *tsec;
3401 struct cred *new_creds = *new;
3402
3403 if (new_creds == NULL) {
3404 new_creds = prepare_creds();
3405 if (!new_creds)
3406 return -ENOMEM;
3407 }
3408
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003409 tsec = selinux_cred(new_creds);
Vivek Goyal56909eb2016-07-13 10:44:48 -04003410 /* Get label from overlay inode and set it in create_sid */
3411 selinux_inode_getsecid(d_inode(src), &sid);
3412 tsec->create_sid = sid;
3413 *new = new_creds;
3414 return 0;
3415}
3416
Vivek Goyal19472b62016-07-13 10:44:50 -04003417static int selinux_inode_copy_up_xattr(const char *name)
3418{
3419 /* The copy_up hook above sets the initial context on an inode, but we
3420 * don't then want to overwrite it by blindly copying all the lower
3421 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3422 */
3423 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3424 return 1; /* Discard */
3425 /*
3426 * Any other attribute apart from SELINUX is not claimed, supported
3427 * by selinux.
3428 */
3429 return -EOPNOTSUPP;
3430}
3431
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003432/* kernfs node operations */
3433
YueHaibingc72c4cd2019-03-22 22:04:00 +08003434static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
3435 struct kernfs_node *kn)
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003436{
Stephen Smalley169ce0c2019-09-04 10:32:48 -04003437 const struct task_security_struct *tsec = selinux_cred(current_cred());
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003438 u32 parent_sid, newsid, clen;
3439 int rc;
3440 char *context;
3441
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003442 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003443 if (rc == -ENODATA)
3444 return 0;
3445 else if (rc < 0)
3446 return rc;
3447
3448 clen = (u32)rc;
3449 context = kmalloc(clen, GFP_KERNEL);
3450 if (!context)
3451 return -ENOMEM;
3452
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003453 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, context, clen);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003454 if (rc < 0) {
3455 kfree(context);
3456 return rc;
3457 }
3458
3459 rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid,
3460 GFP_KERNEL);
3461 kfree(context);
3462 if (rc)
3463 return rc;
3464
3465 if (tsec->create_sid) {
3466 newsid = tsec->create_sid;
3467 } else {
3468 u16 secclass = inode_mode_to_security_class(kn->mode);
3469 struct qstr q;
3470
3471 q.name = kn->name;
3472 q.hash_len = hashlen_string(kn_dir, kn->name);
3473
3474 rc = security_transition_sid(&selinux_state, tsec->sid,
3475 parent_sid, secclass, &q,
3476 &newsid);
3477 if (rc)
3478 return rc;
3479 }
3480
3481 rc = security_sid_to_context_force(&selinux_state, newsid,
3482 &context, &clen);
3483 if (rc)
3484 return rc;
3485
Ondrej Mosnacek1537ad12019-04-03 09:29:41 +02003486 rc = kernfs_xattr_set(kn, XATTR_NAME_SELINUX, context, clen,
3487 XATTR_CREATE);
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01003488 kfree(context);
3489 return rc;
3490}
3491
3492
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493/* file security operations */
3494
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003495static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496{
David Howells88e67f32008-11-14 10:39:21 +11003497 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003498 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3501 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3502 mask |= MAY_APPEND;
3503
Paul Moore389fb8002009-03-27 17:10:34 -04003504 return file_has_perm(cred, file,
3505 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003508static int selinux_file_permission(struct file *file, int mask)
3509{
Al Viro496ad9a2013-01-23 17:07:38 -05003510 struct inode *inode = file_inode(file);
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003511 struct file_security_struct *fsec = selinux_file(file);
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003512 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003513 u32 sid = current_sid();
3514
Paul Moore389fb8002009-03-27 17:10:34 -04003515 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003516 /* No permission to check. Existence test. */
3517 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003518
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003519 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003520 if (sid == fsec->sid && fsec->isid == isec->sid &&
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003521 fsec->pseqno == avc_policy_seqno(&selinux_state))
Eric Paris83d49852012-04-04 13:45:40 -04003522 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003523 return 0;
3524
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003525 return selinux_revalidate_file_permission(file, mask);
3526}
3527
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528static int selinux_file_alloc_security(struct file *file)
3529{
Paul Moorecb89e242020-01-10 16:32:10 -05003530 struct file_security_struct *fsec = selinux_file(file);
3531 u32 sid = current_sid();
3532
3533 fsec->sid = sid;
3534 fsec->fown_sid = sid;
3535
3536 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537}
3538
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003539/*
3540 * Check whether a task has the ioctl permission and cmd
3541 * operation to an inode.
3542 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003543static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003544 u32 requested, u16 cmd)
3545{
3546 struct common_audit_data ad;
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003547 struct file_security_struct *fsec = selinux_file(file);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003548 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003549 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003550 struct lsm_ioctlop_audit ioctl;
3551 u32 ssid = cred_sid(cred);
3552 int rc;
3553 u8 driver = cmd >> 8;
3554 u8 xperm = cmd & 0xff;
3555
3556 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3557 ad.u.op = &ioctl;
3558 ad.u.op->cmd = cmd;
3559 ad.u.op->path = file->f_path;
3560
3561 if (ssid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003562 rc = avc_has_perm(&selinux_state,
3563 ssid, fsec->sid,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003564 SECCLASS_FD,
3565 FD__USE,
3566 &ad);
3567 if (rc)
3568 goto out;
3569 }
3570
3571 if (unlikely(IS_PRIVATE(inode)))
3572 return 0;
3573
Paul Moore20cdef82016-04-04 14:14:42 -04003574 isec = inode_security(inode);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003575 rc = avc_has_extended_perms(&selinux_state,
3576 ssid, isec->sid, isec->sclass,
3577 requested, driver, xperm, &ad);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003578out:
3579 return rc;
3580}
3581
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3583 unsigned long arg)
3584{
David Howells88e67f32008-11-14 10:39:21 +11003585 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003586 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Eric Paris0b24dcb2011-02-25 15:39:20 -05003588 switch (cmd) {
3589 case FIONREAD:
3590 /* fall through */
3591 case FIBMAP:
3592 /* fall through */
3593 case FIGETBSZ:
3594 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003595 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003596 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003597 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003598 error = file_has_perm(cred, file, FILE__GETATTR);
3599 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600
Al Viro2f99c362012-03-23 16:04:05 -04003601 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003602 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003603 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003604 error = file_has_perm(cred, file, FILE__SETATTR);
3605 break;
3606
3607 /* sys_ioctl() checks */
3608 case FIONBIO:
3609 /* fall through */
3610 case FIOASYNC:
3611 error = file_has_perm(cred, file, 0);
3612 break;
3613
3614 case KDSKBENT:
3615 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003616 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Micah Mortonc1a85a02019-01-07 16:10:53 -08003617 CAP_OPT_NONE, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003618 break;
3619
3620 /* default case assumes that the command will go
3621 * to the file's ioctl() function.
3622 */
3623 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003624 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003625 }
3626 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627}
3628
Stephen Smalleyb78b7d52020-01-08 12:23:56 -05003629static int default_noexec __ro_after_init;
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003630
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3632{
David Howells88e67f32008-11-14 10:39:21 +11003633 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003634 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003635 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003636
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003637 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003638 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3639 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 /*
3641 * We are making executable an anonymous mapping or a
3642 * private file mapping that will also be writable.
3643 * This has an additional check.
3644 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003645 rc = avc_has_perm(&selinux_state,
3646 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003647 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003649 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
3652 if (file) {
3653 /* read access is always possible with a mapping */
3654 u32 av = FILE__READ;
3655
3656 /* write access only matters if the mapping is shared */
3657 if (shared && (prot & PROT_WRITE))
3658 av |= FILE__WRITE;
3659
3660 if (prot & PROT_EXEC)
3661 av |= FILE__EXECUTE;
3662
David Howells88e67f32008-11-14 10:39:21 +11003663 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 }
David Howellsd84f4f92008-11-14 10:39:23 +11003665
3666error:
3667 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668}
3669
Al Viroe5467852012-05-30 13:30:51 -04003670static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003672 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003673
3674 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3675 u32 sid = current_sid();
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003676 rc = avc_has_perm(&selinux_state,
3677 sid, sid, SECCLASS_MEMPROTECT,
Paul Moore98883bf2014-03-19 16:46:11 -04003678 MEMPROTECT__MMAP_ZERO, NULL);
3679 }
3680
3681 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003682}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
Al Viroe5467852012-05-30 13:30:51 -04003684static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3685 unsigned long prot, unsigned long flags)
3686{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003687 struct common_audit_data ad;
3688 int rc;
3689
3690 if (file) {
3691 ad.type = LSM_AUDIT_DATA_FILE;
3692 ad.u.file = file;
3693 rc = inode_has_perm(current_cred(), file_inode(file),
3694 FILE__MAP, &ad);
3695 if (rc)
3696 return rc;
3697 }
3698
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003699 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 prot = reqprot;
3701
3702 return file_map_prot_check(file, prot,
3703 (flags & MAP_TYPE) == MAP_SHARED);
3704}
3705
3706static int selinux_file_mprotect(struct vm_area_struct *vma,
3707 unsigned long reqprot,
3708 unsigned long prot)
3709{
David Howells88e67f32008-11-14 10:39:21 +11003710 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003711 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003713 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 prot = reqprot;
3715
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003716 if (default_noexec &&
3717 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003718 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003719 if (vma->vm_start >= vma->vm_mm->start_brk &&
3720 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003721 rc = avc_has_perm(&selinux_state,
3722 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003723 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003724 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003725 ((vma->vm_start <= vma->vm_mm->start_stack &&
3726 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003727 vma_is_stack_for_current(vma))) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003728 rc = avc_has_perm(&selinux_state,
3729 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003730 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003731 } else if (vma->vm_file && vma->anon_vma) {
3732 /*
3733 * We are making executable a file mapping that has
3734 * had some COW done. Since pages might have been
3735 * written, check ability to execute the possibly
3736 * modified content. This typically should only
3737 * occur for text relocations.
3738 */
David Howellsd84f4f92008-11-14 10:39:23 +11003739 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003740 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003741 if (rc)
3742 return rc;
3743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
3745 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3746}
3747
3748static int selinux_file_lock(struct file *file, unsigned int cmd)
3749{
David Howells88e67f32008-11-14 10:39:21 +11003750 const struct cred *cred = current_cred();
3751
3752 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753}
3754
3755static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3756 unsigned long arg)
3757{
David Howells88e67f32008-11-14 10:39:21 +11003758 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 int err = 0;
3760
3761 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003762 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003763 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003764 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003766 }
3767 /* fall through */
3768 case F_SETOWN:
3769 case F_SETSIG:
3770 case F_GETFL:
3771 case F_GETOWN:
3772 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003773 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003774 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003775 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003776 break;
3777 case F_GETLK:
3778 case F_SETLK:
3779 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003780 case F_OFD_GETLK:
3781 case F_OFD_SETLK:
3782 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003784 case F_GETLK64:
3785 case F_SETLK64:
3786 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787#endif
David Howells88e67f32008-11-14 10:39:21 +11003788 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003789 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 }
3791
3792 return err;
3793}
3794
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003795static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 struct file_security_struct *fsec;
3798
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003799 fsec = selinux_file(file);
David Howells275bb412008-11-14 10:39:19 +11003800 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801}
3802
3803static int selinux_file_send_sigiotask(struct task_struct *tsk,
3804 struct fown_struct *fown, int signum)
3805{
Eric Paris828dfe12008-04-17 13:17:49 -04003806 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003807 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 struct file_security_struct *fsec;
3810
3811 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003812 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003814 fsec = selinux_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
3816 if (!signum)
3817 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3818 else
3819 perm = signal_to_av(signum);
3820
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003821 return avc_has_perm(&selinux_state,
3822 fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 SECCLASS_PROCESS, perm, NULL);
3824}
3825
3826static int selinux_file_receive(struct file *file)
3827{
David Howells88e67f32008-11-14 10:39:21 +11003828 const struct cred *cred = current_cred();
3829
3830 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831}
3832
Al Viro94817692018-07-10 14:13:18 -04003833static int selinux_file_open(struct file *file)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003834{
3835 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003836 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003837
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003838 fsec = selinux_file(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003839 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003840 /*
3841 * Save inode label and policy sequence number
3842 * at open-time so that selinux_file_permission
3843 * can determine whether revalidation is necessary.
3844 * Task label is already saved in the file security
3845 * struct as its SID.
3846 */
3847 fsec->isid = isec->sid;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003848 fsec->pseqno = avc_policy_seqno(&selinux_state);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003849 /*
3850 * Since the inode label or policy seqno may have changed
3851 * between the selinux_inode_permission check and the saving
3852 * of state above, recheck that access is still permitted.
3853 * Otherwise, access might never be revalidated against the
3854 * new inode label or new policy.
3855 * This check is not redundant - do not remove.
3856 */
Al Viro94817692018-07-10 14:13:18 -04003857 return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003858}
3859
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860/* task security operations */
3861
Tetsuo Handaa79be232017-03-28 23:08:45 +09003862static int selinux_task_alloc(struct task_struct *task,
3863 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003865 u32 sid = current_sid();
3866
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003867 return avc_has_perm(&selinux_state,
3868 sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869}
3870
David Howellsf1752ee2008-11-14 10:39:17 +11003871/*
David Howellsd84f4f92008-11-14 10:39:23 +11003872 * prepare a new set of credentials for modification
3873 */
3874static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3875 gfp_t gfp)
3876{
Casey Schauflerbbd36622018-11-12 09:30:56 -08003877 const struct task_security_struct *old_tsec = selinux_cred(old);
3878 struct task_security_struct *tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11003879
Casey Schauflerbbd36622018-11-12 09:30:56 -08003880 *tsec = *old_tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11003881 return 0;
3882}
3883
3884/*
David Howellsee18d642009-09-02 09:14:21 +01003885 * transfer the SELinux data to a blank set of creds
3886 */
3887static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3888{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003889 const struct task_security_struct *old_tsec = selinux_cred(old);
3890 struct task_security_struct *tsec = selinux_cred(new);
David Howellsee18d642009-09-02 09:14:21 +01003891
3892 *tsec = *old_tsec;
3893}
3894
Matthew Garrett3ec30112018-01-08 13:36:19 -08003895static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3896{
3897 *secid = cred_sid(c);
3898}
3899
David Howellsee18d642009-09-02 09:14:21 +01003900/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003901 * set the security data for a kernel service
3902 * - all the creation contexts are set to unlabelled
3903 */
3904static int selinux_kernel_act_as(struct cred *new, u32 secid)
3905{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003906 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003907 u32 sid = current_sid();
3908 int ret;
3909
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003910 ret = avc_has_perm(&selinux_state,
3911 sid, secid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003912 SECCLASS_KERNEL_SERVICE,
3913 KERNEL_SERVICE__USE_AS_OVERRIDE,
3914 NULL);
3915 if (ret == 0) {
3916 tsec->sid = secid;
3917 tsec->create_sid = 0;
3918 tsec->keycreate_sid = 0;
3919 tsec->sockcreate_sid = 0;
3920 }
3921 return ret;
3922}
3923
3924/*
3925 * set the file creation context in a security record to the same as the
3926 * objective context of the specified inode
3927 */
3928static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3929{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003930 struct inode_security_struct *isec = inode_security(inode);
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003931 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003932 u32 sid = current_sid();
3933 int ret;
3934
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003935 ret = avc_has_perm(&selinux_state,
3936 sid, isec->sid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003937 SECCLASS_KERNEL_SERVICE,
3938 KERNEL_SERVICE__CREATE_FILES_AS,
3939 NULL);
3940
3941 if (ret == 0)
3942 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003943 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003944}
3945
Eric Parisdd8dbf22009-11-03 16:35:32 +11003946static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003947{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003948 struct common_audit_data ad;
3949
Eric Paris50c205f2012-04-04 15:01:43 -04003950 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003951 ad.u.kmod_name = kmod_name;
3952
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003953 return avc_has_perm(&selinux_state,
3954 current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11003955 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003956}
3957
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003958static int selinux_kernel_module_from_file(struct file *file)
3959{
3960 struct common_audit_data ad;
3961 struct inode_security_struct *isec;
3962 struct file_security_struct *fsec;
3963 u32 sid = current_sid();
3964 int rc;
3965
3966 /* init_module */
3967 if (file == NULL)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003968 return avc_has_perm(&selinux_state,
3969 sid, sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003970 SYSTEM__MODULE_LOAD, NULL);
3971
3972 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003973
Vivek Goyal43af5de2016-09-09 11:37:49 -04003974 ad.type = LSM_AUDIT_DATA_FILE;
3975 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003976
Casey Schauflerbb6c6b02018-09-21 17:22:32 -07003977 fsec = selinux_file(file);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003978 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003979 rc = avc_has_perm(&selinux_state,
3980 sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003981 if (rc)
3982 return rc;
3983 }
3984
Paul Moore20cdef82016-04-04 14:14:42 -04003985 isec = inode_security(file_inode(file));
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003986 return avc_has_perm(&selinux_state,
3987 sid, isec->sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003988 SYSTEM__MODULE_LOAD, &ad);
3989}
3990
3991static int selinux_kernel_read_file(struct file *file,
3992 enum kernel_read_file_id id)
3993{
3994 int rc = 0;
3995
3996 switch (id) {
3997 case READING_MODULE:
3998 rc = selinux_kernel_module_from_file(file);
3999 break;
4000 default:
4001 break;
4002 }
4003
4004 return rc;
4005}
4006
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04004007static int selinux_kernel_load_data(enum kernel_load_data_id id)
4008{
4009 int rc = 0;
4010
4011 switch (id) {
4012 case LOADING_MODULE:
4013 rc = selinux_kernel_module_from_file(NULL);
4014 default:
4015 break;
4016 }
4017
4018 return rc;
4019}
4020
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
4022{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004023 return avc_has_perm(&selinux_state,
4024 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004025 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026}
4027
4028static int selinux_task_getpgid(struct task_struct *p)
4029{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004030 return avc_has_perm(&selinux_state,
4031 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004032 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033}
4034
4035static int selinux_task_getsid(struct task_struct *p)
4036{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004037 return avc_has_perm(&selinux_state,
4038 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004039 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040}
4041
David Quigleyf9008e4c2006-06-30 01:55:46 -07004042static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
4043{
David Howells275bb412008-11-14 10:39:19 +11004044 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07004045}
4046
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047static int selinux_task_setnice(struct task_struct *p, int nice)
4048{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004049 return avc_has_perm(&selinux_state,
4050 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004051 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052}
4053
James Morris03e68062006-06-23 02:03:58 -07004054static int selinux_task_setioprio(struct task_struct *p, int ioprio)
4055{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004056 return avc_has_perm(&selinux_state,
4057 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004058 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07004059}
4060
David Quigleya1836a42006-06-30 01:55:49 -07004061static int selinux_task_getioprio(struct task_struct *p)
4062{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004063 return avc_has_perm(&selinux_state,
4064 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004065 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07004066}
4067
Corentin LABBE42985552017-10-04 20:32:18 +02004068static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
4069 unsigned int flags)
Stephen Smalley791ec492017-02-17 07:57:00 -05004070{
4071 u32 av = 0;
4072
Stephen Smalley84e68852017-02-28 09:35:08 -05004073 if (!flags)
4074 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05004075 if (flags & LSM_PRLIMIT_WRITE)
4076 av |= PROCESS__SETRLIMIT;
4077 if (flags & LSM_PRLIMIT_READ)
4078 av |= PROCESS__GETRLIMIT;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004079 return avc_has_perm(&selinux_state,
4080 cred_sid(cred), cred_sid(tcred),
Stephen Smalley791ec492017-02-17 07:57:00 -05004081 SECCLASS_PROCESS, av, NULL);
4082}
4083
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004084static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
4085 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004087 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088
4089 /* Control the ability to change the hard limit (whether
4090 lowering or raising it), so that the hard limit can
4091 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11004092 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004094 return avc_has_perm(&selinux_state,
4095 current_sid(), task_sid(p),
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004096 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
4098 return 0;
4099}
4100
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09004101static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004103 return avc_has_perm(&selinux_state,
4104 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004105 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106}
4107
4108static int selinux_task_getscheduler(struct task_struct *p)
4109{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004110 return avc_has_perm(&selinux_state,
4111 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004112 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113}
4114
David Quigley35601542006-06-23 02:04:01 -07004115static int selinux_task_movememory(struct task_struct *p)
4116{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004117 return avc_has_perm(&selinux_state,
4118 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004119 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07004120}
4121
Eric W. Biedermanae7795b2018-09-25 11:27:20 +02004122static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004123 int sig, const struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004125 u32 secid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 if (!sig)
4129 perm = PROCESS__SIGNULL; /* null signal; existence test */
4130 else
4131 perm = signal_to_av(sig);
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004132 if (!cred)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004133 secid = current_sid();
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004134 else
4135 secid = cred_sid(cred);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004136 return avc_has_perm(&selinux_state,
4137 secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138}
4139
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140static void selinux_task_to_inode(struct task_struct *p,
4141 struct inode *inode)
4142{
Casey Schaufler80788c22018-09-21 17:19:11 -07004143 struct inode_security_struct *isec = selinux_inode(inode);
David Howells275bb412008-11-14 10:39:19 +11004144 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004146 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004147 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004148 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004149 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004150 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151}
4152
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004154static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004155 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156{
4157 int offset, ihlen, ret = -EINVAL;
4158 struct iphdr _iph, *ih;
4159
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004160 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4162 if (ih == NULL)
4163 goto out;
4164
4165 ihlen = ih->ihl * 4;
4166 if (ihlen < sizeof(_iph))
4167 goto out;
4168
Eric Paris48c62af2012-04-02 13:15:44 -04004169 ad->u.net->v4info.saddr = ih->saddr;
4170 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 ret = 0;
4172
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004173 if (proto)
4174 *proto = ih->protocol;
4175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004177 case IPPROTO_TCP: {
4178 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
Eric Paris828dfe12008-04-17 13:17:49 -04004180 if (ntohs(ih->frag_off) & IP_OFFSET)
4181 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
4183 offset += ihlen;
4184 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4185 if (th == NULL)
4186 break;
4187
Eric Paris48c62af2012-04-02 13:15:44 -04004188 ad->u.net->sport = th->source;
4189 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Eric Paris828dfe12008-04-17 13:17:49 -04004193 case IPPROTO_UDP: {
4194 struct udphdr _udph, *uh;
4195
4196 if (ntohs(ih->frag_off) & IP_OFFSET)
4197 break;
4198
4199 offset += ihlen;
4200 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4201 if (uh == NULL)
4202 break;
4203
Eric Paris48c62af2012-04-02 13:15:44 -04004204 ad->u.net->sport = uh->source;
4205 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004206 break;
4207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208
James Morris2ee92d42006-11-13 16:09:01 -08004209 case IPPROTO_DCCP: {
4210 struct dccp_hdr _dccph, *dh;
4211
4212 if (ntohs(ih->frag_off) & IP_OFFSET)
4213 break;
4214
4215 offset += ihlen;
4216 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4217 if (dh == NULL)
4218 break;
4219
Eric Paris48c62af2012-04-02 13:15:44 -04004220 ad->u.net->sport = dh->dccph_sport;
4221 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004222 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004223 }
James Morris2ee92d42006-11-13 16:09:01 -08004224
Richard Hainesd4529302018-02-13 20:57:18 +00004225#if IS_ENABLED(CONFIG_IP_SCTP)
4226 case IPPROTO_SCTP: {
4227 struct sctphdr _sctph, *sh;
4228
4229 if (ntohs(ih->frag_off) & IP_OFFSET)
4230 break;
4231
4232 offset += ihlen;
4233 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4234 if (sh == NULL)
4235 break;
4236
4237 ad->u.net->sport = sh->source;
4238 ad->u.net->dport = sh->dest;
4239 break;
4240 }
4241#endif
Eric Paris828dfe12008-04-17 13:17:49 -04004242 default:
4243 break;
4244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245out:
4246 return ret;
4247}
4248
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004249#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
4251/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004252static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004253 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254{
4255 u8 nexthdr;
4256 int ret = -EINVAL, offset;
4257 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004258 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004260 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4262 if (ip6 == NULL)
4263 goto out;
4264
Eric Paris48c62af2012-04-02 13:15:44 -04004265 ad->u.net->v6info.saddr = ip6->saddr;
4266 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 ret = 0;
4268
4269 nexthdr = ip6->nexthdr;
4270 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004271 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 if (offset < 0)
4273 goto out;
4274
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004275 if (proto)
4276 *proto = nexthdr;
4277
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 switch (nexthdr) {
4279 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004280 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281
4282 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4283 if (th == NULL)
4284 break;
4285
Eric Paris48c62af2012-04-02 13:15:44 -04004286 ad->u.net->sport = th->source;
4287 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 break;
4289 }
4290
4291 case IPPROTO_UDP: {
4292 struct udphdr _udph, *uh;
4293
4294 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4295 if (uh == NULL)
4296 break;
4297
Eric Paris48c62af2012-04-02 13:15:44 -04004298 ad->u.net->sport = uh->source;
4299 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 break;
4301 }
4302
James Morris2ee92d42006-11-13 16:09:01 -08004303 case IPPROTO_DCCP: {
4304 struct dccp_hdr _dccph, *dh;
4305
4306 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4307 if (dh == NULL)
4308 break;
4309
Eric Paris48c62af2012-04-02 13:15:44 -04004310 ad->u.net->sport = dh->dccph_sport;
4311 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004312 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004313 }
James Morris2ee92d42006-11-13 16:09:01 -08004314
Richard Hainesd4529302018-02-13 20:57:18 +00004315#if IS_ENABLED(CONFIG_IP_SCTP)
4316 case IPPROTO_SCTP: {
4317 struct sctphdr _sctph, *sh;
4318
4319 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4320 if (sh == NULL)
4321 break;
4322
4323 ad->u.net->sport = sh->source;
4324 ad->u.net->dport = sh->dest;
4325 break;
4326 }
4327#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 /* includes fragments */
4329 default:
4330 break;
4331 }
4332out:
4333 return ret;
4334}
4335
4336#endif /* IPV6 */
4337
Thomas Liu2bf49692009-07-14 12:14:09 -04004338static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004339 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340{
David Howellscf9481e2008-07-27 21:31:07 +10004341 char *addrp;
4342 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Eric Paris48c62af2012-04-02 13:15:44 -04004344 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004346 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004347 if (ret)
4348 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004349 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4350 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004351 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004353#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004355 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004356 if (ret)
4357 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004358 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4359 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004360 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361#endif /* IPV6 */
4362 default:
David Howellscf9481e2008-07-27 21:31:07 +10004363 addrp = NULL;
4364 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 }
4366
David Howellscf9481e2008-07-27 21:31:07 +10004367parse_error:
peter enderborgc103a912018-06-12 10:09:03 +02004368 pr_warn(
David Howellscf9481e2008-07-27 21:31:07 +10004369 "SELinux: failure in selinux_parse_skb(),"
4370 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004372
4373okay:
4374 if (_addrp)
4375 *_addrp = addrp;
4376 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377}
4378
Paul Moore4f6a9932007-03-01 14:35:22 -05004379/**
Paul Moore220deb92008-01-29 08:38:23 -05004380 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004381 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004382 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004383 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004384 *
4385 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004386 * Check the various different forms of network peer labeling and determine
4387 * the peer label/SID for the packet; most of the magic actually occurs in
4388 * the security server function security_net_peersid_cmp(). The function
4389 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4390 * or -EACCES if @sid is invalid due to inconsistencies with the different
4391 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004392 *
4393 */
Paul Moore220deb92008-01-29 08:38:23 -05004394static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004395{
Paul Moore71f1cb02008-01-29 08:51:16 -05004396 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004397 u32 xfrm_sid;
4398 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004399 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004400
Paul Moore817eff72013-12-10 14:57:54 -05004401 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004402 if (unlikely(err))
4403 return -EACCES;
4404 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4405 if (unlikely(err))
4406 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004407
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004408 err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
4409 nlbl_type, xfrm_sid, sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004410 if (unlikely(err)) {
peter enderborgc103a912018-06-12 10:09:03 +02004411 pr_warn(
Paul Moore71f1cb02008-01-29 08:51:16 -05004412 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4413 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004414 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004415 }
Paul Moore220deb92008-01-29 08:38:23 -05004416
4417 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004418}
4419
Paul Moore446b8022013-12-04 16:10:51 -05004420/**
4421 * selinux_conn_sid - Determine the child socket label for a connection
4422 * @sk_sid: the parent socket's SID
4423 * @skb_sid: the packet's SID
4424 * @conn_sid: the resulting connection SID
4425 *
4426 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4427 * combined with the MLS information from @skb_sid in order to create
4428 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4429 * of @sk_sid. Returns zero on success, negative values on failure.
4430 *
4431 */
4432static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4433{
4434 int err = 0;
4435
4436 if (skb_sid != SECSID_NULL)
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004437 err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
4438 conn_sid);
Paul Moore446b8022013-12-04 16:10:51 -05004439 else
4440 *conn_sid = sk_sid;
4441
4442 return err;
4443}
4444
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004446
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004447static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4448 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004449{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004450 if (tsec->sockcreate_sid > SECSID_NULL) {
4451 *socksid = tsec->sockcreate_sid;
4452 return 0;
4453 }
4454
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004455 return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
4456 secclass, NULL, socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004457}
4458
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004459static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460{
Paul Moore253bfae2010-04-22 14:46:19 -04004461 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004462 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004463 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Paul Moore253bfae2010-04-22 14:46:19 -04004465 if (sksec->sid == SECINITSID_KERNEL)
4466 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Eric Paris50c205f2012-04-04 15:01:43 -04004468 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004469 ad.u.net = &net;
4470 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004472 return avc_has_perm(&selinux_state,
4473 current_sid(), sksec->sid, sksec->sclass, perms,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004474 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475}
4476
4477static int selinux_socket_create(int family, int type,
4478 int protocol, int kern)
4479{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004480 const struct task_security_struct *tsec = selinux_cred(current_cred());
Paul Moored4f2d972010-04-22 14:46:18 -04004481 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004482 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004483 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484
4485 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004486 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
David Howells275bb412008-11-14 10:39:19 +11004488 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004489 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4490 if (rc)
4491 return rc;
4492
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004493 return avc_has_perm(&selinux_state,
4494 tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495}
4496
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004497static int selinux_socket_post_create(struct socket *sock, int family,
4498 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004500 const struct task_security_struct *tsec = selinux_cred(current_cred());
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004501 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004502 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004503 u16 sclass = socket_type_to_security_class(family, type, protocol);
4504 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004505 int err = 0;
4506
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004507 if (!kern) {
4508 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004509 if (err)
4510 return err;
4511 }
David Howells275bb412008-11-14 10:39:19 +11004512
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004513 isec->sclass = sclass;
4514 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004515 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004517 if (sock->sk) {
4518 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004519 sksec->sclass = sclass;
4520 sksec->sid = sid;
Richard Hainesd4529302018-02-13 20:57:18 +00004521 /* Allows detection of the first association on this socket */
4522 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4523 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4524
Paul Moore389fb8002009-03-27 17:10:34 -04004525 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004526 }
4527
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004528 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529}
4530
David Herrmann0b811db2018-05-04 16:28:21 +02004531static int selinux_socket_socketpair(struct socket *socka,
4532 struct socket *sockb)
4533{
4534 struct sk_security_struct *sksec_a = socka->sk->sk_security;
4535 struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4536
4537 sksec_a->peer_sid = sksec_b->sid;
4538 sksec_b->peer_sid = sksec_a->sid;
4539
4540 return 0;
4541}
4542
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543/* Range of port numbers used to automatically bind.
4544 Need to determine whether we should perform a name_bind
4545 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546
4547static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4548{
Paul Moore253bfae2010-04-22 14:46:19 -04004549 struct sock *sk = sock->sk;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004550 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 u16 family;
4552 int err;
4553
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004554 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 if (err)
4556 goto out;
4557
Richard Hainesd4529302018-02-13 20:57:18 +00004558 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
Paul Moore253bfae2010-04-22 14:46:19 -04004559 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 if (family == PF_INET || family == PF_INET6) {
4561 char *addrp;
Thomas Liu2bf49692009-07-14 12:14:09 -04004562 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004563 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 struct sockaddr_in *addr4 = NULL;
4565 struct sockaddr_in6 *addr6 = NULL;
Tetsuo Handac750e692019-04-12 19:59:34 +09004566 u16 family_sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004568 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569
Richard Hainesd4529302018-02-13 20:57:18 +00004570 /*
4571 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4572 * that validates multiple binding addresses. Because of this
4573 * need to check address->sa_family as it is possible to have
4574 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4575 */
Tetsuo Handac750e692019-04-12 19:59:34 +09004576 if (addrlen < offsetofend(struct sockaddr, sa_family))
4577 return -EINVAL;
4578 family_sa = address->sa_family;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004579 switch (family_sa) {
4580 case AF_UNSPEC:
Richard Haines68741a8a2018-03-02 19:54:34 +00004581 case AF_INET:
4582 if (addrlen < sizeof(struct sockaddr_in))
4583 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 addr4 = (struct sockaddr_in *)address;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004585 if (family_sa == AF_UNSPEC) {
4586 /* see __inet_bind(), we only want to allow
4587 * AF_UNSPEC if the address is INADDR_ANY
4588 */
4589 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4590 goto err_af;
4591 family_sa = AF_INET;
4592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 addrp = (char *)&addr4->sin_addr.s_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004595 break;
4596 case AF_INET6:
4597 if (addrlen < SIN6_LEN_RFC2133)
4598 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599 addr6 = (struct sockaddr_in6 *)address;
4600 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 addrp = (char *)&addr6->sin6_addr.s6_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004602 break;
4603 default:
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004604 goto err_af;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 }
4606
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004607 ad.type = LSM_AUDIT_DATA_NET;
4608 ad.u.net = &net;
4609 ad.u.net->sport = htons(snum);
4610 ad.u.net->family = family_sa;
4611
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004612 if (snum) {
4613 int low, high;
4614
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004615 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004616
Maciej Żenczykowski82f31eb2019-11-25 15:37:04 -08004617 if (inet_port_requires_bind_service(sock_net(sk), snum) ||
4618 snum < low || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004619 err = sel_netport_sid(sk->sk_protocol,
4620 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004621 if (err)
4622 goto out;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004623 err = avc_has_perm(&selinux_state,
4624 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004625 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004626 SOCKET__NAME_BIND, &ad);
4627 if (err)
4628 goto out;
4629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 }
Eric Paris828dfe12008-04-17 13:17:49 -04004631
Paul Moore253bfae2010-04-22 14:46:19 -04004632 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004633 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 node_perm = TCP_SOCKET__NODE_BIND;
4635 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004636
James Morris13402582005-09-30 14:24:34 -04004637 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638 node_perm = UDP_SOCKET__NODE_BIND;
4639 break;
James Morris2ee92d42006-11-13 16:09:01 -08004640
4641 case SECCLASS_DCCP_SOCKET:
4642 node_perm = DCCP_SOCKET__NODE_BIND;
4643 break;
4644
Richard Hainesd4529302018-02-13 20:57:18 +00004645 case SECCLASS_SCTP_SOCKET:
4646 node_perm = SCTP_SOCKET__NODE_BIND;
4647 break;
4648
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 default:
4650 node_perm = RAWIP_SOCKET__NODE_BIND;
4651 break;
4652 }
Eric Paris828dfe12008-04-17 13:17:49 -04004653
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004654 err = sel_netnode_sid(addrp, family_sa, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655 if (err)
4656 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004657
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004658 if (family_sa == AF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004659 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 else
Eric Paris48c62af2012-04-02 13:15:44 -04004661 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004663 err = avc_has_perm(&selinux_state,
4664 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004665 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666 if (err)
4667 goto out;
4668 }
4669out:
4670 return err;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004671err_af:
4672 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4673 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4674 return -EINVAL;
4675 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676}
4677
Richard Hainesd4529302018-02-13 20:57:18 +00004678/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
Kees Cookd61330c2019-02-17 14:08:36 -08004679 * and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
Richard Hainesd4529302018-02-13 20:57:18 +00004680 */
4681static int selinux_socket_connect_helper(struct socket *sock,
4682 struct sockaddr *address, int addrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683{
Paul Moore014ab192008-10-10 10:16:33 -04004684 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004685 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686 int err;
4687
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004688 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004689 if (err)
4690 return err;
Paolo Abeni05174c92019-05-10 19:12:33 +02004691 if (addrlen < offsetofend(struct sockaddr, sa_family))
4692 return -EINVAL;
4693
4694 /* connect(AF_UNSPEC) has special handling, as it is a documented
4695 * way to disconnect the socket
4696 */
4697 if (address->sa_family == AF_UNSPEC)
4698 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699
4700 /*
Richard Hainesd4529302018-02-13 20:57:18 +00004701 * If a TCP, DCCP or SCTP socket, check name_connect permission
4702 * for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703 */
Paul Moore253bfae2010-04-22 14:46:19 -04004704 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004705 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4706 sksec->sclass == SECCLASS_SCTP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004707 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004708 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709 struct sockaddr_in *addr4 = NULL;
4710 struct sockaddr_in6 *addr6 = NULL;
4711 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004712 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713
Richard Hainesd4529302018-02-13 20:57:18 +00004714 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4715 * that validates multiple connect addresses. Because of this
4716 * need to check address->sa_family as it is possible to have
4717 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4718 */
Richard Haines68741a8a2018-03-02 19:54:34 +00004719 switch (address->sa_family) {
4720 case AF_INET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004722 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723 return -EINVAL;
4724 snum = ntohs(addr4->sin_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004725 break;
4726 case AF_INET6:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004728 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729 return -EINVAL;
4730 snum = ntohs(addr6->sin6_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004731 break;
4732 default:
4733 /* Note that SCTP services expect -EINVAL, whereas
4734 * others expect -EAFNOSUPPORT.
4735 */
4736 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4737 return -EINVAL;
4738 else
4739 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740 }
4741
Paul Moore3e112172008-04-10 10:48:14 -04004742 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004744 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745
Richard Hainesd4529302018-02-13 20:57:18 +00004746 switch (sksec->sclass) {
4747 case SECCLASS_TCP_SOCKET:
4748 perm = TCP_SOCKET__NAME_CONNECT;
4749 break;
4750 case SECCLASS_DCCP_SOCKET:
4751 perm = DCCP_SOCKET__NAME_CONNECT;
4752 break;
4753 case SECCLASS_SCTP_SOCKET:
4754 perm = SCTP_SOCKET__NAME_CONNECT;
4755 break;
4756 }
James Morris2ee92d42006-11-13 16:09:01 -08004757
Eric Paris50c205f2012-04-04 15:01:43 -04004758 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004759 ad.u.net = &net;
4760 ad.u.net->dport = htons(snum);
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004761 ad.u.net->family = address->sa_family;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004762 err = avc_has_perm(&selinux_state,
4763 sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004765 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766 }
4767
Richard Hainesd4529302018-02-13 20:57:18 +00004768 return 0;
4769}
Paul Moore014ab192008-10-10 10:16:33 -04004770
Richard Hainesd4529302018-02-13 20:57:18 +00004771/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4772static int selinux_socket_connect(struct socket *sock,
4773 struct sockaddr *address, int addrlen)
4774{
4775 int err;
4776 struct sock *sk = sock->sk;
4777
4778 err = selinux_socket_connect_helper(sock, address, addrlen);
4779 if (err)
4780 return err;
4781
4782 return selinux_netlbl_socket_connect(sk, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783}
4784
4785static int selinux_socket_listen(struct socket *sock, int backlog)
4786{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004787 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788}
4789
4790static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4791{
4792 int err;
4793 struct inode_security_struct *isec;
4794 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004795 u16 sclass;
4796 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004798 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 if (err)
4800 return err;
4801
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004802 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004803 spin_lock(&isec->lock);
4804 sclass = isec->sclass;
4805 sid = isec->sid;
4806 spin_unlock(&isec->lock);
4807
4808 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4809 newisec->sclass = sclass;
4810 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004811 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812
4813 return 0;
4814}
4815
4816static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004817 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004819 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820}
4821
4822static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4823 int size, int flags)
4824{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004825 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826}
4827
4828static int selinux_socket_getsockname(struct socket *sock)
4829{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004830 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831}
4832
4833static int selinux_socket_getpeername(struct socket *sock)
4834{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004835 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836}
4837
Eric Paris828dfe12008-04-17 13:17:49 -04004838static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839{
Paul Mooref8687af2006-10-30 15:22:15 -08004840 int err;
4841
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004842 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004843 if (err)
4844 return err;
4845
4846 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847}
4848
4849static int selinux_socket_getsockopt(struct socket *sock, int level,
4850 int optname)
4851{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004852 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853}
4854
4855static int selinux_socket_shutdown(struct socket *sock, int how)
4856{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004857 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858}
4859
David S. Miller3610cda2011-01-05 15:38:53 -08004860static int selinux_socket_unix_stream_connect(struct sock *sock,
4861 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862 struct sock *newsk)
4863{
David S. Miller3610cda2011-01-05 15:38:53 -08004864 struct sk_security_struct *sksec_sock = sock->sk_security;
4865 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004866 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004867 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004868 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869 int err;
4870
Eric Paris50c205f2012-04-04 15:01:43 -04004871 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004872 ad.u.net = &net;
4873 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004874
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004875 err = avc_has_perm(&selinux_state,
4876 sksec_sock->sid, sksec_other->sid,
Paul Moore4d1e2452010-04-22 14:46:18 -04004877 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4879 if (err)
4880 return err;
4881
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004883 sksec_new->peer_sid = sksec_sock->sid;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004884 err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
4885 sksec_sock->sid, &sksec_new->sid);
Paul Moore4d1e2452010-04-22 14:46:18 -04004886 if (err)
4887 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004888
Paul Moore4d1e2452010-04-22 14:46:18 -04004889 /* connecting socket */
4890 sksec_sock->peer_sid = sksec_new->sid;
4891
4892 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893}
4894
4895static int selinux_socket_unix_may_send(struct socket *sock,
4896 struct socket *other)
4897{
Paul Moore253bfae2010-04-22 14:46:19 -04004898 struct sk_security_struct *ssec = sock->sk->sk_security;
4899 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004900 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004901 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902
Eric Paris50c205f2012-04-04 15:01:43 -04004903 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004904 ad.u.net = &net;
4905 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004907 return avc_has_perm(&selinux_state,
4908 ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
Paul Moore253bfae2010-04-22 14:46:19 -04004909 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910}
4911
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004912static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4913 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004914 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004915{
4916 int err;
4917 u32 if_sid;
4918 u32 node_sid;
4919
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004920 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004921 if (err)
4922 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004923 err = avc_has_perm(&selinux_state,
4924 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004925 SECCLASS_NETIF, NETIF__INGRESS, ad);
4926 if (err)
4927 return err;
4928
4929 err = sel_netnode_sid(addrp, family, &node_sid);
4930 if (err)
4931 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004932 return avc_has_perm(&selinux_state,
4933 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004934 SECCLASS_NODE, NODE__RECVFROM, ad);
4935}
4936
Paul Moore220deb92008-01-29 08:38:23 -05004937static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004938 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004939{
Paul Moore277d3422008-12-31 12:54:11 -05004940 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004941 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004942 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004943 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004944 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004945 char *addrp;
4946
Eric Paris50c205f2012-04-04 15:01:43 -04004947 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004948 ad.u.net = &net;
4949 ad.u.net->netif = skb->skb_iif;
4950 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004951 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4952 if (err)
4953 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004954
Paul Moore58bfbb52009-03-27 17:10:41 -04004955 if (selinux_secmark_enabled()) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004956 err = avc_has_perm(&selinux_state,
4957 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004958 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004959 if (err)
4960 return err;
4961 }
Paul Moore220deb92008-01-29 08:38:23 -05004962
Steffen Klassertb9679a72011-02-23 12:55:21 +01004963 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4964 if (err)
4965 return err;
4966 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004967
James Morris4e5ab4c2006-06-09 00:33:33 -07004968 return err;
4969}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004970
James Morris4e5ab4c2006-06-09 00:33:33 -07004971static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4972{
Paul Moore220deb92008-01-29 08:38:23 -05004973 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004974 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004975 u16 family = sk->sk_family;
4976 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004977 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004978 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004979 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004980 u8 secmark_active;
4981 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004982
James Morris4e5ab4c2006-06-09 00:33:33 -07004983 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004984 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004985
4986 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004987 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004988 family = PF_INET;
4989
Paul Moored8395c82008-10-10 10:16:30 -04004990 /* If any sort of compatibility mode is enabled then handoff processing
4991 * to the selinux_sock_rcv_skb_compat() function to deal with the
4992 * special handling. We do this in an attempt to keep this function
4993 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004994 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04004995 return selinux_sock_rcv_skb_compat(sk, skb, family);
4996
4997 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004998 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004999 if (!secmark_active && !peerlbl_active)
5000 return 0;
5001
Eric Paris50c205f2012-04-04 15:01:43 -04005002 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005003 ad.u.net = &net;
5004 ad.u.net->netif = skb->skb_iif;
5005 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05005006 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07005007 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05005008 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07005009
Paul Moored8395c82008-10-10 10:16:30 -04005010 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05005011 u32 peer_sid;
5012
5013 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
5014 if (err)
5015 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005016 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
5017 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005018 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005019 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005020 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04005021 }
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005022 err = avc_has_perm(&selinux_state,
5023 sk_sid, peer_sid, SECCLASS_PEER,
Paul Moored621d352008-01-29 08:43:36 -05005024 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05005025 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005026 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05005027 return err;
5028 }
Paul Moored621d352008-01-29 08:43:36 -05005029 }
5030
Paul Moored8395c82008-10-10 10:16:30 -04005031 if (secmark_active) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005032 err = avc_has_perm(&selinux_state,
5033 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005034 PACKET__RECV, &ad);
5035 if (err)
5036 return err;
5037 }
5038
Paul Moored621d352008-01-29 08:43:36 -05005039 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040}
5041
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005042static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
5043 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044{
5045 int err = 0;
5046 char *scontext;
5047 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04005048 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05005049 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
Paul Moore253bfae2010-04-22 14:46:19 -04005051 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00005052 sksec->sclass == SECCLASS_TCP_SOCKET ||
5053 sksec->sclass == SECCLASS_SCTP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04005054 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04005055 if (peer_sid == SECSID_NULL)
5056 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005058 err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
5059 &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04005061 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062
5063 if (scontext_len > len) {
5064 err = -ERANGE;
5065 goto out_len;
5066 }
5067
5068 if (copy_to_user(optval, scontext, scontext_len))
5069 err = -EFAULT;
5070
5071out_len:
5072 if (put_user(scontext_len, optlen))
5073 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075 return err;
5076}
5077
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005078static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005079{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005080 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05005081 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04005082 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07005083
Paul Mooreaa862902008-10-10 10:16:29 -04005084 if (skb && skb->protocol == htons(ETH_P_IP))
5085 family = PF_INET;
5086 else if (skb && skb->protocol == htons(ETH_P_IPV6))
5087 family = PF_INET6;
5088 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05005089 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05005090 else
5091 goto out;
5092
Paul Moore899134f2016-03-28 15:19:10 -04005093 if (sock && family == PF_UNIX) {
5094 isec = inode_security_novalidate(SOCK_INODE(sock));
5095 peer_secid = isec->sid;
5096 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05005097 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005098
Paul Moore75e22912008-01-29 08:38:04 -05005099out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005100 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05005101 if (peer_secid == SECSID_NULL)
5102 return -EINVAL;
5103 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005104}
5105
Al Viro7d877f32005-10-21 03:20:43 -04005106static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107{
Paul Moore84914b72010-04-22 14:46:18 -04005108 struct sk_security_struct *sksec;
5109
5110 sksec = kzalloc(sizeof(*sksec), priority);
5111 if (!sksec)
5112 return -ENOMEM;
5113
5114 sksec->peer_sid = SECINITSID_UNLABELED;
5115 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04005116 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04005117 selinux_netlbl_sk_security_reset(sksec);
5118 sk->sk_security = sksec;
5119
5120 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121}
5122
5123static void selinux_sk_free_security(struct sock *sk)
5124{
Paul Moore84914b72010-04-22 14:46:18 -04005125 struct sk_security_struct *sksec = sk->sk_security;
5126
5127 sk->sk_security = NULL;
5128 selinux_netlbl_sk_security_free(sksec);
5129 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130}
5131
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005132static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
5133{
Eric Parisdd3e7832010-04-07 15:08:46 -04005134 struct sk_security_struct *sksec = sk->sk_security;
5135 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005136
Eric Parisdd3e7832010-04-07 15:08:46 -04005137 newsksec->sid = sksec->sid;
5138 newsksec->peer_sid = sksec->peer_sid;
5139 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07005140
Eric Parisdd3e7832010-04-07 15:08:46 -04005141 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005142}
5143
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005144static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005145{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005146 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005147 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005148 else {
5149 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005150
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005151 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005152 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005153}
5154
Eric Paris828dfe12008-04-17 13:17:49 -04005155static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005156{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05005157 struct inode_security_struct *isec =
5158 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005159 struct sk_security_struct *sksec = sk->sk_security;
5160
Paul Moore2873ead2014-07-28 10:42:48 -04005161 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5162 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07005163 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05005164 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005165}
5166
Richard Hainesd4529302018-02-13 20:57:18 +00005167/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5168 * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5169 * already present).
5170 */
5171static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5172 struct sk_buff *skb)
5173{
5174 struct sk_security_struct *sksec = ep->base.sk->sk_security;
5175 struct common_audit_data ad;
5176 struct lsm_network_audit net = {0,};
5177 u8 peerlbl_active;
5178 u32 peer_sid = SECINITSID_UNLABELED;
5179 u32 conn_sid;
5180 int err = 0;
5181
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005182 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005183 return 0;
5184
5185 peerlbl_active = selinux_peerlbl_enabled();
5186
5187 if (peerlbl_active) {
5188 /* This will return peer_sid = SECSID_NULL if there are
5189 * no peer labels, see security_net_peersid_resolve().
5190 */
5191 err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5192 &peer_sid);
5193 if (err)
5194 return err;
5195
5196 if (peer_sid == SECSID_NULL)
5197 peer_sid = SECINITSID_UNLABELED;
5198 }
5199
5200 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5201 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5202
5203 /* Here as first association on socket. As the peer SID
5204 * was allowed by peer recv (and the netif/node checks),
5205 * then it is approved by policy and used as the primary
5206 * peer SID for getpeercon(3).
5207 */
5208 sksec->peer_sid = peer_sid;
5209 } else if (sksec->peer_sid != peer_sid) {
5210 /* Other association peer SIDs are checked to enforce
5211 * consistency among the peer SIDs.
5212 */
5213 ad.type = LSM_AUDIT_DATA_NET;
5214 ad.u.net = &net;
5215 ad.u.net->sk = ep->base.sk;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005216 err = avc_has_perm(&selinux_state,
5217 sksec->peer_sid, peer_sid, sksec->sclass,
Richard Hainesd4529302018-02-13 20:57:18 +00005218 SCTP_SOCKET__ASSOCIATION, &ad);
5219 if (err)
5220 return err;
5221 }
5222
5223 /* Compute the MLS component for the connection and store
5224 * the information in ep. This will be used by SCTP TCP type
5225 * sockets and peeled off connections as they cause a new
5226 * socket to be generated. selinux_sctp_sk_clone() will then
5227 * plug this into the new socket.
5228 */
5229 err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5230 if (err)
5231 return err;
5232
5233 ep->secid = conn_sid;
5234 ep->peer_secid = peer_sid;
5235
5236 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
5237 return selinux_netlbl_sctp_assoc_request(ep, skb);
5238}
5239
5240/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5241 * based on their @optname.
5242 */
5243static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5244 struct sockaddr *address,
5245 int addrlen)
5246{
5247 int len, err = 0, walk_size = 0;
5248 void *addr_buf;
5249 struct sockaddr *addr;
5250 struct socket *sock;
5251
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005252 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005253 return 0;
5254
5255 /* Process one or more addresses that may be IPv4 or IPv6 */
5256 sock = sk->sk_socket;
5257 addr_buf = address;
5258
5259 while (walk_size < addrlen) {
Ondrej Mosnacekc1383252018-11-13 16:16:08 +01005260 if (walk_size + sizeof(sa_family_t) > addrlen)
5261 return -EINVAL;
5262
Richard Hainesd4529302018-02-13 20:57:18 +00005263 addr = addr_buf;
5264 switch (addr->sa_family) {
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005265 case AF_UNSPEC:
Richard Hainesd4529302018-02-13 20:57:18 +00005266 case AF_INET:
5267 len = sizeof(struct sockaddr_in);
5268 break;
5269 case AF_INET6:
5270 len = sizeof(struct sockaddr_in6);
5271 break;
5272 default:
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005273 return -EINVAL;
Richard Hainesd4529302018-02-13 20:57:18 +00005274 }
5275
Xin Long292c9972019-03-09 00:07:34 +08005276 if (walk_size + len > addrlen)
5277 return -EINVAL;
5278
Richard Hainesd4529302018-02-13 20:57:18 +00005279 err = -EINVAL;
5280 switch (optname) {
5281 /* Bind checks */
5282 case SCTP_PRIMARY_ADDR:
5283 case SCTP_SET_PEER_PRIMARY_ADDR:
5284 case SCTP_SOCKOPT_BINDX_ADD:
5285 err = selinux_socket_bind(sock, addr, len);
5286 break;
5287 /* Connect checks */
5288 case SCTP_SOCKOPT_CONNECTX:
5289 case SCTP_PARAM_SET_PRIMARY:
5290 case SCTP_PARAM_ADD_IP:
5291 case SCTP_SENDMSG_CONNECT:
5292 err = selinux_socket_connect_helper(sock, addr, len);
5293 if (err)
5294 return err;
5295
5296 /* As selinux_sctp_bind_connect() is called by the
5297 * SCTP protocol layer, the socket is already locked,
5298 * therefore selinux_netlbl_socket_connect_locked() is
5299 * is called here. The situations handled are:
5300 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5301 * whenever a new IP address is added or when a new
5302 * primary address is selected.
5303 * Note that an SCTP connect(2) call happens before
5304 * the SCTP protocol layer and is handled via
5305 * selinux_socket_connect().
5306 */
5307 err = selinux_netlbl_socket_connect_locked(sk, addr);
5308 break;
5309 }
5310
5311 if (err)
5312 return err;
5313
5314 addr_buf += len;
5315 walk_size += len;
5316 }
5317
5318 return 0;
5319}
5320
5321/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
5322static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5323 struct sock *newsk)
5324{
5325 struct sk_security_struct *sksec = sk->sk_security;
5326 struct sk_security_struct *newsksec = newsk->sk_security;
5327
5328 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5329 * the non-sctp clone version.
5330 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005331 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005332 return selinux_sk_clone_security(sk, newsk);
5333
5334 newsksec->sid = ep->secid;
5335 newsksec->peer_sid = ep->peer_secid;
5336 newsksec->sclass = sksec->sclass;
5337 selinux_netlbl_sctp_sk_clone(sk, newsk);
5338}
5339
Adrian Bunk9a673e52006-08-15 00:03:53 -07005340static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
5341 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005342{
5343 struct sk_security_struct *sksec = sk->sk_security;
5344 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05005345 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05005346 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005347 u32 peersid;
5348
Paul Mooreaa862902008-10-10 10:16:29 -04005349 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05005350 if (err)
5351 return err;
Paul Moore446b8022013-12-04 16:10:51 -05005352 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5353 if (err)
5354 return err;
5355 req->secid = connsid;
5356 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07005357
Paul Moore389fb8002009-03-27 17:10:34 -04005358 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005359}
5360
Adrian Bunk9a673e52006-08-15 00:03:53 -07005361static void selinux_inet_csk_clone(struct sock *newsk,
5362 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005363{
5364 struct sk_security_struct *newsksec = newsk->sk_security;
5365
5366 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005367 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005368 /* NOTE: Ideally, we should also get the isec->sid for the
5369 new socket in sync, but we don't have the isec available yet.
5370 So we will wait until sock_graft to do it, by which
5371 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07005372
Paul Moore9f2ad662006-11-17 17:38:53 -05005373 /* We don't need to take any sort of lock here as we are the only
5374 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04005375 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005376}
5377
Paul Moore014ab192008-10-10 10:16:33 -04005378static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005379{
Paul Mooreaa862902008-10-10 10:16:29 -04005380 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005381 struct sk_security_struct *sksec = sk->sk_security;
5382
Paul Mooreaa862902008-10-10 10:16:29 -04005383 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5384 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5385 family = PF_INET;
5386
5387 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005388}
5389
Eric Paris2606fd12010-10-13 16:24:41 -04005390static int selinux_secmark_relabel_packet(u32 sid)
5391{
5392 const struct task_security_struct *__tsec;
5393 u32 tsid;
5394
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07005395 __tsec = selinux_cred(current_cred());
Eric Paris2606fd12010-10-13 16:24:41 -04005396 tsid = __tsec->sid;
5397
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005398 return avc_has_perm(&selinux_state,
5399 tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
5400 NULL);
Eric Paris2606fd12010-10-13 16:24:41 -04005401}
5402
5403static void selinux_secmark_refcount_inc(void)
5404{
5405 atomic_inc(&selinux_secmark_refcount);
5406}
5407
5408static void selinux_secmark_refcount_dec(void)
5409{
5410 atomic_dec(&selinux_secmark_refcount);
5411}
5412
Adrian Bunk9a673e52006-08-15 00:03:53 -07005413static void selinux_req_classify_flow(const struct request_sock *req,
5414 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005415{
David S. Miller1d28f422011-03-12 00:29:39 -05005416 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005417}
5418
Paul Moore5dbbaf22013-01-14 07:12:19 +00005419static int selinux_tun_dev_alloc_security(void **security)
5420{
5421 struct tun_security_struct *tunsec;
5422
5423 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5424 if (!tunsec)
5425 return -ENOMEM;
5426 tunsec->sid = current_sid();
5427
5428 *security = tunsec;
5429 return 0;
5430}
5431
5432static void selinux_tun_dev_free_security(void *security)
5433{
5434 kfree(security);
5435}
5436
Paul Mooreed6d76e2009-08-28 18:12:49 -04005437static int selinux_tun_dev_create(void)
5438{
5439 u32 sid = current_sid();
5440
5441 /* we aren't taking into account the "sockcreate" SID since the socket
5442 * that is being created here is not a socket in the traditional sense,
5443 * instead it is a private sock, accessible only to the kernel, and
5444 * representing a wide range of network traffic spanning multiple
5445 * connections unlike traditional sockets - check the TUN driver to
5446 * get a better understanding of why this socket is special */
5447
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005448 return avc_has_perm(&selinux_state,
5449 sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005450 NULL);
5451}
5452
Paul Moore5dbbaf22013-01-14 07:12:19 +00005453static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005454{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005455 struct tun_security_struct *tunsec = security;
5456
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005457 return avc_has_perm(&selinux_state,
5458 current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005459 TUN_SOCKET__ATTACH_QUEUE, NULL);
5460}
5461
5462static int selinux_tun_dev_attach(struct sock *sk, void *security)
5463{
5464 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005465 struct sk_security_struct *sksec = sk->sk_security;
5466
5467 /* we don't currently perform any NetLabel based labeling here and it
5468 * isn't clear that we would want to do so anyway; while we could apply
5469 * labeling without the support of the TUN user the resulting labeled
5470 * traffic from the other end of the connection would almost certainly
5471 * cause confusion to the TUN user that had no idea network labeling
5472 * protocols were being used */
5473
Paul Moore5dbbaf22013-01-14 07:12:19 +00005474 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005475 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005476
5477 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005478}
5479
Paul Moore5dbbaf22013-01-14 07:12:19 +00005480static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005481{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005482 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005483 u32 sid = current_sid();
5484 int err;
5485
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005486 err = avc_has_perm(&selinux_state,
5487 sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005488 TUN_SOCKET__RELABELFROM, NULL);
5489 if (err)
5490 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005491 err = avc_has_perm(&selinux_state,
5492 sid, sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005493 TUN_SOCKET__RELABELTO, NULL);
5494 if (err)
5495 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005496 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005497
5498 return 0;
5499}
5500
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501#ifdef CONFIG_NETFILTER
5502
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005503static unsigned int selinux_ip_forward(struct sk_buff *skb,
5504 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005505 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506{
Paul Mooredfaebe92008-10-10 10:16:31 -04005507 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005508 char *addrp;
5509 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005510 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005511 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005512 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005513 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005514 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005515
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005516 if (!selinux_policycap_netpeer())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005517 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005518
Paul Mooreeffad8d2008-01-29 08:49:27 -05005519 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005520 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005521 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005522 if (!secmark_active && !peerlbl_active)
5523 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005524
Paul Moored8395c82008-10-10 10:16:30 -04005525 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5526 return NF_DROP;
5527
Eric Paris50c205f2012-04-04 15:01:43 -04005528 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005529 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005530 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005531 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005532 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5533 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534
Paul Mooredfaebe92008-10-10 10:16:31 -04005535 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005536 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5537 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005538 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005539 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005540 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005541 }
5542 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005543
5544 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005545 if (avc_has_perm(&selinux_state,
5546 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005547 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5548 return NF_DROP;
5549
Paul Moore948bf852008-10-10 10:16:32 -04005550 if (netlbl_active)
5551 /* we do this in the FORWARD path and not the POST_ROUTING
5552 * path because we want to make sure we apply the necessary
5553 * labeling before IPsec is applied so we can leverage AH
5554 * protection */
5555 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5556 return NF_DROP;
5557
Paul Mooreeffad8d2008-01-29 08:49:27 -05005558 return NF_ACCEPT;
5559}
5560
Eric W. Biederman06198b32015-09-18 14:33:06 -05005561static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005562 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005563 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005564{
David S. Miller238e54c2015-04-03 20:32:56 -04005565 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005566}
5567
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005568#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005569static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005570 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005571 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005572{
David S. Miller238e54c2015-04-03 20:32:56 -04005573 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005574}
5575#endif /* IPV6 */
5576
Paul Moore948bf852008-10-10 10:16:32 -04005577static unsigned int selinux_ip_output(struct sk_buff *skb,
5578 u16 family)
5579{
Paul Moore47180062013-12-04 16:10:45 -05005580 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005581 u32 sid;
5582
5583 if (!netlbl_enabled())
5584 return NF_ACCEPT;
5585
5586 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5587 * because we want to make sure we apply the necessary labeling
5588 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005589 sk = skb->sk;
5590 if (sk) {
5591 struct sk_security_struct *sksec;
5592
Eric Dumazete446f9d2015-10-08 05:01:55 -07005593 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005594 /* if the socket is the listening state then this
5595 * packet is a SYN-ACK packet which means it needs to
5596 * be labeled based on the connection/request_sock and
5597 * not the parent socket. unfortunately, we can't
5598 * lookup the request_sock yet as it isn't queued on
5599 * the parent socket until after the SYN-ACK is sent.
5600 * the "solution" is to simply pass the packet as-is
5601 * as any IP option based labeling should be copied
5602 * from the initial connection request (in the IP
5603 * layer). it is far from ideal, but until we get a
5604 * security label in the packet itself this is the
5605 * best we can do. */
5606 return NF_ACCEPT;
5607
5608 /* standard practice, label using the parent socket */
5609 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005610 sid = sksec->sid;
5611 } else
5612 sid = SECINITSID_KERNEL;
5613 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5614 return NF_DROP;
5615
5616 return NF_ACCEPT;
5617}
5618
Eric W. Biederman06198b32015-09-18 14:33:06 -05005619static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005620 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005621 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005622{
5623 return selinux_ip_output(skb, PF_INET);
5624}
5625
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005626#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005627static unsigned int selinux_ipv6_output(void *priv,
5628 struct sk_buff *skb,
5629 const struct nf_hook_state *state)
5630{
5631 return selinux_ip_output(skb, PF_INET6);
5632}
5633#endif /* IPV6 */
5634
Paul Mooreeffad8d2008-01-29 08:49:27 -05005635static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5636 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005637 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005638{
Eric Dumazet54abc682015-11-08 10:54:07 -08005639 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005640 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005641 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005642 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005643 char *addrp;
5644 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005645
Paul Mooreeffad8d2008-01-29 08:49:27 -05005646 if (sk == NULL)
5647 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005648 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005649
Eric Paris50c205f2012-04-04 15:01:43 -04005650 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005651 ad.u.net = &net;
5652 ad.u.net->netif = ifindex;
5653 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005654 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5655 return NF_DROP;
5656
Paul Moore58bfbb52009-03-27 17:10:41 -04005657 if (selinux_secmark_enabled())
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005658 if (avc_has_perm(&selinux_state,
5659 sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005660 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005661 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005662
Steffen Klassertb9679a72011-02-23 12:55:21 +01005663 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5664 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005665
Paul Mooreeffad8d2008-01-29 08:49:27 -05005666 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667}
5668
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005669static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5670 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005671 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005673 u32 secmark_perm;
5674 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005675 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005676 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005677 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005678 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005679 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005680 u8 secmark_active;
5681 u8 peerlbl_active;
5682
Paul Mooreeffad8d2008-01-29 08:49:27 -05005683 /* If any sort of compatibility mode is enabled then handoff processing
5684 * to the selinux_ip_postroute_compat() function to deal with the
5685 * special handling. We do this in an attempt to keep this function
5686 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005687 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005688 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005689
Paul Mooreeffad8d2008-01-29 08:49:27 -05005690 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005691 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005692 if (!secmark_active && !peerlbl_active)
5693 return NF_ACCEPT;
5694
Eric Dumazet54abc682015-11-08 10:54:07 -08005695 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005696
Paul Mooreeffad8d2008-01-29 08:49:27 -05005697#ifdef CONFIG_XFRM
5698 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5699 * packet transformation so allow the packet to pass without any checks
5700 * since we'll have another chance to perform access control checks
5701 * when the packet is on it's final way out.
5702 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005703 * is NULL, in this case go ahead and apply access control.
5704 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5705 * TCP listening state we cannot wait until the XFRM processing
5706 * is done as we will miss out on the SA label if we do;
5707 * unfortunately, this means more work, but it is only once per
5708 * connection. */
5709 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005710 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005711 return NF_ACCEPT;
5712#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005713
Paul Moored8395c82008-10-10 10:16:30 -04005714 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005715 /* Without an associated socket the packet is either coming
5716 * from the kernel or it is being forwarded; check the packet
5717 * to determine which and if the packet is being forwarded
5718 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005719 if (skb->skb_iif) {
5720 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005721 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005722 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005723 } else {
5724 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005725 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005726 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005727 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005728 /* Locally generated packet but the associated socket is in the
5729 * listening state which means this is a SYN-ACK packet. In
5730 * this particular case the correct security label is assigned
5731 * to the connection/request_sock but unfortunately we can't
5732 * query the request_sock as it isn't queued on the parent
5733 * socket until after the SYN-ACK packet is sent; the only
5734 * viable choice is to regenerate the label like we do in
5735 * selinux_inet_conn_request(). See also selinux_ip_output()
5736 * for similar problems. */
5737 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005738 struct sk_security_struct *sksec;
5739
Eric Dumazete446f9d2015-10-08 05:01:55 -07005740 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005741 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5742 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005743 /* At this point, if the returned skb peerlbl is SECSID_NULL
5744 * and the packet has been through at least one XFRM
5745 * transformation then we must be dealing with the "final"
5746 * form of labeled IPsec packet; since we've already applied
5747 * all of our access controls on this packet we can safely
5748 * pass the packet. */
5749 if (skb_sid == SECSID_NULL) {
5750 switch (family) {
5751 case PF_INET:
5752 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5753 return NF_ACCEPT;
5754 break;
5755 case PF_INET6:
5756 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5757 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005758 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005759 default:
5760 return NF_DROP_ERR(-ECONNREFUSED);
5761 }
5762 }
Paul Moore446b8022013-12-04 16:10:51 -05005763 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5764 return NF_DROP;
5765 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005766 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005767 /* Locally generated packet, fetch the security label from the
5768 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005769 struct sk_security_struct *sksec = sk->sk_security;
5770 peer_sid = sksec->sid;
5771 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005772 }
5773
Eric Paris50c205f2012-04-04 15:01:43 -04005774 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005775 ad.u.net = &net;
5776 ad.u.net->netif = ifindex;
5777 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005778 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005779 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005780
Paul Mooreeffad8d2008-01-29 08:49:27 -05005781 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005782 if (avc_has_perm(&selinux_state,
5783 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005784 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005785 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005786
5787 if (peerlbl_active) {
5788 u32 if_sid;
5789 u32 node_sid;
5790
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005791 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005792 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005793 if (avc_has_perm(&selinux_state,
5794 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005795 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005796 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005797
5798 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005799 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005800 if (avc_has_perm(&selinux_state,
5801 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005802 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005803 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005804 }
5805
5806 return NF_ACCEPT;
5807}
5808
Eric W. Biederman06198b32015-09-18 14:33:06 -05005809static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005810 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005811 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005812{
David S. Miller238e54c2015-04-03 20:32:56 -04005813 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814}
5815
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005816#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005817static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005818 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005819 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820{
David S. Miller238e54c2015-04-03 20:32:56 -04005821 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823#endif /* IPV6 */
5824
5825#endif /* CONFIG_NETFILTER */
5826
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5828{
Huaisheng Yedf4779b2020-01-13 23:03:31 +08005829 int err = 0;
5830 u32 perm;
5831 struct nlmsghdr *nlh;
5832 struct sk_security_struct *sksec = sk->sk_security;
5833
5834 if (skb->len < NLMSG_HDRLEN) {
5835 err = -EINVAL;
5836 goto out;
5837 }
5838 nlh = nlmsg_hdr(skb);
5839
5840 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
5841 if (err) {
5842 if (err == -EINVAL) {
5843 pr_warn_ratelimited("SELinux: unrecognized netlink"
5844 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5845 " pid=%d comm=%s\n",
5846 sk->sk_protocol, nlh->nlmsg_type,
5847 secclass_map[sksec->sclass - 1].name,
5848 task_pid_nr(current), current->comm);
5849 if (!enforcing_enabled(&selinux_state) ||
5850 security_get_allow_unknown(&selinux_state))
5851 err = 0;
5852 }
5853
5854 /* Ignore */
5855 if (err == -ENOENT)
5856 err = 0;
5857 goto out;
5858 }
5859
5860 err = sock_has_perm(sk, perm);
5861out:
5862 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863}
5864
Casey Schauflerecd5f822018-11-20 11:55:02 -08005865static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005866{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005868 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869}
5870
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005872 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005875 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005876 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877
Casey Schaufler7c653822018-09-21 17:19:45 -07005878 isec = selinux_ipc(ipc_perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879
Eric Paris50c205f2012-04-04 15:01:43 -04005880 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881 ad.u.ipc_id = ipc_perms->key;
5882
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005883 return avc_has_perm(&selinux_state,
5884 sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885}
5886
5887static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5888{
Huaisheng Yeb82f3f62020-01-10 17:58:56 +08005889 struct msg_security_struct *msec;
5890
5891 msec = selinux_msg_msg(msg);
5892 msec->sid = SECINITSID_UNLABELED;
5893
5894 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895}
5896
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897/* message queue security operations */
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005898static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005901 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005902 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903 int rc;
5904
Casey Schauflerecd5f822018-11-20 11:55:02 -08005905 isec = selinux_ipc(msq);
5906 ipc_init_security(isec, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907
Eric Paris50c205f2012-04-04 15:01:43 -04005908 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005909 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005911 rc = avc_has_perm(&selinux_state,
5912 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913 MSGQ__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08005914 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915}
5916
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005917static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005920 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005921 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922
Casey Schaufler7c653822018-09-21 17:19:45 -07005923 isec = selinux_ipc(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Eric Paris50c205f2012-04-04 15:01:43 -04005925 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005926 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005928 return avc_has_perm(&selinux_state,
5929 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930 MSGQ__ASSOCIATE, &ad);
5931}
5932
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005933static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934{
5935 int err;
5936 int perms;
5937
Eric Paris828dfe12008-04-17 13:17:49 -04005938 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939 case IPC_INFO:
5940 case MSG_INFO:
5941 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005942 return avc_has_perm(&selinux_state,
5943 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005944 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945 case IPC_STAT:
5946 case MSG_STAT:
Davidlohr Bueso23c8cec2018-04-10 16:35:30 -07005947 case MSG_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5949 break;
5950 case IPC_SET:
5951 perms = MSGQ__SETATTR;
5952 break;
5953 case IPC_RMID:
5954 perms = MSGQ__DESTROY;
5955 break;
5956 default:
5957 return 0;
5958 }
5959
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005960 err = ipc_has_perm(msq, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961 return err;
5962}
5963
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005964static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966 struct ipc_security_struct *isec;
5967 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005968 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005969 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 int rc;
5971
Casey Schaufler7c653822018-09-21 17:19:45 -07005972 isec = selinux_ipc(msq);
5973 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974
5975 /*
5976 * First time through, need to assign label to the message
5977 */
5978 if (msec->sid == SECINITSID_UNLABELED) {
5979 /*
5980 * Compute new sid based on current process and
5981 * message queue this message will be stored in
5982 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005983 rc = security_transition_sid(&selinux_state, sid, isec->sid,
5984 SECCLASS_MSG, NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985 if (rc)
5986 return rc;
5987 }
5988
Eric Paris50c205f2012-04-04 15:01:43 -04005989 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005990 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
5992 /* Can this process write to the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005993 rc = avc_has_perm(&selinux_state,
5994 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995 MSGQ__WRITE, &ad);
5996 if (!rc)
5997 /* Can this process send the message */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005998 rc = avc_has_perm(&selinux_state,
5999 sid, msec->sid, SECCLASS_MSG,
David Howells275bb412008-11-14 10:39:19 +11006000 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001 if (!rc)
6002 /* Can the message be put in the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006003 rc = avc_has_perm(&selinux_state,
6004 msec->sid, isec->sid, SECCLASS_MSGQ,
David Howells275bb412008-11-14 10:39:19 +11006005 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006
6007 return rc;
6008}
6009
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006010static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011 struct task_struct *target,
6012 long type, int mode)
6013{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014 struct ipc_security_struct *isec;
6015 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006016 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006017 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 int rc;
6019
Casey Schaufler7c653822018-09-21 17:19:45 -07006020 isec = selinux_ipc(msq);
6021 msec = selinux_msg_msg(msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006022
Eric Paris50c205f2012-04-04 15:01:43 -04006023 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05006024 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006026 rc = avc_has_perm(&selinux_state,
6027 sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028 SECCLASS_MSGQ, MSGQ__READ, &ad);
6029 if (!rc)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006030 rc = avc_has_perm(&selinux_state,
6031 sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032 SECCLASS_MSG, MSG__RECEIVE, &ad);
6033 return rc;
6034}
6035
6036/* Shared Memory security operations */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006037static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006040 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006041 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042 int rc;
6043
Casey Schauflerecd5f822018-11-20 11:55:02 -08006044 isec = selinux_ipc(shp);
6045 ipc_init_security(isec, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Eric Paris50c205f2012-04-04 15:01:43 -04006047 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006048 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006050 rc = avc_has_perm(&selinux_state,
6051 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052 SHM__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08006053 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054}
6055
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006056static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006059 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006060 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Casey Schaufler7c653822018-09-21 17:19:45 -07006062 isec = selinux_ipc(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Eric Paris50c205f2012-04-04 15:01:43 -04006064 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006065 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006067 return avc_has_perm(&selinux_state,
6068 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069 SHM__ASSOCIATE, &ad);
6070}
6071
6072/* Note, at this point, shp is locked down */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006073static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074{
6075 int perms;
6076 int err;
6077
Eric Paris828dfe12008-04-17 13:17:49 -04006078 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079 case IPC_INFO:
6080 case SHM_INFO:
6081 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006082 return avc_has_perm(&selinux_state,
6083 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006084 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085 case IPC_STAT:
6086 case SHM_STAT:
Davidlohr Buesoc21a6972018-04-10 16:35:23 -07006087 case SHM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088 perms = SHM__GETATTR | SHM__ASSOCIATE;
6089 break;
6090 case IPC_SET:
6091 perms = SHM__SETATTR;
6092 break;
6093 case SHM_LOCK:
6094 case SHM_UNLOCK:
6095 perms = SHM__LOCK;
6096 break;
6097 case IPC_RMID:
6098 perms = SHM__DESTROY;
6099 break;
6100 default:
6101 return 0;
6102 }
6103
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006104 err = ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105 return err;
6106}
6107
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006108static int selinux_shm_shmat(struct kern_ipc_perm *shp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109 char __user *shmaddr, int shmflg)
6110{
6111 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
6113 if (shmflg & SHM_RDONLY)
6114 perms = SHM__READ;
6115 else
6116 perms = SHM__READ | SHM__WRITE;
6117
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006118 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119}
6120
6121/* Semaphore security operations */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006122static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006125 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006126 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127 int rc;
6128
Casey Schauflerecd5f822018-11-20 11:55:02 -08006129 isec = selinux_ipc(sma);
6130 ipc_init_security(isec, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131
Eric Paris50c205f2012-04-04 15:01:43 -04006132 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006133 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006135 rc = avc_has_perm(&selinux_state,
6136 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137 SEM__CREATE, &ad);
Casey Schauflerecd5f822018-11-20 11:55:02 -08006138 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139}
6140
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006141static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006144 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006145 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146
Casey Schaufler7c653822018-09-21 17:19:45 -07006147 isec = selinux_ipc(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148
Eric Paris50c205f2012-04-04 15:01:43 -04006149 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006150 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006152 return avc_has_perm(&selinux_state,
6153 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006154 SEM__ASSOCIATE, &ad);
6155}
6156
6157/* Note, at this point, sma is locked down */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006158static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159{
6160 int err;
6161 u32 perms;
6162
Eric Paris828dfe12008-04-17 13:17:49 -04006163 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164 case IPC_INFO:
6165 case SEM_INFO:
6166 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006167 return avc_has_perm(&selinux_state,
6168 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006169 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006170 case GETPID:
6171 case GETNCNT:
6172 case GETZCNT:
6173 perms = SEM__GETATTR;
6174 break;
6175 case GETVAL:
6176 case GETALL:
6177 perms = SEM__READ;
6178 break;
6179 case SETVAL:
6180 case SETALL:
6181 perms = SEM__WRITE;
6182 break;
6183 case IPC_RMID:
6184 perms = SEM__DESTROY;
6185 break;
6186 case IPC_SET:
6187 perms = SEM__SETATTR;
6188 break;
6189 case IPC_STAT:
6190 case SEM_STAT:
Davidlohr Buesoa280d6d2018-04-10 16:35:26 -07006191 case SEM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192 perms = SEM__GETATTR | SEM__ASSOCIATE;
6193 break;
6194 default:
6195 return 0;
6196 }
6197
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006198 err = ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199 return err;
6200}
6201
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006202static int selinux_sem_semop(struct kern_ipc_perm *sma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203 struct sembuf *sops, unsigned nsops, int alter)
6204{
6205 u32 perms;
6206
6207 if (alter)
6208 perms = SEM__READ | SEM__WRITE;
6209 else
6210 perms = SEM__READ;
6211
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006212 return ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213}
6214
6215static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6216{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217 u32 av = 0;
6218
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219 av = 0;
6220 if (flag & S_IRUGO)
6221 av |= IPC__UNIX_READ;
6222 if (flag & S_IWUGO)
6223 av |= IPC__UNIX_WRITE;
6224
6225 if (av == 0)
6226 return 0;
6227
Stephen Smalley6af963f2005-05-01 08:58:39 -07006228 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229}
6230
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006231static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6232{
Casey Schaufler7c653822018-09-21 17:19:45 -07006233 struct ipc_security_struct *isec = selinux_ipc(ipcp);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006234 *secid = isec->sid;
6235}
6236
Eric Paris828dfe12008-04-17 13:17:49 -04006237static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238{
6239 if (inode)
6240 inode_doinit_with_dentry(inode, dentry);
6241}
6242
6243static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00006244 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245{
David Howells275bb412008-11-14 10:39:19 +11006246 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00006247 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248 int error;
Al Viro04ff9702007-03-12 16:17:58 +00006249 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
David Howells275bb412008-11-14 10:39:19 +11006251 rcu_read_lock();
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006252 __tsec = selinux_cred(__task_cred(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006254 if (current != p) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006255 error = avc_has_perm(&selinux_state,
6256 current_sid(), __tsec->sid,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006257 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6258 if (error)
6259 goto bad;
6260 }
6261
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11006263 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11006265 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11006267 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006268 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11006269 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006270 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11006271 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07006272 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11006273 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006274 else {
6275 error = -EINVAL;
6276 goto bad;
6277 }
David Howells275bb412008-11-14 10:39:19 +11006278 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279
6280 if (!sid)
6281 return 0;
6282
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006283 error = security_sid_to_context(&selinux_state, sid, value, &len);
Al Viro04ff9702007-03-12 16:17:58 +00006284 if (error)
6285 return error;
6286 return len;
David Howells275bb412008-11-14 10:39:19 +11006287
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006288bad:
David Howells275bb412008-11-14 10:39:19 +11006289 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006290 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291}
6292
Stephen Smalleyb21507e2017-01-09 10:07:31 -05006293static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294{
6295 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11006296 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006297 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298 int error;
6299 char *str = value;
6300
Linus Torvalds1da177e2005-04-16 15:20:36 -07006301 /*
6302 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006303 */
6304 if (!strcmp(name, "exec"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006305 error = avc_has_perm(&selinux_state,
6306 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006307 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006308 else if (!strcmp(name, "fscreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006309 error = avc_has_perm(&selinux_state,
6310 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006311 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006312 else if (!strcmp(name, "keycreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006313 error = avc_has_perm(&selinux_state,
6314 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006315 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07006316 else if (!strcmp(name, "sockcreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006317 error = avc_has_perm(&selinux_state,
6318 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006319 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320 else if (!strcmp(name, "current"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006321 error = avc_has_perm(&selinux_state,
6322 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006323 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006324 else
6325 error = -EINVAL;
6326 if (error)
6327 return error;
6328
6329 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05006330 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006331 if (str[size-1] == '\n') {
6332 str[size-1] = 0;
6333 size--;
6334 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006335 error = security_context_to_sid(&selinux_state, value, size,
6336 &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006337 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04006338 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04006339 struct audit_buffer *ab;
6340 size_t audit_size;
6341
6342 /* We strip a nul only if it is at the end, otherwise the
6343 * context contains a nul and we should audit that */
6344 if (str[size - 1] == '\0')
6345 audit_size = size - 1;
6346 else
6347 audit_size = size;
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04006348 ab = audit_log_start(audit_context(),
6349 GFP_ATOMIC,
6350 AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04006351 audit_log_format(ab, "op=fscreate invalid_context=");
6352 audit_log_n_untrustedstring(ab, value, audit_size);
6353 audit_log_end(ab);
6354
Stephen Smalley12b29f32008-05-07 13:03:20 -04006355 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006356 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006357 error = security_context_to_sid_force(
6358 &selinux_state,
6359 value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361 if (error)
6362 return error;
6363 }
6364
David Howellsd84f4f92008-11-14 10:39:23 +11006365 new = prepare_creds();
6366 if (!new)
6367 return -ENOMEM;
6368
Linus Torvalds1da177e2005-04-16 15:20:36 -07006369 /* Permission checking based on the specified context is
6370 performed during the actual operation (execve,
6371 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11006372 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373 checks and may_create for the file creation checks. The
6374 operation will then fail if the context is not permitted. */
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006375 tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11006376 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006377 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006378 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006379 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006380 } else if (!strcmp(name, "keycreate")) {
Ondrej Mosnacek464c2582019-06-12 10:12:26 +02006381 if (sid) {
6382 error = avc_has_perm(&selinux_state, mysid, sid,
6383 SECCLASS_KEY, KEY__CREATE, NULL);
6384 if (error)
6385 goto abort_change;
6386 }
Michael LeMay4eb582c2006-06-26 00:24:57 -07006387 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006388 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006389 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006390 } else if (!strcmp(name, "current")) {
6391 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006393 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006394
David Howellsd84f4f92008-11-14 10:39:23 +11006395 /* Only allow single threaded processes to change context */
6396 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006397 if (!current_is_single_threaded()) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006398 error = security_bounded_transition(&selinux_state,
6399 tsec->sid, sid);
David Howellsd84f4f92008-11-14 10:39:23 +11006400 if (error)
6401 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006403
6404 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006405 error = avc_has_perm(&selinux_state,
6406 tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006407 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006408 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006409 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006410
6411 /* Check for ptracing, and update the task SID if ok.
6412 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006413 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006414 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006415 error = avc_has_perm(&selinux_state,
6416 ptsid, sid, SECCLASS_PROCESS,
David Howellsd84f4f92008-11-14 10:39:23 +11006417 PROCESS__PTRACE, NULL);
6418 if (error)
6419 goto abort_change;
6420 }
6421
6422 tsec->sid = sid;
6423 } else {
6424 error = -EINVAL;
6425 goto abort_change;
6426 }
6427
6428 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006429 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006430
6431abort_change:
6432 abort_creds(new);
6433 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434}
6435
David Quigley746df9b2013-05-22 12:50:35 -04006436static int selinux_ismaclabel(const char *name)
6437{
6438 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6439}
6440
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006441static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6442{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006443 return security_sid_to_context(&selinux_state, secid,
6444 secdata, seclen);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006445}
6446
David Howells7bf570d2008-04-29 20:52:51 +01006447static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006448{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006449 return security_context_to_sid(&selinux_state, secdata, seclen,
6450 secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006451}
6452
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006453static void selinux_release_secctx(char *secdata, u32 seclen)
6454{
Paul Moore088999e2007-08-01 11:12:58 -04006455 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006456}
6457
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006458static void selinux_inode_invalidate_secctx(struct inode *inode)
6459{
Casey Schaufler80788c22018-09-21 17:19:11 -07006460 struct inode_security_struct *isec = selinux_inode(inode);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006461
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006462 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006463 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006464 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006465}
6466
David P. Quigley1ee65e32009-09-03 14:25:57 -04006467/*
6468 * called with inode->i_mutex locked
6469 */
6470static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6471{
Ondrej Mosnacek53e0c2a2018-12-21 21:18:53 +01006472 int rc = selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX,
6473 ctx, ctxlen, 0);
6474 /* Do not return error when suppressing label (SBLABEL_MNT not set). */
6475 return rc == -EOPNOTSUPP ? 0 : rc;
David P. Quigley1ee65e32009-09-03 14:25:57 -04006476}
6477
6478/*
6479 * called with inode->i_mutex locked
6480 */
6481static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6482{
6483 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6484}
6485
6486static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6487{
6488 int len = 0;
6489 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6490 ctx, true);
6491 if (len < 0)
6492 return len;
6493 *ctxlen = len;
6494 return 0;
6495}
Michael LeMayd7200242006-06-22 14:47:17 -07006496#ifdef CONFIG_KEYS
6497
David Howellsd84f4f92008-11-14 10:39:23 +11006498static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006499 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006500{
David Howellsd84f4f92008-11-14 10:39:23 +11006501 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006502 struct key_security_struct *ksec;
6503
6504 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6505 if (!ksec)
6506 return -ENOMEM;
6507
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006508 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11006509 if (tsec->keycreate_sid)
6510 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006511 else
David Howellsd84f4f92008-11-14 10:39:23 +11006512 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006513
David Howells275bb412008-11-14 10:39:19 +11006514 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006515 return 0;
6516}
6517
6518static void selinux_key_free(struct key *k)
6519{
6520 struct key_security_struct *ksec = k->security;
6521
6522 k->security = NULL;
6523 kfree(ksec);
6524}
6525
6526static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006527 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006528 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006529{
6530 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006531 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006532 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006533
6534 /* if no specific permissions are requested, we skip the
6535 permission check. No serious, additional covert channels
6536 appear to be created. */
6537 if (perm == 0)
6538 return 0;
6539
David Howellsd84f4f92008-11-14 10:39:23 +11006540 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006541
6542 key = key_ref_to_ptr(key_ref);
6543 ksec = key->security;
6544
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006545 return avc_has_perm(&selinux_state,
Linus Torvalds028db3e2019-07-10 18:43:43 -07006546 sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006547}
6548
David Howells70a5bb72008-04-29 01:01:26 -07006549static int selinux_key_getsecurity(struct key *key, char **_buffer)
6550{
6551 struct key_security_struct *ksec = key->security;
6552 char *context = NULL;
6553 unsigned len;
6554 int rc;
6555
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006556 rc = security_sid_to_context(&selinux_state, ksec->sid,
6557 &context, &len);
David Howells70a5bb72008-04-29 01:01:26 -07006558 if (!rc)
6559 rc = len;
6560 *_buffer = context;
6561 return rc;
6562}
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006563#endif
David Howells70a5bb72008-04-29 01:01:26 -07006564
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006565#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006566static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6567{
6568 struct common_audit_data ad;
6569 int err;
6570 u32 sid = 0;
6571 struct ib_security_struct *sec = ib_sec;
6572 struct lsm_ibpkey_audit ibpkey;
6573
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006574 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006575 if (err)
6576 return err;
6577
6578 ad.type = LSM_AUDIT_DATA_IBPKEY;
6579 ibpkey.subnet_prefix = subnet_prefix;
6580 ibpkey.pkey = pkey_val;
6581 ad.u.ibpkey = &ibpkey;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006582 return avc_has_perm(&selinux_state,
6583 sec->sid, sid,
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006584 SECCLASS_INFINIBAND_PKEY,
6585 INFINIBAND_PKEY__ACCESS, &ad);
6586}
6587
Daniel Jurgensab861df2017-05-19 15:48:58 +03006588static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6589 u8 port_num)
6590{
6591 struct common_audit_data ad;
6592 int err;
6593 u32 sid = 0;
6594 struct ib_security_struct *sec = ib_sec;
6595 struct lsm_ibendport_audit ibendport;
6596
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006597 err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
6598 &sid);
Daniel Jurgensab861df2017-05-19 15:48:58 +03006599
6600 if (err)
6601 return err;
6602
6603 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6604 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6605 ibendport.port = port_num;
6606 ad.u.ibendport = &ibendport;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006607 return avc_has_perm(&selinux_state,
6608 sec->sid, sid,
Daniel Jurgensab861df2017-05-19 15:48:58 +03006609 SECCLASS_INFINIBAND_ENDPORT,
6610 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6611}
6612
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006613static int selinux_ib_alloc_security(void **ib_sec)
6614{
6615 struct ib_security_struct *sec;
6616
6617 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6618 if (!sec)
6619 return -ENOMEM;
6620 sec->sid = current_sid();
6621
6622 *ib_sec = sec;
6623 return 0;
6624}
6625
6626static void selinux_ib_free_security(void *ib_sec)
6627{
6628 kfree(ib_sec);
6629}
Michael LeMayd7200242006-06-22 14:47:17 -07006630#endif
6631
Chenbo Fengec27c352017-10-18 13:00:25 -07006632#ifdef CONFIG_BPF_SYSCALL
6633static int selinux_bpf(int cmd, union bpf_attr *attr,
6634 unsigned int size)
6635{
6636 u32 sid = current_sid();
6637 int ret;
6638
6639 switch (cmd) {
6640 case BPF_MAP_CREATE:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006641 ret = avc_has_perm(&selinux_state,
6642 sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
Chenbo Fengec27c352017-10-18 13:00:25 -07006643 NULL);
6644 break;
6645 case BPF_PROG_LOAD:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006646 ret = avc_has_perm(&selinux_state,
6647 sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
Chenbo Fengec27c352017-10-18 13:00:25 -07006648 NULL);
6649 break;
6650 default:
6651 ret = 0;
6652 break;
6653 }
6654
6655 return ret;
6656}
6657
6658static u32 bpf_map_fmode_to_av(fmode_t fmode)
6659{
6660 u32 av = 0;
6661
6662 if (fmode & FMODE_READ)
6663 av |= BPF__MAP_READ;
6664 if (fmode & FMODE_WRITE)
6665 av |= BPF__MAP_WRITE;
6666 return av;
6667}
6668
Chenbo Fengf66e4482017-10-18 13:00:26 -07006669/* This function will check the file pass through unix socket or binder to see
6670 * if it is a bpf related object. And apply correspinding checks on the bpf
6671 * object based on the type. The bpf maps and programs, not like other files and
6672 * socket, are using a shared anonymous inode inside the kernel as their inode.
6673 * So checking that inode cannot identify if the process have privilege to
6674 * access the bpf object and that's why we have to add this additional check in
6675 * selinux_file_receive and selinux_binder_transfer_files.
6676 */
6677static int bpf_fd_pass(struct file *file, u32 sid)
6678{
6679 struct bpf_security_struct *bpfsec;
6680 struct bpf_prog *prog;
6681 struct bpf_map *map;
6682 int ret;
6683
6684 if (file->f_op == &bpf_map_fops) {
6685 map = file->private_data;
6686 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006687 ret = avc_has_perm(&selinux_state,
6688 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006689 bpf_map_fmode_to_av(file->f_mode), NULL);
6690 if (ret)
6691 return ret;
6692 } else if (file->f_op == &bpf_prog_fops) {
6693 prog = file->private_data;
6694 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006695 ret = avc_has_perm(&selinux_state,
6696 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006697 BPF__PROG_RUN, NULL);
6698 if (ret)
6699 return ret;
6700 }
6701 return 0;
6702}
6703
Chenbo Fengec27c352017-10-18 13:00:25 -07006704static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6705{
6706 u32 sid = current_sid();
6707 struct bpf_security_struct *bpfsec;
6708
6709 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006710 return avc_has_perm(&selinux_state,
6711 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006712 bpf_map_fmode_to_av(fmode), NULL);
6713}
6714
6715static int selinux_bpf_prog(struct bpf_prog *prog)
6716{
6717 u32 sid = current_sid();
6718 struct bpf_security_struct *bpfsec;
6719
6720 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006721 return avc_has_perm(&selinux_state,
6722 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006723 BPF__PROG_RUN, NULL);
6724}
6725
6726static int selinux_bpf_map_alloc(struct bpf_map *map)
6727{
6728 struct bpf_security_struct *bpfsec;
6729
6730 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6731 if (!bpfsec)
6732 return -ENOMEM;
6733
6734 bpfsec->sid = current_sid();
6735 map->security = bpfsec;
6736
6737 return 0;
6738}
6739
6740static void selinux_bpf_map_free(struct bpf_map *map)
6741{
6742 struct bpf_security_struct *bpfsec = map->security;
6743
6744 map->security = NULL;
6745 kfree(bpfsec);
6746}
6747
6748static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6749{
6750 struct bpf_security_struct *bpfsec;
6751
6752 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6753 if (!bpfsec)
6754 return -ENOMEM;
6755
6756 bpfsec->sid = current_sid();
6757 aux->security = bpfsec;
6758
6759 return 0;
6760}
6761
6762static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6763{
6764 struct bpf_security_struct *bpfsec = aux->security;
6765
6766 aux->security = NULL;
6767 kfree(bpfsec);
6768}
6769#endif
6770
Stephen Smalley59438b462019-11-27 12:04:36 -05006771static int selinux_lockdown(enum lockdown_reason what)
6772{
6773 struct common_audit_data ad;
6774 u32 sid = current_sid();
6775 int invalid_reason = (what <= LOCKDOWN_NONE) ||
6776 (what == LOCKDOWN_INTEGRITY_MAX) ||
6777 (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
6778
6779 if (WARN(invalid_reason, "Invalid lockdown reason")) {
6780 audit_log(audit_context(),
6781 GFP_ATOMIC, AUDIT_SELINUX_ERR,
6782 "lockdown_reason=invalid");
6783 return -EINVAL;
6784 }
6785
6786 ad.type = LSM_AUDIT_DATA_LOCKDOWN;
6787 ad.u.reason = what;
6788
6789 if (what <= LOCKDOWN_INTEGRITY_MAX)
6790 return avc_has_perm(&selinux_state,
6791 sid, sid, SECCLASS_LOCKDOWN,
6792 LOCKDOWN__INTEGRITY, &ad);
6793 else
6794 return avc_has_perm(&selinux_state,
6795 sid, sid, SECCLASS_LOCKDOWN,
6796 LOCKDOWN__CONFIDENTIALITY, &ad);
6797}
6798
Casey Schauflerbbd36622018-11-12 09:30:56 -08006799struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
6800 .lbs_cred = sizeof(struct task_security_struct),
Casey Schaufler33bf60c2018-11-12 12:02:49 -08006801 .lbs_file = sizeof(struct file_security_struct),
Casey Schauflerafb1cbe32018-09-21 17:19:29 -07006802 .lbs_inode = sizeof(struct inode_security_struct),
Casey Schauflerecd5f822018-11-20 11:55:02 -08006803 .lbs_ipc = sizeof(struct ipc_security_struct),
6804 .lbs_msg_msg = sizeof(struct msg_security_struct),
Casey Schauflerbbd36622018-11-12 09:30:56 -08006805};
6806
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04006807#ifdef CONFIG_PERF_EVENTS
6808static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
6809{
6810 u32 requested, sid = current_sid();
6811
6812 if (type == PERF_SECURITY_OPEN)
6813 requested = PERF_EVENT__OPEN;
6814 else if (type == PERF_SECURITY_CPU)
6815 requested = PERF_EVENT__CPU;
6816 else if (type == PERF_SECURITY_KERNEL)
6817 requested = PERF_EVENT__KERNEL;
6818 else if (type == PERF_SECURITY_TRACEPOINT)
6819 requested = PERF_EVENT__TRACEPOINT;
6820 else
6821 return -EINVAL;
6822
6823 return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
6824 requested, NULL);
6825}
6826
6827static int selinux_perf_event_alloc(struct perf_event *event)
6828{
6829 struct perf_event_security_struct *perfsec;
6830
6831 perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
6832 if (!perfsec)
6833 return -ENOMEM;
6834
6835 perfsec->sid = current_sid();
6836 event->security = perfsec;
6837
6838 return 0;
6839}
6840
6841static void selinux_perf_event_free(struct perf_event *event)
6842{
6843 struct perf_event_security_struct *perfsec = event->security;
6844
6845 event->security = NULL;
6846 kfree(perfsec);
6847}
6848
6849static int selinux_perf_event_read(struct perf_event *event)
6850{
6851 struct perf_event_security_struct *perfsec = event->security;
6852 u32 sid = current_sid();
6853
6854 return avc_has_perm(&selinux_state, sid, perfsec->sid,
6855 SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
6856}
6857
6858static int selinux_perf_event_write(struct perf_event *event)
6859{
6860 struct perf_event_security_struct *perfsec = event->security;
6861 u32 sid = current_sid();
6862
6863 return avc_has_perm(&selinux_state, sid, perfsec->sid,
6864 SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
6865}
6866#endif
6867
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01006868/*
6869 * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
6870 * 1. any hooks that don't belong to (2.) or (3.) below,
6871 * 2. hooks that both access structures allocated by other hooks, and allocate
6872 * structures that can be later accessed by other hooks (mostly "cloning"
6873 * hooks),
6874 * 3. hooks that only allocate structures that can be later accessed by other
6875 * hooks ("allocating" hooks).
6876 *
6877 * Please follow block comment delimiters in the list to keep this order.
6878 *
6879 * This ordering is needed for SELinux runtime disable to work at least somewhat
6880 * safely. Breaking the ordering rules above might lead to NULL pointer derefs
6881 * when disabling SELinux at runtime.
6882 */
James Morrisca97d932017-02-15 00:18:51 +11006883static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006884 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6885 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6886 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6887 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006888
Casey Schauflere20b0432015-05-02 15:11:36 -07006889 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6890 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6891 LSM_HOOK_INIT(capget, selinux_capget),
6892 LSM_HOOK_INIT(capset, selinux_capset),
6893 LSM_HOOK_INIT(capable, selinux_capable),
6894 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6895 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6896 LSM_HOOK_INIT(syslog, selinux_syslog),
6897 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006898
Casey Schauflere20b0432015-05-02 15:11:36 -07006899 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006900
Casey Schauflere20b0432015-05-02 15:11:36 -07006901 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6902 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6903 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006904
Casey Schauflere20b0432015-05-02 15:11:36 -07006905 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
Al Viro204cc0c2018-12-13 13:41:47 -05006906 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
Casey Schauflere20b0432015-05-02 15:11:36 -07006907 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6908 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6909 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6910 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6911 LSM_HOOK_INIT(sb_mount, selinux_mount),
6912 LSM_HOOK_INIT(sb_umount, selinux_umount),
6913 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6914 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915
Casey Schauflere20b0432015-05-02 15:11:36 -07006916 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006917 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006918
Casey Schauflere20b0432015-05-02 15:11:36 -07006919 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6920 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6921 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6922 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6923 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6924 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6925 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6926 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6927 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6928 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6929 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6930 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6931 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6932 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6933 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6934 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6935 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6936 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6937 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6938 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6939 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6940 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6941 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6942 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006943 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006944 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Aaron Goidelac5656d2019-08-12 11:20:00 -04006945 LSM_HOOK_INIT(path_notify, selinux_path_notify),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006946
Ondrej Mosnacekec882da2019-02-22 15:57:17 +01006947 LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
6948
Casey Schauflere20b0432015-05-02 15:11:36 -07006949 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6950 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
Casey Schauflere20b0432015-05-02 15:11:36 -07006951 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6952 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6953 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6954 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6955 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6956 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6957 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6958 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6959 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960
Casey Schauflere20b0432015-05-02 15:11:36 -07006961 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006962
Tetsuo Handaa79be232017-03-28 23:08:45 +09006963 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07006964 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6965 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
Matthew Garrett3ec30112018-01-08 13:36:19 -08006966 LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
Casey Schauflere20b0432015-05-02 15:11:36 -07006967 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6968 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6969 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04006970 LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006971 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006972 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6973 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6974 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6975 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6976 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6977 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6978 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05006979 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07006980 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6981 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6982 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6983 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6984 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07006985 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006986
Casey Schauflere20b0432015-05-02 15:11:36 -07006987 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6988 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006989
Casey Schauflere20b0432015-05-02 15:11:36 -07006990 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6991 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6992 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6993 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006994
Casey Schauflere20b0432015-05-02 15:11:36 -07006995 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6996 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6997 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006998
Casey Schauflere20b0432015-05-02 15:11:36 -07006999 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
7000 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
7001 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002
Casey Schauflere20b0432015-05-02 15:11:36 -07007003 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004
Casey Schauflere20b0432015-05-02 15:11:36 -07007005 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
7006 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007
Casey Schauflere20b0432015-05-02 15:11:36 -07007008 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
Casey Schauflere20b0432015-05-02 15:11:36 -07007009 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
7010 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05007011 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07007012 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
7013 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014
Casey Schauflere20b0432015-05-02 15:11:36 -07007015 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
7016 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07007017
Casey Schauflere20b0432015-05-02 15:11:36 -07007018 LSM_HOOK_INIT(socket_create, selinux_socket_create),
7019 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
David Herrmann0b811db2018-05-04 16:28:21 +02007020 LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
Casey Schauflere20b0432015-05-02 15:11:36 -07007021 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
7022 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
7023 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
7024 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
7025 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
7026 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
7027 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
7028 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
7029 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
7030 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
7031 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
7032 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
7033 LSM_HOOK_INIT(socket_getpeersec_stream,
7034 selinux_socket_getpeersec_stream),
7035 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
Casey Schauflere20b0432015-05-02 15:11:36 -07007036 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
7037 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
7038 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
7039 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
Richard Hainesd4529302018-02-13 20:57:18 +00007040 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
7041 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
7042 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
Casey Schauflere20b0432015-05-02 15:11:36 -07007043 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
7044 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
7045 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
7046 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
7047 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
7048 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
7049 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
Casey Schauflere20b0432015-05-02 15:11:36 -07007050 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
7051 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
7052 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
7053 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
7054 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007055#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03007056 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03007057 LSM_HOOK_INIT(ib_endport_manage_subnet,
7058 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03007059 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
7060#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08007061#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07007062 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
7063 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
Casey Schauflere20b0432015-05-02 15:11:36 -07007064 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
7065 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
7066 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
7067 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
7068 selinux_xfrm_state_pol_flow_match),
7069 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070#endif
Michael LeMayd7200242006-06-22 14:47:17 -07007071
7072#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07007073 LSM_HOOK_INIT(key_free, selinux_key_free),
7074 LSM_HOOK_INIT(key_permission, selinux_key_permission),
7075 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07007076#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007077
7078#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07007079 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
7080 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
7081 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02007082#endif
Chenbo Fengec27c352017-10-18 13:00:25 -07007083
7084#ifdef CONFIG_BPF_SYSCALL
7085 LSM_HOOK_INIT(bpf, selinux_bpf),
7086 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
7087 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
Chenbo Fengec27c352017-10-18 13:00:25 -07007088 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
7089 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
7090#endif
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007091
7092#ifdef CONFIG_PERF_EVENTS
7093 LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
Joel Fernandes (Google)da97e182019-10-14 13:03:08 -04007094 LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
7095 LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
7096 LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
7097#endif
Stephen Smalley59438b462019-11-27 12:04:36 -05007098
7099 LSM_HOOK_INIT(locked_down, selinux_lockdown),
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007100
7101 /*
7102 * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE
7103 */
7104 LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
7105 LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
7106 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
7107 LSM_HOOK_INIT(sb_add_mnt_opt, selinux_add_mnt_opt),
7108#ifdef CONFIG_SECURITY_NETWORK_XFRM
7109 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
7110#endif
7111
7112 /*
7113 * PUT "ALLOCATING" HOOKS HERE
7114 */
7115 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
7116 LSM_HOOK_INIT(msg_queue_alloc_security,
7117 selinux_msg_queue_alloc_security),
7118 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
7119 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
7120 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
7121 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
7122 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
7123 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
7124 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
7125 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
7126#ifdef CONFIG_SECURITY_INFINIBAND
7127 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
7128#endif
7129#ifdef CONFIG_SECURITY_NETWORK_XFRM
7130 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
7131 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
7132 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
7133 selinux_xfrm_state_alloc_acquire),
7134#endif
7135#ifdef CONFIG_KEYS
7136 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
7137#endif
7138#ifdef CONFIG_AUDIT
7139 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
7140#endif
7141#ifdef CONFIG_BPF_SYSCALL
7142 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
7143 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
7144#endif
7145#ifdef CONFIG_PERF_EVENTS
7146 LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
7147#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007148};
7149
7150static __init int selinux_init(void)
7151{
peter enderborgc103a912018-06-12 10:09:03 +02007152 pr_info("SELinux: Initializing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007153
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007154 memset(&selinux_state, 0, sizeof(selinux_state));
Paul Mooree5a5ca92018-03-01 17:38:30 -05007155 enforcing_set(&selinux_state, selinux_enforcing_boot);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007156 selinux_state.checkreqprot = selinux_checkreqprot_boot;
7157 selinux_ss_init(&selinux_state.ss);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05007158 selinux_avc_init(&selinux_state.avc);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007159
Linus Torvalds1da177e2005-04-16 15:20:36 -07007160 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11007161 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007162
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04007163 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
7164
Linus Torvalds1da177e2005-04-16 15:20:36 -07007165 avc_init();
7166
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007167 avtab_cache_init();
7168
7169 ebitmap_cache_init();
7170
7171 hashtab_cache_init();
7172
Casey Schauflerd69dece52017-01-18 17:09:05 -08007173 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007174
Paul Moore615e51f2014-06-26 14:33:56 -04007175 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
7176 panic("SELinux: Unable to register AVC netcache callback\n");
7177
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03007178 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
7179 panic("SELinux: Unable to register AVC LSM notifier callback\n");
7180
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007181 if (selinux_enforcing_boot)
peter enderborgc103a912018-06-12 10:09:03 +02007182 pr_debug("SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04007183 else
peter enderborgc103a912018-06-12 10:09:03 +02007184 pr_debug("SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07007185
David Howells442155c2018-11-01 23:07:24 +00007186 fs_validate_description(&selinux_fs_parameters);
7187
Linus Torvalds1da177e2005-04-16 15:20:36 -07007188 return 0;
7189}
7190
Al Viroe8c26252010-03-23 06:36:54 -04007191static void delayed_superblock_init(struct super_block *sb, void *unused)
7192{
Al Viro204cc0c2018-12-13 13:41:47 -05007193 selinux_set_mnt_opts(sb, NULL, 0, NULL);
Al Viroe8c26252010-03-23 06:36:54 -04007194}
7195
Linus Torvalds1da177e2005-04-16 15:20:36 -07007196void selinux_complete_init(void)
7197{
peter enderborgc103a912018-06-12 10:09:03 +02007198 pr_debug("SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199
7200 /* Set up any superblocks initialized prior to the policy load. */
peter enderborgc103a912018-06-12 10:09:03 +02007201 pr_debug("SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04007202 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007203}
7204
7205/* SELinux requires early initialization in order to label
7206 all processes and objects when they are created. */
Kees Cook3d6e5f62018-10-10 17:18:23 -07007207DEFINE_LSM(selinux) = {
Kees Cook07aed2f2018-10-10 17:18:24 -07007208 .name = "selinux",
Kees Cook14bd99c2018-09-19 19:57:06 -07007209 .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007210 .enabled = &selinux_enabled_boot,
Casey Schauflerbbd36622018-11-12 09:30:56 -08007211 .blobs = &selinux_blob_sizes,
Kees Cook3d6e5f62018-10-10 17:18:23 -07007212 .init = selinux_init,
7213};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007215#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216
Florian Westphal591bb272017-07-26 11:40:52 +02007217static const struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05007218 {
7219 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007220 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007221 .hooknum = NF_INET_POST_ROUTING,
7222 .priority = NF_IP_PRI_SELINUX_LAST,
7223 },
7224 {
7225 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007226 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007227 .hooknum = NF_INET_FORWARD,
7228 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04007229 },
7230 {
7231 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00007232 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04007233 .hooknum = NF_INET_LOCAL_OUT,
7234 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007235 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04007236#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05007237 {
7238 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007239 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007240 .hooknum = NF_INET_POST_ROUTING,
7241 .priority = NF_IP6_PRI_SELINUX_LAST,
7242 },
7243 {
7244 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007245 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007246 .hooknum = NF_INET_FORWARD,
7247 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007248 },
Huw Davies2917f572016-06-27 15:06:15 -04007249 {
7250 .hook = selinux_ipv6_output,
7251 .pf = NFPROTO_IPV6,
7252 .hooknum = NF_INET_LOCAL_OUT,
7253 .priority = NF_IP6_PRI_SELINUX_FIRST,
7254 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02007256};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Florian Westphal8e71bf72017-04-21 11:49:09 +02007258static int __net_init selinux_nf_register(struct net *net)
7259{
7260 return nf_register_net_hooks(net, selinux_nf_ops,
7261 ARRAY_SIZE(selinux_nf_ops));
7262}
7263
7264static void __net_exit selinux_nf_unregister(struct net *net)
7265{
7266 nf_unregister_net_hooks(net, selinux_nf_ops,
7267 ARRAY_SIZE(selinux_nf_ops));
7268}
7269
7270static struct pernet_operations selinux_net_ops = {
7271 .init = selinux_nf_register,
7272 .exit = selinux_nf_unregister,
7273};
7274
Linus Torvalds1da177e2005-04-16 15:20:36 -07007275static int __init selinux_nf_ip_init(void)
7276{
Jiri Pirko25db6be2014-09-03 17:42:13 +02007277 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007278
Stephen Smalley6c5a6822019-12-17 09:15:10 -05007279 if (!selinux_enabled_boot)
Jiri Pirko25db6be2014-09-03 17:42:13 +02007280 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05007281
peter enderborgc103a912018-06-12 10:09:03 +02007282 pr_debug("SELinux: Registering netfilter hooks\n");
Eric Parisfadcdb42007-02-22 18:11:31 -05007283
Florian Westphal8e71bf72017-04-21 11:49:09 +02007284 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07007285 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02007286 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007287
Jiri Pirko25db6be2014-09-03 17:42:13 +02007288 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007289}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290__initcall(selinux_nf_ip_init);
7291
7292#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7293static void selinux_nf_ip_exit(void)
7294{
peter enderborgc103a912018-06-12 10:09:03 +02007295 pr_debug("SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007296
Florian Westphal8e71bf72017-04-21 11:49:09 +02007297 unregister_pernet_subsys(&selinux_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007298}
7299#endif
7300
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007301#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302
7303#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7304#define selinux_nf_ip_exit()
7305#endif
7306
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007307#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007308
7309#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007310int selinux_disable(struct selinux_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007311{
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007312 if (selinux_initialized(state)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007313 /* Not permitted after initial policy load. */
7314 return -EINVAL;
7315 }
7316
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007317 if (selinux_disabled(state)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007318 /* Only do this once. */
7319 return -EINVAL;
7320 }
7321
Ondrej Mosnacek65cddd52020-01-07 14:31:53 +01007322 selinux_mark_disabled(state);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007323
peter enderborgc103a912018-06-12 10:09:03 +02007324 pr_info("SELinux: Disabled at runtime.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007325
Ondrej Mosnacekcfff75d2020-01-08 15:09:58 +01007326 /*
7327 * Unregister netfilter hooks.
7328 * Must be done before security_delete_hooks() to avoid breaking
7329 * runtime disable.
7330 */
7331 selinux_nf_ip_exit();
7332
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07007333 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007334
Eric Parisaf8ff042009-09-20 21:23:01 -04007335 /* Try to destroy the avc node cache */
7336 avc_disable();
7337
Linus Torvalds1da177e2005-04-16 15:20:36 -07007338 /* Unregister selinuxfs. */
7339 exit_sel_fs();
7340
7341 return 0;
7342}
7343#endif