blob: 26ec7d67e15dac915e18483dd819bd8069d21af3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
Stephen Smalley7efbb602017-08-17 13:32:36 -04006 * Authors: Stephen Smalley, <sds@tycho.nsa.gov>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Daniel Jurgens3a976fa2017-05-19 15:48:56 +030020 * Copyright (C) 2016 Mellanox Technologies
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040024 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050028#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070030#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010032#include <linux/sched/signal.h>
Ingo Molnar29930022017-02-08 18:51:36 +010033#include <linux/sched/task.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070034#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/xattr.h>
36#include <linux/capability.h>
37#include <linux/unistd.h>
38#include <linux/mm.h>
39#include <linux/mman.h>
40#include <linux/slab.h>
41#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050042#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/spinlock.h>
45#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050046#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040048#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/namei.h>
50#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/netfilter_ipv4.h>
52#include <linux/netfilter_ipv6.h>
53#include <linux/tty.h>
54#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070055#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050057#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050058#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050059#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040060#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070062#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#include <linux/bitops.h>
64#include <linux/interrupt.h>
65#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000066#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include <linux/tcp.h>
68#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080069#include <linux/dccp.h>
Richard Hainesd4529302018-02-13 20:57:18 +000070#include <linux/sctp.h>
71#include <net/sctp/structs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#include <linux/quota.h>
73#include <linux/un.h> /* for Unix socket types */
74#include <net/af_unix.h> /* for Unix socket types */
75#include <linux/parser.h>
76#include <linux/nfs_mount.h>
77#include <net/ipv6.h>
78#include <linux/hugetlb.h>
79#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070081#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070082#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070083#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070084#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080085#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070086#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040087#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000088#include <linux/msg.h>
89#include <linux/shm.h>
Chenbo Fengec27c352017-10-18 13:00:25 -070090#include <linux/bpf.h>
David Howellse262e32d2018-11-01 23:07:23 +000091#include <uapi/linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93#include "avc.h"
94#include "objsec.h"
95#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050096#include "netnode.h"
Paul Moore3e1121722008-04-10 10:48:14 -040097#include "netport.h"
Daniel Jurgens409dcf32017-05-19 15:48:59 +030098#include "ibpkey.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080099#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -0500100#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +0200101#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +1000102#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500104struct selinux_state selinux_state;
105
Paul Moored621d352008-01-29 08:43:36 -0500106/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000107static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500110static int selinux_enforcing_boot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
112static int __init enforcing_setup(char *str)
113{
Eric Parisf5269712008-05-14 11:27:45 -0400114 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900115 if (!kstrtoul(str, 0, &enforcing))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500116 selinux_enforcing_boot = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 return 1;
118}
119__setup("enforcing=", enforcing_setup);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500120#else
121#define selinux_enforcing_boot 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122#endif
123
124#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
125int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
126
127static int __init selinux_enabled_setup(char *str)
128{
Eric Parisf5269712008-05-14 11:27:45 -0400129 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900130 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400131 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 return 1;
133}
134__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400135#else
136int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#endif
138
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500139static unsigned int selinux_checkreqprot_boot =
140 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
141
142static int __init checkreqprot_setup(char *str)
143{
144 unsigned long checkreqprot;
145
146 if (!kstrtoul(str, 0, &checkreqprot))
147 selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
148 return 1;
149}
150__setup("checkreqprot=", checkreqprot_setup);
151
Christoph Lametere18b8902006-12-06 20:33:20 -0800152static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400153static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800154
Paul Moored621d352008-01-29 08:43:36 -0500155/**
156 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
157 *
158 * Description:
159 * This function checks the SECMARK reference counter to see if any SECMARK
160 * targets are currently configured, if the reference counter is greater than
161 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400162 * enabled, false (0) if SECMARK is disabled. If the always_check_network
163 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500164 *
165 */
166static int selinux_secmark_enabled(void)
167{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500168 return (selinux_policycap_alwaysnetwork() ||
169 atomic_read(&selinux_secmark_refcount));
Chris PeBenito2be4d742013-05-03 09:05:39 -0400170}
171
172/**
173 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
174 *
175 * Description:
176 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
177 * (1) if any are enabled or false (0) if neither are enabled. If the
178 * always_check_network policy capability is enabled, peer labeling
179 * is always considered enabled.
180 *
181 */
182static int selinux_peerlbl_enabled(void)
183{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500184 return (selinux_policycap_alwaysnetwork() ||
185 netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500186}
187
Paul Moore615e51f2014-06-26 14:33:56 -0400188static int selinux_netcache_avc_callback(u32 event)
189{
190 if (event == AVC_CALLBACK_RESET) {
191 sel_netif_flush();
192 sel_netnode_flush();
193 sel_netport_flush();
194 synchronize_net();
195 }
196 return 0;
197}
198
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300199static int selinux_lsm_notifier_avc_callback(u32 event)
200{
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300201 if (event == AVC_CALLBACK_RESET) {
202 sel_ib_pkey_flush();
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300203 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300204 }
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300205
206 return 0;
207}
208
David Howellsd84f4f92008-11-14 10:39:23 +1100209/*
210 * initialise the security for the init task
211 */
212static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213{
David Howells3b11a1d2008-11-14 10:39:26 +1100214 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 struct task_security_struct *tsec;
216
James Morris89d155e2005-10-30 14:59:21 -0800217 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100219 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
David Howellsd84f4f92008-11-14 10:39:23 +1100221 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100222 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
David Howells275bb412008-11-14 10:39:19 +1100225/*
David Howells88e67f32008-11-14 10:39:21 +1100226 * get the security ID of a set of credentials
227 */
228static inline u32 cred_sid(const struct cred *cred)
229{
230 const struct task_security_struct *tsec;
231
232 tsec = cred->security;
233 return tsec->sid;
234}
235
236/*
David Howells3b11a1d2008-11-14 10:39:26 +1100237 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100238 */
239static inline u32 task_sid(const struct task_struct *task)
240{
David Howells275bb412008-11-14 10:39:19 +1100241 u32 sid;
242
243 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100244 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100245 rcu_read_unlock();
246 return sid;
247}
248
David Howells88e67f32008-11-14 10:39:21 +1100249/* Allocate and free functions for each kind of security blob. */
250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251static int inode_alloc_security(struct inode *inode)
252{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100254 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Josef Bacika02fe132008-04-04 09:35:05 +1100256 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 if (!isec)
258 return -ENOMEM;
259
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +0100260 spin_lock_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 isec->inode = inode;
263 isec->sid = SECINITSID_UNLABELED;
264 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100265 isec->task_sid = sid;
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100266 isec->initialized = LABEL_INVALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 inode->i_security = isec;
268
269 return 0;
270}
271
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500272static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
273
274/*
275 * Try reloading inode security labels that have been marked as invalid. The
276 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100277 * allowed; when set to false, returns -ECHILD when the label is
Al Viroe9193282018-04-24 21:31:02 -0400278 * invalid. The @dentry parameter should be set to a dentry of the inode.
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500279 */
280static int __inode_security_revalidate(struct inode *inode,
Al Viroe9193282018-04-24 21:31:02 -0400281 struct dentry *dentry,
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500282 bool may_sleep)
283{
284 struct inode_security_struct *isec = inode->i_security;
285
286 might_sleep_if(may_sleep);
287
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500288 if (selinux_state.initialized &&
289 isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500290 if (!may_sleep)
291 return -ECHILD;
292
293 /*
294 * Try reloading the inode security label. This will fail if
295 * @opt_dentry is NULL and no dentry for this inode can be
296 * found; in that case, continue using the old label.
297 */
Al Viroe9193282018-04-24 21:31:02 -0400298 inode_doinit_with_dentry(inode, dentry);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500299 }
300 return 0;
301}
302
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500303static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
304{
305 return inode->i_security;
306}
307
308static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
309{
310 int error;
311
312 error = __inode_security_revalidate(inode, NULL, !rcu);
313 if (error)
314 return ERR_PTR(error);
315 return inode->i_security;
316}
317
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500318/*
319 * Get the security label of an inode.
320 */
321static struct inode_security_struct *inode_security(struct inode *inode)
322{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500323 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500324 return inode->i_security;
325}
326
Paul Moore2c971652016-04-19 16:36:28 -0400327static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
328{
329 struct inode *inode = d_backing_inode(dentry);
330
331 return inode->i_security;
332}
333
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500334/*
335 * Get the security label of a dentry's backing inode.
336 */
337static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
338{
339 struct inode *inode = d_backing_inode(dentry);
340
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500341 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500342 return inode->i_security;
343}
344
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500345static void inode_free_rcu(struct rcu_head *head)
346{
347 struct inode_security_struct *isec;
348
349 isec = container_of(head, struct inode_security_struct, rcu);
350 kmem_cache_free(sel_inode_cache, isec);
351}
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353static void inode_free_security(struct inode *inode)
354{
355 struct inode_security_struct *isec = inode->i_security;
356 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
357
Waiman Long9629d042015-07-10 17:19:56 -0400358 /*
359 * As not all inode security structures are in a list, we check for
360 * empty list outside of the lock to make sure that we won't waste
361 * time taking a lock doing nothing.
362 *
363 * The list_del_init() function can be safely called more than once.
364 * It should not be possible for this function to be called with
365 * concurrent list_add(), but for better safety against future changes
366 * in the code, we use list_empty_careful() here.
367 */
368 if (!list_empty_careful(&isec->list)) {
369 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400371 spin_unlock(&sbsec->isec_lock);
372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500374 /*
375 * The inode may still be referenced in a path walk and
376 * a call to selinux_inode_permission() can be made
377 * after inode_free_security() is called. Ideally, the VFS
378 * wouldn't do this, but fixing that is a much harder
379 * job. For now, simply free the i_security via RCU, and
380 * leave the current inode->i_security pointer intact.
381 * The inode will be freed after the RCU grace period too.
382 */
383 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
386static int file_alloc_security(struct file *file)
387{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100389 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Sangwoo63205652015-10-21 17:44:30 -0400391 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 if (!fsec)
393 return -ENOMEM;
394
David Howells275bb412008-11-14 10:39:19 +1100395 fsec->sid = sid;
396 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 file->f_security = fsec;
398
399 return 0;
400}
401
402static void file_free_security(struct file *file)
403{
404 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400406 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
409static int superblock_alloc_security(struct super_block *sb)
410{
411 struct superblock_security_struct *sbsec;
412
James Morris89d155e2005-10-30 14:59:21 -0800413 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 if (!sbsec)
415 return -ENOMEM;
416
Eric Parisbc7e9822006-09-25 23:32:02 -0700417 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 INIT_LIST_HEAD(&sbsec->isec_head);
419 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 sbsec->sb = sb;
421 sbsec->sid = SECINITSID_UNLABELED;
422 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700423 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 sb->s_security = sbsec;
425
426 return 0;
427}
428
429static void superblock_free_security(struct super_block *sb)
430{
431 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 sb->s_security = NULL;
433 kfree(sbsec);
434}
435
Al Virobd323652018-12-13 15:04:59 -0500436struct selinux_mnt_opts {
437 const char *fscontext, *context, *rootcontext, *defcontext;
438};
439
Al Viro204cc0c2018-12-13 13:41:47 -0500440static void selinux_free_mnt_opts(void *mnt_opts)
441{
Al Virobd323652018-12-13 15:04:59 -0500442 struct selinux_mnt_opts *opts = mnt_opts;
443 kfree(opts->fscontext);
444 kfree(opts->context);
445 kfree(opts->rootcontext);
446 kfree(opts->defcontext);
Al Viro204cc0c2018-12-13 13:41:47 -0500447 kfree(opts);
448}
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450static inline int inode_doinit(struct inode *inode)
451{
452 return inode_doinit_with_dentry(inode, NULL);
453}
454
455enum {
Eric Paris31e87932007-09-19 17:19:12 -0400456 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 Opt_context = 1,
458 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500459 Opt_defcontext = 3,
460 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500461 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400462 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463};
464
Eric Parisd355987f2012-08-24 15:58:53 -0400465#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
466
Steven Whitehousea447c092008-10-13 10:46:57 +0100467static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400468 {Opt_context, CONTEXT_STR "%s"},
469 {Opt_fscontext, FSCONTEXT_STR "%s"},
470 {Opt_defcontext, DEFCONTEXT_STR "%s"},
471 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500472 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400473 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474};
475
476#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
477
Eric Parisc312feb2006-07-10 04:43:53 -0700478static int may_context_mount_sb_relabel(u32 sid,
479 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100480 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700481{
David Howells275bb412008-11-14 10:39:19 +1100482 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700483 int rc;
484
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500485 rc = avc_has_perm(&selinux_state,
486 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700487 FILESYSTEM__RELABELFROM, NULL);
488 if (rc)
489 return rc;
490
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500491 rc = avc_has_perm(&selinux_state,
492 tsec->sid, sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700493 FILESYSTEM__RELABELTO, NULL);
494 return rc;
495}
496
Eric Paris08089252006-07-10 04:43:55 -0700497static int may_context_mount_inode_relabel(u32 sid,
498 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100499 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700500{
David Howells275bb412008-11-14 10:39:19 +1100501 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700502 int rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500503 rc = avc_has_perm(&selinux_state,
504 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700505 FILESYSTEM__RELABELFROM, NULL);
506 if (rc)
507 return rc;
508
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500509 rc = avc_has_perm(&selinux_state,
510 sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700511 FILESYSTEM__ASSOCIATE, NULL);
512 return rc;
513}
514
Eric Parisb43e7252012-10-10 14:27:35 -0400515static int selinux_is_sblabel_mnt(struct super_block *sb)
516{
517 struct superblock_security_struct *sbsec = sb->s_security;
518
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500519 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
520 sbsec->behavior == SECURITY_FS_USE_TRANS ||
521 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400522 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500523 /* Special handling. Genfs but also in-core setxattr handler */
524 !strcmp(sb->s_type->name, "sysfs") ||
525 !strcmp(sb->s_type->name, "pstore") ||
526 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500527 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500528 !strcmp(sb->s_type->name, "rootfs") ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500529 (selinux_policycap_cgroupseclabel() &&
Stephen Smalley2651225b2017-02-28 10:35:56 -0500530 (!strcmp(sb->s_type->name, "cgroup") ||
531 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400532}
533
Eric Parisc9180a52007-11-30 13:00:35 -0500534static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 struct superblock_security_struct *sbsec = sb->s_security;
537 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000538 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 int rc = 0;
540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
542 /* Make sure that the xattr handler exists and that no
543 error other than -ENODATA is returned by getxattr on
544 the root directory. -ENODATA is ok, as this may be
545 the first boot of the SELinux kernel before we have
546 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200547 if (!(root_inode->i_opflags & IOP_XATTR)) {
peter enderborgc103a912018-06-12 10:09:03 +0200548 pr_warn("SELinux: (dev %s, type %s) has no "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800549 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 rc = -EOPNOTSUPP;
551 goto out;
552 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200553
554 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 if (rc < 0 && rc != -ENODATA) {
556 if (rc == -EOPNOTSUPP)
peter enderborgc103a912018-06-12 10:09:03 +0200557 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800558 "%s) has no security xattr handler\n",
559 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 else
peter enderborgc103a912018-06-12 10:09:03 +0200561 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800562 "%s) getxattr errno %d\n", sb->s_id,
563 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 goto out;
565 }
566 }
567
Eric Pariseadcabc2012-08-24 15:59:14 -0400568 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400569
570 /*
571 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
572 * leave the flag untouched because sb_clone_mnt_opts might be handing
573 * us a superblock that needs the flag to be cleared.
574 */
Eric Parisb43e7252012-10-10 14:27:35 -0400575 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400576 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400577 else
578 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500581 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
583 /* Initialize any other inodes associated with the superblock, e.g.
584 inodes created prior to initial policy load or inodes created
585 during get_sb by a pseudo filesystem that directly
586 populates itself. */
587 spin_lock(&sbsec->isec_lock);
Al Viro8d641242018-12-10 15:34:12 -0500588 while (!list_empty(&sbsec->isec_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 struct inode_security_struct *isec =
Al Viro8d641242018-12-10 15:34:12 -0500590 list_first_entry(&sbsec->isec_head,
Eric Parisc9180a52007-11-30 13:00:35 -0500591 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400593 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 spin_unlock(&sbsec->isec_lock);
595 inode = igrab(inode);
596 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500597 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 inode_doinit(inode);
599 iput(inode);
600 }
601 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 }
603 spin_unlock(&sbsec->isec_lock);
604out:
Eric Parisc9180a52007-11-30 13:00:35 -0500605 return rc;
606}
607
Eric Parisc9180a52007-11-30 13:00:35 -0500608static int bad_option(struct superblock_security_struct *sbsec, char flag,
609 u32 old_sid, u32 new_sid)
610{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500611 char mnt_flags = sbsec->flags & SE_MNTMASK;
612
Eric Parisc9180a52007-11-30 13:00:35 -0500613 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500614 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500615 if (!(sbsec->flags & flag) ||
616 (old_sid != new_sid))
617 return 1;
618
619 /* check if we were passed the same options twice,
620 * aka someone passed context=a,context=b
621 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500622 if (!(sbsec->flags & SE_SBINITIALIZED))
623 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500624 return 1;
625 return 0;
626}
Eric Parise0007522008-03-05 10:31:54 -0500627
Al Virobd323652018-12-13 15:04:59 -0500628static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
629{
630 int rc = security_context_str_to_sid(&selinux_state, s,
631 sid, GFP_KERNEL);
632 if (rc)
633 pr_warn("SELinux: security_context_str_to_sid"
634 "(%s) failed for (dev %s, type %s) errno=%d\n",
635 s, sb->s_id, sb->s_type->name, rc);
636 return rc;
637}
638
Eric Parisc9180a52007-11-30 13:00:35 -0500639/*
640 * Allow filesystems with binary mount data to explicitly set mount point
641 * labeling information.
642 */
Eric Parise0007522008-03-05 10:31:54 -0500643static int selinux_set_mnt_opts(struct super_block *sb,
Al Viro204cc0c2018-12-13 13:41:47 -0500644 void *mnt_opts,
David Quigley649f6e72013-05-22 12:50:36 -0400645 unsigned long kern_flags,
646 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500647{
David Howells275bb412008-11-14 10:39:19 +1100648 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500649 struct superblock_security_struct *sbsec = sb->s_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500650 struct dentry *root = sbsec->sb->s_root;
Al Virobd323652018-12-13 15:04:59 -0500651 struct selinux_mnt_opts *opts = mnt_opts;
Paul Moore2c971652016-04-19 16:36:28 -0400652 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500653 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
654 u32 defcontext_sid = 0;
Al Virobd323652018-12-13 15:04:59 -0500655 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500656
657 mutex_lock(&sbsec->lock);
658
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500659 if (!selinux_state.initialized) {
Al Virobd323652018-12-13 15:04:59 -0500660 if (!opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500661 /* Defer initialization until selinux_complete_init,
662 after the initial policy is loaded and the security
663 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500664 goto out;
665 }
666 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200667 pr_warn("SELinux: Unable to set superblock options "
Eric Paris744ba352008-04-17 11:52:44 -0400668 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500669 goto out;
670 }
David Quigley649f6e72013-05-22 12:50:36 -0400671 if (kern_flags && !set_kern_flags) {
672 /* Specifying internal flags without providing a place to
673 * place the results is not allowed */
674 rc = -EINVAL;
675 goto out;
676 }
Eric Parisc9180a52007-11-30 13:00:35 -0500677
678 /*
Eric Parise0007522008-03-05 10:31:54 -0500679 * Binary mount data FS will come through this function twice. Once
680 * from an explicit call and once from the generic calls from the vfs.
681 * Since the generic VFS calls will not contain any security mount data
682 * we need to skip the double mount verification.
683 *
684 * This does open a hole in which we will not notice if the first
685 * mount using this sb set explict options and a second mount using
686 * this sb does not set any security options. (The first options
687 * will be used for both mounts)
688 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500689 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Al Virobd323652018-12-13 15:04:59 -0500690 && !opts)
Eric Parisf5269712008-05-14 11:27:45 -0400691 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500692
Paul Moore2c971652016-04-19 16:36:28 -0400693 root_isec = backing_inode_security_novalidate(root);
694
Eric Parise0007522008-03-05 10:31:54 -0500695 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500696 * parse the mount options, check if they are valid sids.
697 * also check if someone is trying to mount the same sb more
698 * than once with different security options.
699 */
Al Virobd323652018-12-13 15:04:59 -0500700 if (opts) {
701 if (opts->fscontext) {
702 rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
703 if (rc)
704 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500705 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
706 fscontext_sid))
707 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500708 sbsec->flags |= FSCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500709 }
710 if (opts->context) {
711 rc = parse_sid(sb, opts->context, &context_sid);
712 if (rc)
713 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500714 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
715 context_sid))
716 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500717 sbsec->flags |= CONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500718 }
719 if (opts->rootcontext) {
720 rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
721 if (rc)
722 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500723 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
724 rootcontext_sid))
725 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500726 sbsec->flags |= ROOTCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500727 }
728 if (opts->defcontext) {
729 rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
730 if (rc)
731 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500732 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
733 defcontext_sid))
734 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500735 sbsec->flags |= DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500736 }
737 }
738
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500739 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500740 /* previously mounted with options, but not on this attempt? */
Al Virobd323652018-12-13 15:04:59 -0500741 if ((sbsec->flags & SE_MNTMASK) && !opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500742 goto out_double_mount;
743 rc = 0;
744 goto out;
745 }
746
James Morris089be432008-07-15 18:32:49 +1000747 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400748 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
749
Stephen Smalley8e014722015-06-04 16:22:17 -0400750 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700751 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley8e014722015-06-04 16:22:17 -0400752 !strcmp(sb->s_type->name, "sysfs") ||
Antonio Murdaca901ef842017-02-09 17:02:42 +0100753 !strcmp(sb->s_type->name, "pstore") ||
754 !strcmp(sb->s_type->name, "cgroup") ||
755 !strcmp(sb->s_type->name, "cgroup2"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400756 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500757
David Quigleyeb9ae682013-05-22 12:50:37 -0400758 if (!sbsec->behavior) {
759 /*
760 * Determine the labeling behavior to use for this
761 * filesystem type.
762 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500763 rc = security_fs_use(&selinux_state, sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400764 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +0200765 pr_warn("%s: security_fs_use(%s) returned %d\n",
David Quigleyeb9ae682013-05-22 12:50:37 -0400766 __func__, sb->s_type->name, rc);
767 goto out;
768 }
Eric Parisc9180a52007-11-30 13:00:35 -0500769 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500770
771 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500772 * If this is a user namespace mount and the filesystem type is not
773 * explicitly whitelisted, then no contexts are allowed on the command
774 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500775 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500776 if (sb->s_user_ns != &init_user_ns &&
777 strcmp(sb->s_type->name, "tmpfs") &&
778 strcmp(sb->s_type->name, "ramfs") &&
779 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500780 if (context_sid || fscontext_sid || rootcontext_sid ||
781 defcontext_sid) {
782 rc = -EACCES;
783 goto out;
784 }
785 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
786 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500787 rc = security_transition_sid(&selinux_state,
788 current_sid(),
789 current_sid(),
Seth Forsheeaad82892016-04-26 14:36:20 -0500790 SECCLASS_FILE, NULL,
791 &sbsec->mntpoint_sid);
792 if (rc)
793 goto out;
794 }
795 goto out_set_opts;
796 }
797
Eric Parisc9180a52007-11-30 13:00:35 -0500798 /* sets the context of the superblock for the fs being mounted. */
799 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100800 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500801 if (rc)
802 goto out;
803
804 sbsec->sid = fscontext_sid;
805 }
806
807 /*
808 * Switch to using mount point labeling behavior.
809 * sets the label used on all file below the mountpoint, and will set
810 * the superblock context if not already set.
811 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400812 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
813 sbsec->behavior = SECURITY_FS_USE_NATIVE;
814 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
815 }
816
Eric Parisc9180a52007-11-30 13:00:35 -0500817 if (context_sid) {
818 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100819 rc = may_context_mount_sb_relabel(context_sid, sbsec,
820 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500821 if (rc)
822 goto out;
823 sbsec->sid = context_sid;
824 } else {
David Howells275bb412008-11-14 10:39:19 +1100825 rc = may_context_mount_inode_relabel(context_sid, sbsec,
826 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500827 if (rc)
828 goto out;
829 }
830 if (!rootcontext_sid)
831 rootcontext_sid = context_sid;
832
833 sbsec->mntpoint_sid = context_sid;
834 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
835 }
836
837 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100838 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
839 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500840 if (rc)
841 goto out;
842
843 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500844 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500845 }
846
847 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400848 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
849 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500850 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200851 pr_warn("SELinux: defcontext option is "
Eric Parisc9180a52007-11-30 13:00:35 -0500852 "invalid for this filesystem type\n");
853 goto out;
854 }
855
856 if (defcontext_sid != sbsec->def_sid) {
857 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100858 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500859 if (rc)
860 goto out;
861 }
862
863 sbsec->def_sid = defcontext_sid;
864 }
865
Seth Forsheeaad82892016-04-26 14:36:20 -0500866out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500867 rc = sb_finish_set_opts(sb);
868out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700869 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500871out_double_mount:
872 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200873 pr_warn("SELinux: mount invalid. Same superblock, different "
Al Virobd323652018-12-13 15:04:59 -0500874 "security settings for (dev %s, type %s)\n", sb->s_id,
875 sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500876 goto out;
877}
878
Jeff Layton094f7b62013-04-01 08:14:24 -0400879static int selinux_cmp_sb_context(const struct super_block *oldsb,
880 const struct super_block *newsb)
881{
882 struct superblock_security_struct *old = oldsb->s_security;
883 struct superblock_security_struct *new = newsb->s_security;
884 char oldflags = old->flags & SE_MNTMASK;
885 char newflags = new->flags & SE_MNTMASK;
886
887 if (oldflags != newflags)
888 goto mismatch;
889 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
890 goto mismatch;
891 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
892 goto mismatch;
893 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
894 goto mismatch;
895 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500896 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
897 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400898 if (oldroot->sid != newroot->sid)
899 goto mismatch;
900 }
901 return 0;
902mismatch:
peter enderborgc103a912018-06-12 10:09:03 +0200903 pr_warn("SELinux: mount invalid. Same superblock, "
Jeff Layton094f7b62013-04-01 08:14:24 -0400904 "different security settings for (dev %s, "
905 "type %s)\n", newsb->s_id, newsb->s_type->name);
906 return -EBUSY;
907}
908
909static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400910 struct super_block *newsb,
911 unsigned long kern_flags,
912 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500913{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400914 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500915 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
916 struct superblock_security_struct *newsbsec = newsb->s_security;
917
918 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
919 int set_context = (oldsbsec->flags & CONTEXT_MNT);
920 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
921
Eric Paris0f5e6422008-04-21 16:24:11 -0400922 /*
923 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400924 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400925 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500926 if (!selinux_state.initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400927 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500928
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400929 /*
930 * Specifying internal flags without providing a place to
931 * place the results is not allowed.
932 */
933 if (kern_flags && !set_kern_flags)
934 return -EINVAL;
935
Eric Parisc9180a52007-11-30 13:00:35 -0500936 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500937 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500938
Jeff Layton094f7b62013-04-01 08:14:24 -0400939 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500940 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400941 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400942
Eric Parisc9180a52007-11-30 13:00:35 -0500943 mutex_lock(&newsbsec->lock);
944
945 newsbsec->flags = oldsbsec->flags;
946
947 newsbsec->sid = oldsbsec->sid;
948 newsbsec->def_sid = oldsbsec->def_sid;
949 newsbsec->behavior = oldsbsec->behavior;
950
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400951 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
952 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500953 rc = security_fs_use(&selinux_state, newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400954 if (rc)
955 goto out;
956 }
957
958 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
959 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
960 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
961 }
962
Eric Parisc9180a52007-11-30 13:00:35 -0500963 if (set_context) {
964 u32 sid = oldsbsec->mntpoint_sid;
965
966 if (!set_fscontext)
967 newsbsec->sid = sid;
968 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500969 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500970 newisec->sid = sid;
971 }
972 newsbsec->mntpoint_sid = sid;
973 }
974 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500975 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
976 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500977
978 newisec->sid = oldisec->sid;
979 }
980
981 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400982out:
Eric Parisc9180a52007-11-30 13:00:35 -0500983 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400984 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500985}
986
Al Viroba641862018-12-14 20:28:15 -0500987static int selinux_add_opt(int token, const char *s, void **mnt_opts)
988{
989 struct selinux_mnt_opts *opts = *mnt_opts;
990
991 if (!opts) {
992 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
993 if (!opts)
994 return -ENOMEM;
995 *mnt_opts = opts;
996 }
997 if (!s)
998 return -ENOMEM;
999 switch (token) {
1000 case Opt_context:
1001 if (opts->context || opts->defcontext)
1002 goto Einval;
1003 opts->context = s;
1004 break;
1005 case Opt_fscontext:
1006 if (opts->fscontext)
1007 goto Einval;
1008 opts->fscontext = s;
1009 break;
1010 case Opt_rootcontext:
1011 if (opts->rootcontext)
1012 goto Einval;
1013 opts->rootcontext = s;
1014 break;
1015 case Opt_defcontext:
1016 if (opts->context || opts->defcontext)
1017 goto Einval;
1018 opts->defcontext = s;
1019 break;
1020 }
1021 return 0;
1022Einval:
1023 pr_warn(SEL_MOUNT_FAIL_MSG);
1024 kfree(s);
1025 return -EINVAL;
1026}
1027
Adrian Bunk2e1479d2008-03-17 22:29:23 +02001028static int selinux_parse_opts_str(char *options,
Al Viro204cc0c2018-12-13 13:41:47 -05001029 void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001030{
Eric Parise0007522008-03-05 10:31:54 -05001031 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -05001032
1033 /* Standard string-based options. */
1034 while ((p = strsep(&options, "|")) != NULL) {
Al Viroba641862018-12-14 20:28:15 -05001035 int token, rc;
Eric Parisc9180a52007-11-30 13:00:35 -05001036 substring_t args[MAX_OPT_ARGS];
Al Viroba641862018-12-14 20:28:15 -05001037 const char *arg;
Eric Parisc9180a52007-11-30 13:00:35 -05001038
1039 if (!*p)
1040 continue;
1041
1042 token = match_token(p, tokens, args);
1043
Al Viroba641862018-12-14 20:28:15 -05001044 if (token == Opt_labelsupport) /* eaten and completely ignored */
1045 continue;
1046 arg = match_strdup(&args[0]);
1047 rc = selinux_add_opt(token, arg, mnt_opts);
1048 if (unlikely(rc)) {
1049 kfree(arg);
1050 if (*mnt_opts) {
1051 selinux_free_mnt_opts(*mnt_opts);
1052 *mnt_opts = NULL;
Eric Parisc9180a52007-11-30 13:00:35 -05001053 }
Al Viroba641862018-12-14 20:28:15 -05001054 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -05001055 }
1056 }
Eric Parise0007522008-03-05 10:31:54 -05001057 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058}
1059
Al Viroe3489f82018-12-13 00:24:36 -05001060static int show_sid(struct seq_file *m, u32 sid)
Eric Paris2069f452008-07-04 09:47:13 +10001061{
Al Viroe3489f82018-12-13 00:24:36 -05001062 char *context = NULL;
1063 u32 len;
1064 int rc;
Eric Paris2069f452008-07-04 09:47:13 +10001065
Al Viroe3489f82018-12-13 00:24:36 -05001066 rc = security_sid_to_context(&selinux_state, sid,
1067 &context, &len);
1068 if (!rc) {
1069 bool has_comma = context && strchr(context, ',');
David P. Quigley11689d42009-01-16 09:22:03 -05001070
Eric Paris2069f452008-07-04 09:47:13 +10001071 if (has_comma)
1072 seq_putc(m, '\"');
Al Viroe3489f82018-12-13 00:24:36 -05001073 seq_escape(m, context, "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001074 if (has_comma)
1075 seq_putc(m, '\"');
1076 }
Al Viroe3489f82018-12-13 00:24:36 -05001077 kfree(context);
1078 return rc;
Eric Paris2069f452008-07-04 09:47:13 +10001079}
1080
1081static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1082{
Al Viroe3489f82018-12-13 00:24:36 -05001083 struct superblock_security_struct *sbsec = sb->s_security;
Eric Paris2069f452008-07-04 09:47:13 +10001084 int rc;
1085
Al Viroe3489f82018-12-13 00:24:36 -05001086 if (!(sbsec->flags & SE_SBINITIALIZED))
1087 return 0;
1088
1089 if (!selinux_state.initialized)
1090 return 0;
1091
1092 if (sbsec->flags & FSCONTEXT_MNT) {
1093 seq_putc(m, ',');
1094 seq_puts(m, FSCONTEXT_STR);
1095 rc = show_sid(m, sbsec->sid);
1096 if (rc)
1097 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001098 }
Al Viroe3489f82018-12-13 00:24:36 -05001099 if (sbsec->flags & CONTEXT_MNT) {
1100 seq_putc(m, ',');
1101 seq_puts(m, CONTEXT_STR);
1102 rc = show_sid(m, sbsec->mntpoint_sid);
1103 if (rc)
1104 return rc;
1105 }
1106 if (sbsec->flags & DEFCONTEXT_MNT) {
1107 seq_putc(m, ',');
1108 seq_puts(m, DEFCONTEXT_STR);
1109 rc = show_sid(m, sbsec->def_sid);
1110 if (rc)
1111 return rc;
1112 }
1113 if (sbsec->flags & ROOTCONTEXT_MNT) {
1114 struct dentry *root = sbsec->sb->s_root;
1115 struct inode_security_struct *isec = backing_inode_security(root);
1116 seq_putc(m, ',');
1117 seq_puts(m, ROOTCONTEXT_STR);
1118 rc = show_sid(m, isec->sid);
1119 if (rc)
1120 return rc;
1121 }
1122 if (sbsec->flags & SBLABEL_MNT) {
1123 seq_putc(m, ',');
1124 seq_puts(m, LABELSUPP_STR);
1125 }
1126 return 0;
Eric Paris2069f452008-07-04 09:47:13 +10001127}
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129static inline u16 inode_mode_to_security_class(umode_t mode)
1130{
1131 switch (mode & S_IFMT) {
1132 case S_IFSOCK:
1133 return SECCLASS_SOCK_FILE;
1134 case S_IFLNK:
1135 return SECCLASS_LNK_FILE;
1136 case S_IFREG:
1137 return SECCLASS_FILE;
1138 case S_IFBLK:
1139 return SECCLASS_BLK_FILE;
1140 case S_IFDIR:
1141 return SECCLASS_DIR;
1142 case S_IFCHR:
1143 return SECCLASS_CHR_FILE;
1144 case S_IFIFO:
1145 return SECCLASS_FIFO_FILE;
1146
1147 }
1148
1149 return SECCLASS_FILE;
1150}
1151
James Morris13402582005-09-30 14:24:34 -04001152static inline int default_protocol_stream(int protocol)
1153{
1154 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1155}
1156
1157static inline int default_protocol_dgram(int protocol)
1158{
1159 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1160}
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1163{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001164 int extsockclass = selinux_policycap_extsockclass();
Stephen Smalleyda69a532017-01-09 10:07:30 -05001165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 switch (family) {
1167 case PF_UNIX:
1168 switch (type) {
1169 case SOCK_STREAM:
1170 case SOCK_SEQPACKET:
1171 return SECCLASS_UNIX_STREAM_SOCKET;
1172 case SOCK_DGRAM:
Luis Ressel2a764b52017-07-25 15:13:41 -04001173 case SOCK_RAW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 return SECCLASS_UNIX_DGRAM_SOCKET;
1175 }
1176 break;
1177 case PF_INET:
1178 case PF_INET6:
1179 switch (type) {
1180 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001181 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001182 if (default_protocol_stream(protocol))
1183 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001184 else if (extsockclass && protocol == IPPROTO_SCTP)
1185 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001186 else
1187 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001189 if (default_protocol_dgram(protocol))
1190 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001191 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1192 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001193 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001194 else
1195 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001196 case SOCK_DCCP:
1197 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001198 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 return SECCLASS_RAWIP_SOCKET;
1200 }
1201 break;
1202 case PF_NETLINK:
1203 switch (protocol) {
1204 case NETLINK_ROUTE:
1205 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001206 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1208 case NETLINK_NFLOG:
1209 return SECCLASS_NETLINK_NFLOG_SOCKET;
1210 case NETLINK_XFRM:
1211 return SECCLASS_NETLINK_XFRM_SOCKET;
1212 case NETLINK_SELINUX:
1213 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001214 case NETLINK_ISCSI:
1215 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 case NETLINK_AUDIT:
1217 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001218 case NETLINK_FIB_LOOKUP:
1219 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1220 case NETLINK_CONNECTOR:
1221 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1222 case NETLINK_NETFILTER:
1223 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 case NETLINK_DNRTMSG:
1225 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001226 case NETLINK_KOBJECT_UEVENT:
1227 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001228 case NETLINK_GENERIC:
1229 return SECCLASS_NETLINK_GENERIC_SOCKET;
1230 case NETLINK_SCSITRANSPORT:
1231 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1232 case NETLINK_RDMA:
1233 return SECCLASS_NETLINK_RDMA_SOCKET;
1234 case NETLINK_CRYPTO:
1235 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 default:
1237 return SECCLASS_NETLINK_SOCKET;
1238 }
1239 case PF_PACKET:
1240 return SECCLASS_PACKET_SOCKET;
1241 case PF_KEY:
1242 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001243 case PF_APPLETALK:
1244 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 }
1246
Stephen Smalleyda69a532017-01-09 10:07:30 -05001247 if (extsockclass) {
1248 switch (family) {
1249 case PF_AX25:
1250 return SECCLASS_AX25_SOCKET;
1251 case PF_IPX:
1252 return SECCLASS_IPX_SOCKET;
1253 case PF_NETROM:
1254 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001255 case PF_ATMPVC:
1256 return SECCLASS_ATMPVC_SOCKET;
1257 case PF_X25:
1258 return SECCLASS_X25_SOCKET;
1259 case PF_ROSE:
1260 return SECCLASS_ROSE_SOCKET;
1261 case PF_DECnet:
1262 return SECCLASS_DECNET_SOCKET;
1263 case PF_ATMSVC:
1264 return SECCLASS_ATMSVC_SOCKET;
1265 case PF_RDS:
1266 return SECCLASS_RDS_SOCKET;
1267 case PF_IRDA:
1268 return SECCLASS_IRDA_SOCKET;
1269 case PF_PPPOX:
1270 return SECCLASS_PPPOX_SOCKET;
1271 case PF_LLC:
1272 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001273 case PF_CAN:
1274 return SECCLASS_CAN_SOCKET;
1275 case PF_TIPC:
1276 return SECCLASS_TIPC_SOCKET;
1277 case PF_BLUETOOTH:
1278 return SECCLASS_BLUETOOTH_SOCKET;
1279 case PF_IUCV:
1280 return SECCLASS_IUCV_SOCKET;
1281 case PF_RXRPC:
1282 return SECCLASS_RXRPC_SOCKET;
1283 case PF_ISDN:
1284 return SECCLASS_ISDN_SOCKET;
1285 case PF_PHONET:
1286 return SECCLASS_PHONET_SOCKET;
1287 case PF_IEEE802154:
1288 return SECCLASS_IEEE802154_SOCKET;
1289 case PF_CAIF:
1290 return SECCLASS_CAIF_SOCKET;
1291 case PF_ALG:
1292 return SECCLASS_ALG_SOCKET;
1293 case PF_NFC:
1294 return SECCLASS_NFC_SOCKET;
1295 case PF_VSOCK:
1296 return SECCLASS_VSOCK_SOCKET;
1297 case PF_KCM:
1298 return SECCLASS_KCM_SOCKET;
1299 case PF_QIPCRTR:
1300 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001301 case PF_SMC:
1302 return SECCLASS_SMC_SOCKET;
Björn Töpel68e8b842018-05-02 13:01:22 +02001303 case PF_XDP:
1304 return SECCLASS_XDP_SOCKET;
1305#if PF_MAX > 45
Stephen Smalleyda69a532017-01-09 10:07:30 -05001306#error New address family defined, please update this function.
1307#endif
1308 }
1309 }
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 return SECCLASS_SOCKET;
1312}
1313
Stephen Smalley134509d2015-06-04 16:22:17 -04001314static int selinux_genfs_get_sid(struct dentry *dentry,
1315 u16 tclass,
1316 u16 flags,
1317 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001319 int rc;
Al Virofc640052016-04-10 01:33:30 -04001320 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001321 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Eric Paris828dfe12008-04-17 13:17:49 -04001323 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (!buffer)
1325 return -ENOMEM;
1326
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001327 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1328 if (IS_ERR(path))
1329 rc = PTR_ERR(path);
1330 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001331 if (flags & SE_SBPROC) {
1332 /* each process gets a /proc/PID/ entry. Strip off the
1333 * PID part to get a valid selinux labeling.
1334 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1335 while (path[1] >= '0' && path[1] <= '9') {
1336 path[1] = '/';
1337 path++;
1338 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001339 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001340 rc = security_genfs_sid(&selinux_state, sb->s_type->name,
1341 path, tclass, sid);
Stephen Smalley7bb185e2018-09-04 16:51:36 -04001342 if (rc == -ENOENT) {
1343 /* No match in policy, mark as unlabeled. */
1344 *sid = SECINITSID_UNLABELED;
1345 rc = 0;
1346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 free_page((unsigned long)buffer);
1349 return rc;
1350}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
1352/* The inode's security attributes must be initialized before first use. */
1353static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1354{
1355 struct superblock_security_struct *sbsec = NULL;
1356 struct inode_security_struct *isec = inode->i_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001357 u32 task_sid, sid = 0;
1358 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 struct dentry *dentry;
1360#define INITCONTEXTLEN 255
1361 char *context = NULL;
1362 unsigned len = 0;
1363 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001365 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001366 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001368 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001369 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001370 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001372 if (isec->sclass == SECCLASS_FILE)
1373 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001376 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 /* Defer initialization until selinux_complete_init,
1378 after the initial policy is loaded and the security
1379 server is ready to handle calls. */
1380 spin_lock(&sbsec->isec_lock);
1381 if (list_empty(&isec->list))
1382 list_add(&isec->list, &sbsec->isec_head);
1383 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001384 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 }
1386
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001387 sclass = isec->sclass;
1388 task_sid = isec->task_sid;
1389 sid = isec->sid;
1390 isec->initialized = LABEL_PENDING;
1391 spin_unlock(&isec->lock);
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001394 case SECURITY_FS_USE_NATIVE:
1395 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001397 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001398 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 break;
1400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 /* Need a dentry, since the xattr API requires one.
1402 Life would be simpler if we could just pass the inode. */
1403 if (opt_dentry) {
1404 /* Called from d_instantiate or d_splice_alias. */
1405 dentry = dget(opt_dentry);
1406 } else {
Al Virob1271252018-04-25 10:28:38 -04001407 /*
1408 * Called from selinux_complete_init, try to find a dentry.
1409 * Some filesystems really want a connected one, so try
1410 * that first. We could split SECURITY_FS_USE_XATTR in
1411 * two, depending upon that...
1412 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001414 if (!dentry)
1415 dentry = d_find_any_alias(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 }
1417 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001418 /*
1419 * this is can be hit on boot when a file is accessed
1420 * before the policy is loaded. When we load policy we
1421 * may find inodes that have no dentry on the
1422 * sbsec->isec_head list. No reason to complain as these
1423 * will get fixed up the next time we go through
1424 * inode_doinit with a dentry, before these inodes could
1425 * be used again by userspace.
1426 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001427 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
1429
1430 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001431 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 if (!context) {
1433 rc = -ENOMEM;
1434 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001435 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001437 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001438 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001440 kfree(context);
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001443 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 if (rc < 0) {
1445 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001446 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001449 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 if (!context) {
1451 rc = -ENOMEM;
1452 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001453 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001455 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001456 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 }
1458 dput(dentry);
1459 if (rc < 0) {
1460 if (rc != -ENODATA) {
peter enderborgc103a912018-06-12 10:09:03 +02001461 pr_warn("SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001462 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 -rc, inode->i_sb->s_id, inode->i_ino);
1464 kfree(context);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001465 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 }
1467 /* Map ENODATA to the default file SID */
1468 sid = sbsec->def_sid;
1469 rc = 0;
1470 } else {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001471 rc = security_context_to_sid_default(&selinux_state,
1472 context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001473 sbsec->def_sid,
1474 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001476 char *dev = inode->i_sb->s_id;
1477 unsigned long ino = inode->i_ino;
1478
1479 if (rc == -EINVAL) {
1480 if (printk_ratelimit())
peter enderborgc103a912018-06-12 10:09:03 +02001481 pr_notice("SELinux: inode=%lu on dev=%s was found to have an invalid "
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001482 "context=%s. This indicates you may need to relabel the inode or the "
1483 "filesystem in question.\n", ino, dev, context);
1484 } else {
peter enderborgc103a912018-06-12 10:09:03 +02001485 pr_warn("SELinux: %s: context_to_sid(%s) "
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001486 "returned %d for dev=%s ino=%ld\n",
1487 __func__, context, -rc, dev, ino);
1488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 kfree(context);
1490 /* Leave with the unlabeled SID */
1491 rc = 0;
1492 break;
1493 }
1494 }
1495 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 break;
1497 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001498 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 break;
1500 case SECURITY_FS_USE_TRANS:
1501 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001502 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
1504 /* Try to obtain a transition SID. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001505 rc = security_transition_sid(&selinux_state, task_sid, sid,
1506 sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001508 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001510 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001511 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001512 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001514 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001515 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Stephen Smalley134509d2015-06-04 16:22:17 -04001517 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001518 /* We must have a dentry to determine the label on
1519 * procfs inodes */
Al Virob1271252018-04-25 10:28:38 -04001520 if (opt_dentry) {
Paul Mooref64410e2014-03-19 16:46:18 -04001521 /* Called from d_instantiate or
1522 * d_splice_alias. */
1523 dentry = dget(opt_dentry);
Al Virob1271252018-04-25 10:28:38 -04001524 } else {
Paul Mooref64410e2014-03-19 16:46:18 -04001525 /* Called from selinux_complete_init, try to
Al Virob1271252018-04-25 10:28:38 -04001526 * find a dentry. Some filesystems really want
1527 * a connected one, so try that first.
1528 */
Paul Mooref64410e2014-03-19 16:46:18 -04001529 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001530 if (!dentry)
1531 dentry = d_find_any_alias(inode);
1532 }
Paul Mooref64410e2014-03-19 16:46:18 -04001533 /*
1534 * This can be hit on boot when a file is accessed
1535 * before the policy is loaded. When we load policy we
1536 * may find inodes that have no dentry on the
1537 * sbsec->isec_head list. No reason to complain as
1538 * these will get fixed up the next time we go through
1539 * inode_doinit() with a dentry, before these inodes
1540 * could be used again by userspace.
1541 */
1542 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001543 goto out;
1544 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001545 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001546 dput(dentry);
1547 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001548 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 }
1550 break;
1551 }
1552
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001553out:
1554 spin_lock(&isec->lock);
1555 if (isec->initialized == LABEL_PENDING) {
1556 if (!sid || rc) {
1557 isec->initialized = LABEL_INVALID;
1558 goto out_unlock;
1559 }
1560
1561 isec->initialized = LABEL_INITIALIZED;
1562 isec->sid = sid;
1563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Eric Paris23970742006-09-25 23:32:01 -07001565out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001566 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 return rc;
1568}
1569
1570/* Convert a Linux signal to an access vector. */
1571static inline u32 signal_to_av(int sig)
1572{
1573 u32 perm = 0;
1574
1575 switch (sig) {
1576 case SIGCHLD:
1577 /* Commonly granted from child to parent. */
1578 perm = PROCESS__SIGCHLD;
1579 break;
1580 case SIGKILL:
1581 /* Cannot be caught or ignored */
1582 perm = PROCESS__SIGKILL;
1583 break;
1584 case SIGSTOP:
1585 /* Cannot be caught or ignored */
1586 perm = PROCESS__SIGSTOP;
1587 break;
1588 default:
1589 /* All other signals. */
1590 perm = PROCESS__SIGNAL;
1591 break;
1592 }
1593
1594 return perm;
1595}
1596
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001597#if CAP_LAST_CAP > 63
1598#error Fix SELinux to handle capabilities > 63.
1599#endif
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001602static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001603 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604{
Thomas Liu2bf49692009-07-14 12:14:09 -04001605 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001606 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001607 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001608 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001609 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001610 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
Eric Paris50c205f2012-04-04 15:01:43 -04001612 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 ad.u.cap = cap;
1614
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001615 switch (CAP_TO_INDEX(cap)) {
1616 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001617 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001618 break;
1619 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001620 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001621 break;
1622 default:
peter enderborgc103a912018-06-12 10:09:03 +02001623 pr_err("SELinux: out of range capability %d\n", cap);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001624 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001625 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001626 }
Eric Paris06112162008-11-11 22:02:50 +11001627
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001628 rc = avc_has_perm_noaudit(&selinux_state,
1629 sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001630 if (audit == SECURITY_CAP_AUDIT) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001631 int rc2 = avc_audit(&selinux_state,
1632 sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001633 if (rc2)
1634 return rc2;
1635 }
Eric Paris06112162008-11-11 22:02:50 +11001636 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637}
1638
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639/* Check whether a task has a particular permission to an inode.
1640 The 'adp' parameter is optional and allows other audit
1641 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001642static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 struct inode *inode,
1644 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001645 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001648 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
David Howellse0e81732009-09-02 09:13:40 +01001650 validate_creds(cred);
1651
Eric Paris828dfe12008-04-17 13:17:49 -04001652 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001653 return 0;
1654
David Howells88e67f32008-11-14 10:39:21 +11001655 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 isec = inode->i_security;
1657
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001658 return avc_has_perm(&selinux_state,
1659 sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660}
1661
1662/* Same as inode_has_perm, but pass explicit audit data containing
1663 the dentry to help the auditing code to more easily generate the
1664 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001665static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 struct dentry *dentry,
1667 u32 av)
1668{
David Howellsc6f493d2015-03-17 22:26:22 +00001669 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001670 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001671
Eric Paris50c205f2012-04-04 15:01:43 -04001672 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001673 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001674 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001675 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001676}
1677
1678/* Same as inode_has_perm, but pass explicit audit data containing
1679 the path to help the auditing code to more easily generate the
1680 pathname if needed. */
1681static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001682 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001683 u32 av)
1684{
David Howellsc6f493d2015-03-17 22:26:22 +00001685 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001686 struct common_audit_data ad;
1687
Eric Paris50c205f2012-04-04 15:01:43 -04001688 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001689 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001690 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001691 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692}
1693
David Howells13f8e982013-06-13 23:37:55 +01001694/* Same as path_has_perm, but uses the inode from the file struct. */
1695static inline int file_path_has_perm(const struct cred *cred,
1696 struct file *file,
1697 u32 av)
1698{
1699 struct common_audit_data ad;
1700
Vivek Goyal43af5de2016-09-09 11:37:49 -04001701 ad.type = LSM_AUDIT_DATA_FILE;
1702 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001703 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001704}
1705
Chenbo Fengf66e4482017-10-18 13:00:26 -07001706#ifdef CONFIG_BPF_SYSCALL
1707static int bpf_fd_pass(struct file *file, u32 sid);
1708#endif
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710/* Check whether a task can use an open file descriptor to
1711 access an inode in a given way. Check access to the
1712 descriptor itself, and then use dentry_has_perm to
1713 check a particular permission to the file.
1714 Access to the descriptor is implicitly granted if it
1715 has the same SID as the process. If av is zero, then
1716 access to the file is not checked, e.g. for cases
1717 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001718static int file_has_perm(const struct cred *cred,
1719 struct file *file,
1720 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001723 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001724 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001725 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 int rc;
1727
Vivek Goyal43af5de2016-09-09 11:37:49 -04001728 ad.type = LSM_AUDIT_DATA_FILE;
1729 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
David Howells275bb412008-11-14 10:39:19 +11001731 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001732 rc = avc_has_perm(&selinux_state,
1733 sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 SECCLASS_FD,
1735 FD__USE,
1736 &ad);
1737 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001738 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 }
1740
Chenbo Fengf66e4482017-10-18 13:00:26 -07001741#ifdef CONFIG_BPF_SYSCALL
1742 rc = bpf_fd_pass(file, cred_sid(cred));
1743 if (rc)
1744 return rc;
1745#endif
1746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001748 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001750 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
David Howells88e67f32008-11-14 10:39:21 +11001752out:
1753 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754}
1755
David Howellsc3c188b2015-07-10 17:19:58 -04001756/*
1757 * Determine the label for an inode that might be unioned.
1758 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001759static int
1760selinux_determine_inode_label(const struct task_security_struct *tsec,
1761 struct inode *dir,
1762 const struct qstr *name, u16 tclass,
1763 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001764{
1765 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001766
1767 if ((sbsec->flags & SE_SBINITIALIZED) &&
1768 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1769 *_new_isid = sbsec->mntpoint_sid;
1770 } else if ((sbsec->flags & SBLABEL_MNT) &&
1771 tsec->create_sid) {
1772 *_new_isid = tsec->create_sid;
1773 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001774 const struct inode_security_struct *dsec = inode_security(dir);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001775 return security_transition_sid(&selinux_state, tsec->sid,
1776 dsec->sid, tclass,
David Howellsc3c188b2015-07-10 17:19:58 -04001777 name, _new_isid);
1778 }
1779
1780 return 0;
1781}
1782
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783/* Check whether a task can create a file. */
1784static int may_create(struct inode *dir,
1785 struct dentry *dentry,
1786 u16 tclass)
1787{
Paul Moore5fb49872010-04-22 14:46:19 -04001788 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 struct inode_security_struct *dsec;
1790 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001791 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001792 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 int rc;
1794
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001795 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 sbsec = dir->i_sb->s_security;
1797
David Howells275bb412008-11-14 10:39:19 +11001798 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001799
Eric Paris50c205f2012-04-04 15:01:43 -04001800 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001801 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001803 rc = avc_has_perm(&selinux_state,
1804 sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 DIR__ADD_NAME | DIR__SEARCH,
1806 &ad);
1807 if (rc)
1808 return rc;
1809
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001810 rc = selinux_determine_inode_label(current_security(), dir,
1811 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001812 if (rc)
1813 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001815 rc = avc_has_perm(&selinux_state,
1816 sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 if (rc)
1818 return rc;
1819
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001820 return avc_has_perm(&selinux_state,
1821 newsid, sbsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 SECCLASS_FILESYSTEM,
1823 FILESYSTEM__ASSOCIATE, &ad);
1824}
1825
Eric Paris828dfe12008-04-17 13:17:49 -04001826#define MAY_LINK 0
1827#define MAY_UNLINK 1
1828#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
1830/* Check whether a task can link, unlink, or rmdir a file/directory. */
1831static int may_link(struct inode *dir,
1832 struct dentry *dentry,
1833 int kind)
1834
1835{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001837 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001838 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 u32 av;
1840 int rc;
1841
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001842 dsec = inode_security(dir);
1843 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
Eric Paris50c205f2012-04-04 15:01:43 -04001845 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001846 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848 av = DIR__SEARCH;
1849 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001850 rc = avc_has_perm(&selinux_state,
1851 sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 if (rc)
1853 return rc;
1854
1855 switch (kind) {
1856 case MAY_LINK:
1857 av = FILE__LINK;
1858 break;
1859 case MAY_UNLINK:
1860 av = FILE__UNLINK;
1861 break;
1862 case MAY_RMDIR:
1863 av = DIR__RMDIR;
1864 break;
1865 default:
peter enderborgc103a912018-06-12 10:09:03 +02001866 pr_warn("SELinux: %s: unrecognized kind %d\n",
Eric Paris744ba352008-04-17 11:52:44 -04001867 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 return 0;
1869 }
1870
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001871 rc = avc_has_perm(&selinux_state,
1872 sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 return rc;
1874}
1875
1876static inline int may_rename(struct inode *old_dir,
1877 struct dentry *old_dentry,
1878 struct inode *new_dir,
1879 struct dentry *new_dentry)
1880{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001882 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001883 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 u32 av;
1885 int old_is_dir, new_is_dir;
1886 int rc;
1887
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001888 old_dsec = inode_security(old_dir);
1889 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001890 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001891 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
Eric Paris50c205f2012-04-04 15:01:43 -04001893 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
Eric Parisa2694342011-04-25 13:10:27 -04001895 ad.u.dentry = old_dentry;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001896 rc = avc_has_perm(&selinux_state,
1897 sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1899 if (rc)
1900 return rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001901 rc = avc_has_perm(&selinux_state,
1902 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 old_isec->sclass, FILE__RENAME, &ad);
1904 if (rc)
1905 return rc;
1906 if (old_is_dir && new_dir != old_dir) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001907 rc = avc_has_perm(&selinux_state,
1908 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 old_isec->sclass, DIR__REPARENT, &ad);
1910 if (rc)
1911 return rc;
1912 }
1913
Eric Parisa2694342011-04-25 13:10:27 -04001914 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001916 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 av |= DIR__REMOVE_NAME;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001918 rc = avc_has_perm(&selinux_state,
1919 sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 if (rc)
1921 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001922 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001923 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001924 new_is_dir = d_is_dir(new_dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001925 rc = avc_has_perm(&selinux_state,
1926 sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 new_isec->sclass,
1928 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1929 if (rc)
1930 return rc;
1931 }
1932
1933 return 0;
1934}
1935
1936/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001937static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 struct super_block *sb,
1939 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001940 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001943 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 sbsec = sb->s_security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001946 return avc_has_perm(&selinux_state,
1947 sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948}
1949
1950/* Convert a Linux mode and permission mask to an access vector. */
1951static inline u32 file_mask_to_av(int mode, int mask)
1952{
1953 u32 av = 0;
1954
Al Virodba19c62011-07-25 20:49:29 -04001955 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 if (mask & MAY_EXEC)
1957 av |= FILE__EXECUTE;
1958 if (mask & MAY_READ)
1959 av |= FILE__READ;
1960
1961 if (mask & MAY_APPEND)
1962 av |= FILE__APPEND;
1963 else if (mask & MAY_WRITE)
1964 av |= FILE__WRITE;
1965
1966 } else {
1967 if (mask & MAY_EXEC)
1968 av |= DIR__SEARCH;
1969 if (mask & MAY_WRITE)
1970 av |= DIR__WRITE;
1971 if (mask & MAY_READ)
1972 av |= DIR__READ;
1973 }
1974
1975 return av;
1976}
1977
1978/* Convert a Linux file to an access vector. */
1979static inline u32 file_to_av(struct file *file)
1980{
1981 u32 av = 0;
1982
1983 if (file->f_mode & FMODE_READ)
1984 av |= FILE__READ;
1985 if (file->f_mode & FMODE_WRITE) {
1986 if (file->f_flags & O_APPEND)
1987 av |= FILE__APPEND;
1988 else
1989 av |= FILE__WRITE;
1990 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001991 if (!av) {
1992 /*
1993 * Special file opened with flags 3 for ioctl-only use.
1994 */
1995 av = FILE__IOCTL;
1996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
1998 return av;
1999}
2000
Eric Paris8b6a5a32008-10-29 17:06:46 -04002001/*
2002 * Convert a file to an access vector and include the correct open
2003 * open permission.
2004 */
2005static inline u32 open_file_to_av(struct file *file)
2006{
2007 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04002008 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002009
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002010 if (selinux_policycap_openperm() &&
2011 inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002012 av |= FILE__OPEN;
2013
Eric Paris8b6a5a32008-10-29 17:06:46 -04002014 return av;
2015}
2016
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017/* Hook functions begin here. */
2018
Stephen Smalley79af7302015-01-21 10:54:10 -05002019static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2020{
2021 u32 mysid = current_sid();
2022 u32 mgrsid = task_sid(mgr);
2023
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002024 return avc_has_perm(&selinux_state,
2025 mysid, mgrsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002026 BINDER__SET_CONTEXT_MGR, NULL);
2027}
2028
2029static int selinux_binder_transaction(struct task_struct *from,
2030 struct task_struct *to)
2031{
2032 u32 mysid = current_sid();
2033 u32 fromsid = task_sid(from);
2034 u32 tosid = task_sid(to);
2035 int rc;
2036
2037 if (mysid != fromsid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002038 rc = avc_has_perm(&selinux_state,
2039 mysid, fromsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002040 BINDER__IMPERSONATE, NULL);
2041 if (rc)
2042 return rc;
2043 }
2044
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002045 return avc_has_perm(&selinux_state,
2046 fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
Stephen Smalley79af7302015-01-21 10:54:10 -05002047 NULL);
2048}
2049
2050static int selinux_binder_transfer_binder(struct task_struct *from,
2051 struct task_struct *to)
2052{
2053 u32 fromsid = task_sid(from);
2054 u32 tosid = task_sid(to);
2055
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002056 return avc_has_perm(&selinux_state,
2057 fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002058 NULL);
2059}
2060
2061static int selinux_binder_transfer_file(struct task_struct *from,
2062 struct task_struct *to,
2063 struct file *file)
2064{
2065 u32 sid = task_sid(to);
2066 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002067 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002068 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002069 struct common_audit_data ad;
2070 int rc;
2071
2072 ad.type = LSM_AUDIT_DATA_PATH;
2073 ad.u.path = file->f_path;
2074
2075 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002076 rc = avc_has_perm(&selinux_state,
2077 sid, fsec->sid,
Stephen Smalley79af7302015-01-21 10:54:10 -05002078 SECCLASS_FD,
2079 FD__USE,
2080 &ad);
2081 if (rc)
2082 return rc;
2083 }
2084
Chenbo Fengf66e4482017-10-18 13:00:26 -07002085#ifdef CONFIG_BPF_SYSCALL
2086 rc = bpf_fd_pass(file, sid);
2087 if (rc)
2088 return rc;
2089#endif
2090
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002091 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002092 return 0;
2093
Paul Moore20cdef82016-04-04 14:14:42 -04002094 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002095 return avc_has_perm(&selinux_state,
2096 sid, isec->sid, isec->sclass, file_to_av(file),
Stephen Smalley79af7302015-01-21 10:54:10 -05002097 &ad);
2098}
2099
Ingo Molnar9e488582009-05-07 19:26:19 +10002100static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002101 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002103 u32 sid = current_sid();
2104 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002105
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002106 if (mode & PTRACE_MODE_READ)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002107 return avc_has_perm(&selinux_state,
2108 sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002109
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002110 return avc_has_perm(&selinux_state,
2111 sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002112}
2113
2114static int selinux_ptrace_traceme(struct task_struct *parent)
2115{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002116 return avc_has_perm(&selinux_state,
2117 task_sid(parent), current_sid(), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002118 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119}
2120
2121static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002122 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002124 return avc_has_perm(&selinux_state,
2125 current_sid(), task_sid(target), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002126 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127}
2128
David Howellsd84f4f92008-11-14 10:39:23 +11002129static int selinux_capset(struct cred *new, const struct cred *old,
2130 const kernel_cap_t *effective,
2131 const kernel_cap_t *inheritable,
2132 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002134 return avc_has_perm(&selinux_state,
2135 cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002136 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137}
2138
James Morris5626d3e2009-01-30 10:05:06 +11002139/*
2140 * (This comment used to live with the selinux_task_setuid hook,
2141 * which was removed).
2142 *
2143 * Since setuid only affects the current process, and since the SELinux
2144 * controls are not based on the Linux identity attributes, SELinux does not
2145 * need to control this operation. However, SELinux does control the use of
2146 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2147 */
2148
Eric Paris6a9de492012-01-03 12:25:14 -05002149static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2150 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002152 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2156{
David Howells88e67f32008-11-14 10:39:21 +11002157 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 int rc = 0;
2159
2160 if (!sb)
2161 return 0;
2162
2163 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002164 case Q_SYNC:
2165 case Q_QUOTAON:
2166 case Q_QUOTAOFF:
2167 case Q_SETINFO:
2168 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002169 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002170 break;
2171 case Q_GETFMT:
2172 case Q_GETINFO:
2173 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002174 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002175 break;
2176 default:
2177 rc = 0; /* let the kernel handle invalid cmds */
2178 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
2180 return rc;
2181}
2182
2183static int selinux_quota_on(struct dentry *dentry)
2184{
David Howells88e67f32008-11-14 10:39:21 +11002185 const struct cred *cred = current_cred();
2186
Eric Paris2875fa02011-04-28 16:04:24 -04002187 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188}
2189
Eric Paris12b30522010-11-15 18:36:29 -05002190static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002193 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2194 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002195 return avc_has_perm(&selinux_state,
2196 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002197 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002198 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2199 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2200 /* Set level of messages printed to console */
2201 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002202 return avc_has_perm(&selinux_state,
2203 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002204 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2205 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002207 /* All other syslog types */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002208 return avc_has_perm(&selinux_state,
2209 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002210 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211}
2212
2213/*
2214 * Check that a process has enough memory to allocate a new virtual
2215 * mapping. 0 means there is enough memory for the allocation to
2216 * succeed and -ENOMEM implies there is not.
2217 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 * Do not audit the selinux permission check, as this is applied to all
2219 * processes that allocate mappings.
2220 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002221static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222{
2223 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002225 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002226 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 if (rc == 0)
2228 cap_sys_admin = 1;
2229
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002230 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231}
2232
2233/* binprm security operations */
2234
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002235static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002236{
2237 u32 sid = 0;
2238 struct task_struct *tracer;
2239
2240 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002241 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002242 if (tracer)
2243 sid = task_sid(tracer);
2244 rcu_read_unlock();
2245
2246 return sid;
2247}
2248
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002249static int check_nnp_nosuid(const struct linux_binprm *bprm,
2250 const struct task_security_struct *old_tsec,
2251 const struct task_security_struct *new_tsec)
2252{
2253 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002254 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002255 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002256 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002257
2258 if (!nnp && !nosuid)
2259 return 0; /* neither NNP nor nosuid */
2260
2261 if (new_tsec->sid == old_tsec->sid)
2262 return 0; /* No change in credentials */
2263
2264 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002265 * If the policy enables the nnp_nosuid_transition policy capability,
2266 * then we permit transitions under NNP or nosuid if the
2267 * policy allows the corresponding permission between
2268 * the old and new contexts.
2269 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002270 if (selinux_policycap_nnp_nosuid_transition()) {
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002271 av = 0;
2272 if (nnp)
2273 av |= PROCESS2__NNP_TRANSITION;
2274 if (nosuid)
2275 av |= PROCESS2__NOSUID_TRANSITION;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002276 rc = avc_has_perm(&selinux_state,
2277 old_tsec->sid, new_tsec->sid,
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002278 SECCLASS_PROCESS2, av, NULL);
2279 if (!rc)
2280 return 0;
2281 }
2282
2283 /*
2284 * We also permit NNP or nosuid transitions to bounded SIDs,
2285 * i.e. SIDs that are guaranteed to only be allowed a subset
2286 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002287 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002288 rc = security_bounded_transition(&selinux_state, old_tsec->sid,
2289 new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002290 if (!rc)
2291 return 0;
2292
2293 /*
2294 * On failure, preserve the errno values for NNP vs nosuid.
2295 * NNP: Operation not permitted for caller.
2296 * nosuid: Permission denied to file.
2297 */
2298 if (nnp)
2299 return -EPERM;
2300 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002301}
2302
David Howellsa6f76f22008-11-14 10:39:24 +11002303static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304{
David Howellsa6f76f22008-11-14 10:39:24 +11002305 const struct task_security_struct *old_tsec;
2306 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002308 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002309 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 int rc;
2311
David Howellsa6f76f22008-11-14 10:39:24 +11002312 /* SELinux context only depends on initial program or script and not
2313 * the script interpreter */
Kees Cookddb4a142017-07-18 15:25:23 -07002314 if (bprm->called_set_creds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return 0;
2316
David Howellsa6f76f22008-11-14 10:39:24 +11002317 old_tsec = current_security();
2318 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002319 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
2321 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002322 new_tsec->sid = old_tsec->sid;
2323 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
Michael LeMay28eba5b2006-06-27 02:53:42 -07002325 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002326 new_tsec->create_sid = 0;
2327 new_tsec->keycreate_sid = 0;
2328 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
David Howellsa6f76f22008-11-14 10:39:24 +11002330 if (old_tsec->exec_sid) {
2331 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002333 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002334
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002335 /* Fail on NNP or nosuid if not an allowed transition. */
2336 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2337 if (rc)
2338 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 } else {
2340 /* Check for a default transition on this program. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002341 rc = security_transition_sid(&selinux_state, old_tsec->sid,
2342 isec->sid, SECCLASS_PROCESS, NULL,
Eric Paris652bb9b2011-02-01 11:05:40 -05002343 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 if (rc)
2345 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002346
2347 /*
2348 * Fallback to old SID on NNP or nosuid if not an allowed
2349 * transition.
2350 */
2351 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2352 if (rc)
2353 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 }
2355
Vivek Goyal43af5de2016-09-09 11:37:49 -04002356 ad.type = LSM_AUDIT_DATA_FILE;
2357 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
David Howellsa6f76f22008-11-14 10:39:24 +11002359 if (new_tsec->sid == old_tsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002360 rc = avc_has_perm(&selinux_state,
2361 old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2363 if (rc)
2364 return rc;
2365 } else {
2366 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002367 rc = avc_has_perm(&selinux_state,
2368 old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2370 if (rc)
2371 return rc;
2372
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002373 rc = avc_has_perm(&selinux_state,
2374 new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2376 if (rc)
2377 return rc;
2378
David Howellsa6f76f22008-11-14 10:39:24 +11002379 /* Check for shared state */
2380 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002381 rc = avc_has_perm(&selinux_state,
2382 old_tsec->sid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002383 SECCLASS_PROCESS, PROCESS__SHARE,
2384 NULL);
2385 if (rc)
2386 return -EPERM;
2387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
David Howellsa6f76f22008-11-14 10:39:24 +11002389 /* Make sure that anyone attempting to ptrace over a task that
2390 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002391 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002392 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002393 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002394 rc = avc_has_perm(&selinux_state,
2395 ptsid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002396 SECCLASS_PROCESS,
2397 PROCESS__PTRACE, NULL);
2398 if (rc)
2399 return -EPERM;
2400 }
2401 }
2402
2403 /* Clear any possibly unsafe personality bits on exec: */
2404 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 /* Enable secure mode for SIDs transitions unless
2407 the noatsecure permission is granted between
2408 the two SIDs, i.e. ahp returns 0. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002409 rc = avc_has_perm(&selinux_state,
2410 old_tsec->sid, new_tsec->sid,
Kees Cook62874c32017-07-18 15:25:25 -07002411 SECCLASS_PROCESS, PROCESS__NOATSECURE,
2412 NULL);
2413 bprm->secureexec |= !!rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 }
2415
Kees Cook62874c32017-07-18 15:25:25 -07002416 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417}
2418
Al Viroc3c073f2012-08-21 22:32:06 -04002419static int match_file(const void *p, struct file *file, unsigned fd)
2420{
2421 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2422}
2423
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002425static inline void flush_unauthorized_files(const struct cred *cred,
2426 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002429 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002430 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002431 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002433 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002435 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002436 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002437 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002438
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002440 Use file_path_has_perm on the tty path directly
2441 rather than using file_has_perm, as this particular
2442 open file may belong to another process and we are
2443 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002444 file_priv = list_first_entry(&tty->tty_files,
2445 struct tty_file_private, list);
2446 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002447 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002448 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 }
Peter Hurley4a510962016-01-09 21:35:23 -08002450 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002451 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002453 /* Reset controlling tty. */
2454 if (drop_tty)
2455 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002458 n = iterate_fd(files, 0, match_file, cred);
2459 if (!n) /* none found? */
2460 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
Al Viroc3c073f2012-08-21 22:32:06 -04002462 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002463 if (IS_ERR(devnull))
2464 devnull = NULL;
2465 /* replace all the matching ones with this */
2466 do {
2467 replace_fd(n - 1, devnull, 0);
2468 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2469 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002470 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471}
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473/*
David Howellsa6f76f22008-11-14 10:39:24 +11002474 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 */
David Howellsa6f76f22008-11-14 10:39:24 +11002476static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477{
David Howellsa6f76f22008-11-14 10:39:24 +11002478 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 int rc, i;
2481
David Howellsa6f76f22008-11-14 10:39:24 +11002482 new_tsec = bprm->cred->security;
2483 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 return;
2485
2486 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002487 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
David Howellsa6f76f22008-11-14 10:39:24 +11002489 /* Always clear parent death signal on SID transitions. */
2490 current->pdeath_signal = 0;
2491
2492 /* Check whether the new SID can inherit resource limits from the old
2493 * SID. If not, reset all soft limits to the lower of the current
2494 * task's hard limit and the init task's soft limit.
2495 *
2496 * Note that the setting of hard limits (even to lower them) can be
2497 * controlled by the setrlimit check. The inclusion of the init task's
2498 * soft limit into the computation is to avoid resetting soft limits
2499 * higher than the default soft limit for cases where the default is
2500 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2501 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002502 rc = avc_has_perm(&selinux_state,
2503 new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
David Howellsa6f76f22008-11-14 10:39:24 +11002504 PROCESS__RLIMITINH, NULL);
2505 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002506 /* protect against do_prlimit() */
2507 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002508 for (i = 0; i < RLIM_NLIMITS; i++) {
2509 rlim = current->signal->rlim + i;
2510 initrlim = init_task.signal->rlim + i;
2511 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2512 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002513 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002514 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2515 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002516 }
2517}
2518
2519/*
2520 * Clean up the process immediately after the installation of new credentials
2521 * due to exec
2522 */
2523static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2524{
2525 const struct task_security_struct *tsec = current_security();
2526 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002527 u32 osid, sid;
2528 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002529
David Howellsa6f76f22008-11-14 10:39:24 +11002530 osid = tsec->osid;
2531 sid = tsec->sid;
2532
2533 if (sid == osid)
2534 return;
2535
2536 /* Check whether the new SID can inherit signal state from the old SID.
2537 * If not, clear itimers to avoid subsequent signal generation and
2538 * flush and unblock signals.
2539 *
2540 * This must occur _after_ the task SID has been updated so that any
2541 * kill done after the flush will be checked against the new SID.
2542 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002543 rc = avc_has_perm(&selinux_state,
2544 osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 if (rc) {
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002546 if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
2547 memset(&itimer, 0, sizeof itimer);
2548 for (i = 0; i < 3; i++)
2549 do_setitimer(i, &itimer, NULL);
2550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002552 if (!fatal_signal_pending(current)) {
2553 flush_sigqueue(&current->pending);
2554 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002555 flush_signal_handlers(current, 1);
2556 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002557 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 spin_unlock_irq(&current->sighand->siglock);
2560 }
2561
David Howellsa6f76f22008-11-14 10:39:24 +11002562 /* Wake up the parent if it is waiting so that it can recheck
2563 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002564 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002565 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002566 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567}
2568
2569/* superblock security operations */
2570
2571static int selinux_sb_alloc_security(struct super_block *sb)
2572{
2573 return superblock_alloc_security(sb);
2574}
2575
2576static void selinux_sb_free_security(struct super_block *sb)
2577{
2578 superblock_free_security(sb);
2579}
2580
2581static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2582{
2583 if (plen > olen)
2584 return 0;
2585
2586 return !memcmp(prefix, option, plen);
2587}
2588
2589static inline int selinux_option(char *option, int len)
2590{
Eric Paris832cbd92008-04-01 13:24:09 -04002591 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2592 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2593 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002594 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2595 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596}
2597
2598static inline void take_option(char **to, char *from, int *first, int len)
2599{
2600 if (!*first) {
2601 **to = ',';
2602 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002603 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 *first = 0;
2605 memcpy(*to, from, len);
2606 *to += len;
2607}
2608
Eric Paris828dfe12008-04-17 13:17:49 -04002609static inline void take_selinux_option(char **to, char *from, int *first,
2610 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002611{
2612 int current_size = 0;
2613
2614 if (!*first) {
2615 **to = '|';
2616 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002617 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002618 *first = 0;
2619
2620 while (current_size < len) {
2621 if (*from != '"') {
2622 **to = *from;
2623 *to += 1;
2624 }
2625 from += 1;
2626 current_size += 1;
2627 }
2628}
2629
Eric Parise0007522008-03-05 10:31:54 -05002630static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
2632 int fnosec, fsec, rc = 0;
2633 char *in_save, *in_curr, *in_end;
2634 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002635 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 in_curr = orig;
2638 sec_curr = copy;
2639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2641 if (!nosec) {
2642 rc = -ENOMEM;
2643 goto out;
2644 }
2645
2646 nosec_save = nosec;
2647 fnosec = fsec = 1;
2648 in_save = in_end = orig;
2649
2650 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002651 if (*in_end == '"')
2652 open_quote = !open_quote;
2653 if ((*in_end == ',' && open_quote == 0) ||
2654 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 int len = in_end - in_curr;
2656
2657 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002658 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 else
2660 take_option(&nosec, in_curr, &fnosec, len);
2661
2662 in_curr = in_end + 1;
2663 }
2664 } while (*in_end++);
2665
Eric Paris6931dfc2005-06-30 02:58:51 -07002666 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002667 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668out:
2669 return rc;
2670}
2671
Al Viro204cc0c2018-12-13 13:41:47 -05002672static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
Al Viro5b400232018-12-12 20:13:29 -05002673{
2674 char *s = (char *)get_zeroed_page(GFP_KERNEL);
2675 int err;
2676
2677 if (!s)
2678 return -ENOMEM;
2679 err = selinux_sb_copy_data(options, s);
2680 if (!err)
Al Viro204cc0c2018-12-13 13:41:47 -05002681 err = selinux_parse_opts_str(s, mnt_opts);
Al Viro5b400232018-12-12 20:13:29 -05002682 free_page((unsigned long)s);
2683 return err;
2684}
2685
Al Viro204cc0c2018-12-13 13:41:47 -05002686static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002687{
Al Virobd323652018-12-13 15:04:59 -05002688 struct selinux_mnt_opts *opts = mnt_opts;
Eric Paris026eb162011-03-03 16:09:14 -05002689 struct superblock_security_struct *sbsec = sb->s_security;
Al Virobd323652018-12-13 15:04:59 -05002690 u32 sid;
2691 int rc;
Eric Paris026eb162011-03-03 16:09:14 -05002692
2693 if (!(sbsec->flags & SE_SBINITIALIZED))
2694 return 0;
2695
Al Viro204cc0c2018-12-13 13:41:47 -05002696 if (!opts)
2697 return 0;
2698
Al Virobd323652018-12-13 15:04:59 -05002699 if (opts->fscontext) {
2700 rc = parse_sid(sb, opts->fscontext, &sid);
2701 if (rc)
Al Viroc039bc32018-12-01 23:06:57 -05002702 return rc;
Al Virobd323652018-12-13 15:04:59 -05002703 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2704 goto out_bad_option;
2705 }
2706 if (opts->context) {
2707 rc = parse_sid(sb, opts->context, &sid);
2708 if (rc)
2709 return rc;
2710 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2711 goto out_bad_option;
2712 }
2713 if (opts->rootcontext) {
2714 struct inode_security_struct *root_isec;
2715 root_isec = backing_inode_security(sb->s_root);
2716 rc = parse_sid(sb, opts->rootcontext, &sid);
2717 if (rc)
2718 return rc;
2719 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2720 goto out_bad_option;
2721 }
2722 if (opts->defcontext) {
2723 rc = parse_sid(sb, opts->defcontext, &sid);
2724 if (rc)
2725 return rc;
2726 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2727 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002728 }
Al Viroc039bc32018-12-01 23:06:57 -05002729 return 0;
Eric Paris026eb162011-03-03 16:09:14 -05002730
Eric Paris026eb162011-03-03 16:09:14 -05002731out_bad_option:
peter enderborgc103a912018-06-12 10:09:03 +02002732 pr_warn("SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002733 "during remount (dev %s, type=%s)\n", sb->s_id,
2734 sb->s_type->name);
Al Viroc039bc32018-12-01 23:06:57 -05002735 return -EINVAL;
Eric Paris026eb162011-03-03 16:09:14 -05002736}
2737
Al Viroa10d7c22018-12-05 11:58:35 -05002738static int selinux_sb_kern_mount(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739{
David Howells88e67f32008-11-14 10:39:21 +11002740 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002741 struct common_audit_data ad;
James Morris74192242008-12-19 11:41:10 +11002742
Eric Paris50c205f2012-04-04 15:01:43 -04002743 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002744 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002745 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746}
2747
David Howells726c3342006-06-23 02:02:58 -07002748static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749{
David Howells88e67f32008-11-14 10:39:21 +11002750 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002751 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
Eric Paris50c205f2012-04-04 15:01:43 -04002753 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002754 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002755 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756}
2757
Al Viro808d4e32012-10-11 11:42:01 -04002758static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002759 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002760 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002761 unsigned long flags,
2762 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
David Howells88e67f32008-11-14 10:39:21 +11002764 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
2766 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002767 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002768 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 else
Eric Paris2875fa02011-04-28 16:04:24 -04002770 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771}
2772
2773static int selinux_umount(struct vfsmount *mnt, int flags)
2774{
David Howells88e67f32008-11-14 10:39:21 +11002775 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
David Howells88e67f32008-11-14 10:39:21 +11002777 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002778 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779}
2780
2781/* inode security operations */
2782
2783static int selinux_inode_alloc_security(struct inode *inode)
2784{
2785 return inode_alloc_security(inode);
2786}
2787
2788static void selinux_inode_free_security(struct inode *inode)
2789{
2790 inode_free_security(inode);
2791}
2792
David Quigleyd47be3d2013-05-22 12:50:34 -04002793static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002794 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002795 u32 *ctxlen)
2796{
David Quigleyd47be3d2013-05-22 12:50:34 -04002797 u32 newsid;
2798 int rc;
2799
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002800 rc = selinux_determine_inode_label(current_security(),
2801 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002802 inode_mode_to_security_class(mode),
2803 &newsid);
2804 if (rc)
2805 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002806
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002807 return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
2808 ctxlen);
David Quigleyd47be3d2013-05-22 12:50:34 -04002809}
2810
Vivek Goyala518b0a2016-07-13 10:44:53 -04002811static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2812 struct qstr *name,
2813 const struct cred *old,
2814 struct cred *new)
2815{
2816 u32 newsid;
2817 int rc;
2818 struct task_security_struct *tsec;
2819
2820 rc = selinux_determine_inode_label(old->security,
2821 d_inode(dentry->d_parent), name,
2822 inode_mode_to_security_class(mode),
2823 &newsid);
2824 if (rc)
2825 return rc;
2826
2827 tsec = new->security;
2828 tsec->create_sid = newsid;
2829 return 0;
2830}
2831
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002832static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002833 const struct qstr *qstr,
2834 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002835 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002836{
Paul Moore5fb49872010-04-22 14:46:19 -04002837 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002838 struct superblock_security_struct *sbsec;
Corentin LABBEc0d4f462017-10-04 20:32:17 +02002839 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002840 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002841 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002842
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002843 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002844
David Howells275bb412008-11-14 10:39:19 +11002845 newsid = tsec->create_sid;
2846
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002847 rc = selinux_determine_inode_label(current_security(),
David Howellsc3c188b2015-07-10 17:19:58 -04002848 dir, qstr,
2849 inode_mode_to_security_class(inode->i_mode),
2850 &newsid);
2851 if (rc)
2852 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002853
Eric Paris296fddf2006-09-25 23:32:00 -07002854 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002855 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002856 struct inode_security_struct *isec = inode->i_security;
2857 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2858 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002859 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002860 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002861
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002862 if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002863 return -EOPNOTSUPP;
2864
Tetsuo Handa95489062013-07-25 05:44:02 +09002865 if (name)
2866 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002867
2868 if (value && len) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002869 rc = security_sid_to_context_force(&selinux_state, newsid,
2870 &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002871 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002872 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002873 *value = context;
2874 *len = clen;
2875 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002876
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002877 return 0;
2878}
2879
Al Viro4acdaf22011-07-26 01:42:34 -04002880static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
2882 return may_create(dir, dentry, SECCLASS_FILE);
2883}
2884
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2886{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 return may_link(dir, old_dentry, MAY_LINK);
2888}
2889
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 return may_link(dir, dentry, MAY_UNLINK);
2893}
2894
2895static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2896{
2897 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2898}
2899
Al Viro18bb1db2011-07-26 01:41:39 -04002900static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901{
2902 return may_create(dir, dentry, SECCLASS_DIR);
2903}
2904
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2906{
2907 return may_link(dir, dentry, MAY_RMDIR);
2908}
2909
Al Viro1a67aaf2011-07-26 01:52:52 -04002910static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2913}
2914
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002916 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917{
2918 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2919}
2920
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921static int selinux_inode_readlink(struct dentry *dentry)
2922{
David Howells88e67f32008-11-14 10:39:21 +11002923 const struct cred *cred = current_cred();
2924
Eric Paris2875fa02011-04-28 16:04:24 -04002925 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926}
2927
NeilBrownbda0be72015-03-23 13:37:39 +11002928static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2929 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930{
David Howells88e67f32008-11-14 10:39:21 +11002931 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002932 struct common_audit_data ad;
2933 struct inode_security_struct *isec;
2934 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
NeilBrownbda0be72015-03-23 13:37:39 +11002936 validate_creds(cred);
2937
2938 ad.type = LSM_AUDIT_DATA_DENTRY;
2939 ad.u.dentry = dentry;
2940 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002941 isec = inode_security_rcu(inode, rcu);
2942 if (IS_ERR(isec))
2943 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002944
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002945 return avc_has_perm_flags(&selinux_state,
2946 sid, isec->sid, isec->sclass, FILE__READ, &ad,
NeilBrownbda0be72015-03-23 13:37:39 +11002947 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948}
2949
Eric Parisd4cf970d2012-04-04 15:01:42 -04002950static noinline int audit_inode_permission(struct inode *inode,
2951 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002952 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002953 unsigned flags)
2954{
2955 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002956 struct inode_security_struct *isec = inode->i_security;
2957 int rc;
2958
Eric Paris50c205f2012-04-04 15:01:43 -04002959 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002960 ad.u.inode = inode;
2961
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002962 rc = slow_avc_audit(&selinux_state,
2963 current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002964 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002965 if (rc)
2966 return rc;
2967 return 0;
2968}
2969
Al Viroe74f71e2011-06-20 19:38:15 -04002970static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971{
David Howells88e67f32008-11-14 10:39:21 +11002972 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002973 u32 perms;
2974 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002975 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002976 struct inode_security_struct *isec;
2977 u32 sid;
2978 struct av_decision avd;
2979 int rc, rc2;
2980 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Eric Parisb782e0a2010-07-23 11:44:03 -04002982 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002983 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2984
Eric Parisb782e0a2010-07-23 11:44:03 -04002985 /* No permission to check. Existence test. */
2986 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988
Eric Paris2e334052012-04-04 15:01:42 -04002989 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002990
Eric Paris2e334052012-04-04 15:01:42 -04002991 if (unlikely(IS_PRIVATE(inode)))
2992 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002993
2994 perms = file_mask_to_av(inode->i_mode, mask);
2995
Eric Paris2e334052012-04-04 15:01:42 -04002996 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002997 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
2998 if (IS_ERR(isec))
2999 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003000
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003001 rc = avc_has_perm_noaudit(&selinux_state,
3002 sid, isec->sid, isec->sclass, perms, 0, &avd);
Eric Paris2e334052012-04-04 15:01:42 -04003003 audited = avc_audit_required(perms, &avd, rc,
3004 from_access ? FILE__AUDIT_ACCESS : 0,
3005 &denied);
3006 if (likely(!audited))
3007 return rc;
3008
Stephen Smalley626b9742014-04-29 11:29:04 -07003009 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04003010 if (rc2)
3011 return rc2;
3012 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013}
3014
3015static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3016{
David Howells88e67f32008-11-14 10:39:21 +11003017 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003018 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003019 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003020 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003022 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3023 if (ia_valid & ATTR_FORCE) {
3024 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3025 ATTR_FORCE);
3026 if (!ia_valid)
3027 return 0;
3028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003030 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3031 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003032 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003034 if (selinux_policycap_openperm() &&
Stephen Smalleyccb54472017-05-12 12:41:24 -04003035 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3036 (ia_valid & ATTR_SIZE) &&
3037 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003038 av |= FILE__OPEN;
3039
3040 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041}
3042
Al Viro3f7036a2015-03-08 19:28:30 -04003043static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044{
Al Viro3f7036a2015-03-08 19:28:30 -04003045 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046}
3047
Stephen Smalleydb590002017-04-20 11:31:30 -04003048static bool has_cap_mac_admin(bool audit)
3049{
3050 const struct cred *cred = current_cred();
3051 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3052
3053 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3054 return false;
3055 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3056 return false;
3057 return true;
3058}
3059
David Howells8f0cfa52008-04-29 00:59:41 -07003060static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3061 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062{
David Howellsc6f493d2015-03-17 22:26:22 +00003063 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003064 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003066 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003067 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 int rc = 0;
3069
Eric W. Biederman6b240302017-10-02 09:38:20 -05003070 if (strcmp(name, XATTR_NAME_SELINUX)) {
3071 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3072 if (rc)
3073 return rc;
3074
3075 /* Not an attribute we recognize, so just check the
3076 ordinary setattr permission. */
3077 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
3080 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003081 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 return -EOPNOTSUPP;
3083
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003084 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 return -EPERM;
3086
Eric Paris50c205f2012-04-04 15:01:43 -04003087 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003088 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
Paul Moore20cdef82016-04-04 14:14:42 -04003090 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003091 rc = avc_has_perm(&selinux_state,
3092 sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 FILE__RELABELFROM, &ad);
3094 if (rc)
3095 return rc;
3096
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003097 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3098 GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003099 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003100 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003101 struct audit_buffer *ab;
3102 size_t audit_size;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003103
3104 /* We strip a nul only if it is at the end, otherwise the
3105 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003106 if (value) {
Colin Ian Kingadd24372017-10-14 13:46:55 +01003107 const char *str = value;
3108
Al Viroe3fea3f2012-06-09 08:15:16 +01003109 if (str[size - 1] == '\0')
3110 audit_size = size - 1;
3111 else
3112 audit_size = size;
3113 } else {
Al Viroe3fea3f2012-06-09 08:15:16 +01003114 audit_size = 0;
3115 }
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04003116 ab = audit_log_start(audit_context(),
3117 GFP_ATOMIC, AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04003118 audit_log_format(ab, "op=setxattr invalid_context=");
3119 audit_log_n_untrustedstring(ab, value, audit_size);
3120 audit_log_end(ab);
3121
Stephen Smalley12b29f32008-05-07 13:03:20 -04003122 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003123 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003124 rc = security_context_to_sid_force(&selinux_state, value,
3125 size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 if (rc)
3128 return rc;
3129
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003130 rc = avc_has_perm(&selinux_state,
3131 sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 FILE__RELABELTO, &ad);
3133 if (rc)
3134 return rc;
3135
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003136 rc = security_validate_transition(&selinux_state, isec->sid, newsid,
3137 sid, isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if (rc)
3139 return rc;
3140
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003141 return avc_has_perm(&selinux_state,
3142 newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 sbsec->sid,
3144 SECCLASS_FILESYSTEM,
3145 FILESYSTEM__ASSOCIATE,
3146 &ad);
3147}
3148
David Howells8f0cfa52008-04-29 00:59:41 -07003149static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003150 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003151 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152{
David Howellsc6f493d2015-03-17 22:26:22 +00003153 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003154 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 u32 newsid;
3156 int rc;
3157
3158 if (strcmp(name, XATTR_NAME_SELINUX)) {
3159 /* Not an attribute we recognize, so nothing to do. */
3160 return;
3161 }
3162
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003163 rc = security_context_to_sid_force(&selinux_state, value, size,
3164 &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +02003166 pr_err("SELinux: unable to map context to SID"
Stephen Smalley12b29f32008-05-07 13:03:20 -04003167 "for (%s, %lu), rc=%d\n",
3168 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 return;
3170 }
3171
Paul Moore20cdef82016-04-04 14:14:42 -04003172 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003173 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003174 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003176 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003177 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003178
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 return;
3180}
3181
David Howells8f0cfa52008-04-29 00:59:41 -07003182static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183{
David Howells88e67f32008-11-14 10:39:21 +11003184 const struct cred *cred = current_cred();
3185
Eric Paris2875fa02011-04-28 16:04:24 -04003186 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187}
3188
Eric Paris828dfe12008-04-17 13:17:49 -04003189static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190{
David Howells88e67f32008-11-14 10:39:21 +11003191 const struct cred *cred = current_cred();
3192
Eric Paris2875fa02011-04-28 16:04:24 -04003193 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194}
3195
David Howells8f0cfa52008-04-29 00:59:41 -07003196static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197{
Eric W. Biederman6b240302017-10-02 09:38:20 -05003198 if (strcmp(name, XATTR_NAME_SELINUX)) {
3199 int rc = cap_inode_removexattr(dentry, name);
3200 if (rc)
3201 return rc;
3202
3203 /* Not an attribute we recognize, so just check the
3204 ordinary setattr permission. */
3205 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207
3208 /* No one is allowed to remove a SELinux security label.
3209 You can change the label, but all data must be labeled. */
3210 return -EACCES;
3211}
3212
James Morrisd381d8a2005-10-30 14:59:22 -08003213/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003214 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003215 *
3216 * Permission check is handled by selinux_inode_getxattr hook.
3217 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003218static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219{
David P. Quigley42492592008-02-04 22:29:39 -08003220 u32 size;
3221 int error;
3222 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003223 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003225 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3226 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003228 /*
3229 * If the caller has CAP_MAC_ADMIN, then get the raw context
3230 * value even if it is not defined by current policy; otherwise,
3231 * use the in-core value under current policy.
3232 * Use the non-auditing forms of the permission checks since
3233 * getxattr may be called by unprivileged processes commonly
3234 * and lack of permission just means that we fall back to the
3235 * in-core context value, not a denial.
3236 */
Paul Moore20cdef82016-04-04 14:14:42 -04003237 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003238 if (has_cap_mac_admin(false))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003239 error = security_sid_to_context_force(&selinux_state,
3240 isec->sid, &context,
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003241 &size);
3242 else
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003243 error = security_sid_to_context(&selinux_state, isec->sid,
3244 &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003245 if (error)
3246 return error;
3247 error = size;
3248 if (alloc) {
3249 *buffer = context;
3250 goto out_nofree;
3251 }
3252 kfree(context);
3253out_nofree:
3254 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255}
3256
3257static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003258 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259{
Paul Moore2c971652016-04-19 16:36:28 -04003260 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 u32 newsid;
3262 int rc;
3263
3264 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3265 return -EOPNOTSUPP;
3266
3267 if (!value || !size)
3268 return -EACCES;
3269
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003270 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3271 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 if (rc)
3273 return rc;
3274
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003275 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003276 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003278 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003279 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 return 0;
3281}
3282
3283static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3284{
3285 const int len = sizeof(XATTR_NAME_SELINUX);
3286 if (buffer && len <= buffer_size)
3287 memcpy(buffer, XATTR_NAME_SELINUX, len);
3288 return len;
3289}
3290
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003291static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003292{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003293 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003294 *secid = isec->sid;
3295}
3296
Vivek Goyal56909eb2016-07-13 10:44:48 -04003297static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3298{
3299 u32 sid;
3300 struct task_security_struct *tsec;
3301 struct cred *new_creds = *new;
3302
3303 if (new_creds == NULL) {
3304 new_creds = prepare_creds();
3305 if (!new_creds)
3306 return -ENOMEM;
3307 }
3308
3309 tsec = new_creds->security;
3310 /* Get label from overlay inode and set it in create_sid */
3311 selinux_inode_getsecid(d_inode(src), &sid);
3312 tsec->create_sid = sid;
3313 *new = new_creds;
3314 return 0;
3315}
3316
Vivek Goyal19472b62016-07-13 10:44:50 -04003317static int selinux_inode_copy_up_xattr(const char *name)
3318{
3319 /* The copy_up hook above sets the initial context on an inode, but we
3320 * don't then want to overwrite it by blindly copying all the lower
3321 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3322 */
3323 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3324 return 1; /* Discard */
3325 /*
3326 * Any other attribute apart from SELINUX is not claimed, supported
3327 * by selinux.
3328 */
3329 return -EOPNOTSUPP;
3330}
3331
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332/* file security operations */
3333
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003334static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335{
David Howells88e67f32008-11-14 10:39:21 +11003336 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003337 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3340 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3341 mask |= MAY_APPEND;
3342
Paul Moore389fb8002009-03-27 17:10:34 -04003343 return file_has_perm(cred, file,
3344 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345}
3346
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003347static int selinux_file_permission(struct file *file, int mask)
3348{
Al Viro496ad9a2013-01-23 17:07:38 -05003349 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003350 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003351 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003352 u32 sid = current_sid();
3353
Paul Moore389fb8002009-03-27 17:10:34 -04003354 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003355 /* No permission to check. Existence test. */
3356 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003357
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003358 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003359 if (sid == fsec->sid && fsec->isid == isec->sid &&
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003360 fsec->pseqno == avc_policy_seqno(&selinux_state))
Eric Paris83d49852012-04-04 13:45:40 -04003361 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003362 return 0;
3363
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003364 return selinux_revalidate_file_permission(file, mask);
3365}
3366
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367static int selinux_file_alloc_security(struct file *file)
3368{
3369 return file_alloc_security(file);
3370}
3371
3372static void selinux_file_free_security(struct file *file)
3373{
3374 file_free_security(file);
3375}
3376
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003377/*
3378 * Check whether a task has the ioctl permission and cmd
3379 * operation to an inode.
3380 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003381static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003382 u32 requested, u16 cmd)
3383{
3384 struct common_audit_data ad;
3385 struct file_security_struct *fsec = file->f_security;
3386 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003387 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003388 struct lsm_ioctlop_audit ioctl;
3389 u32 ssid = cred_sid(cred);
3390 int rc;
3391 u8 driver = cmd >> 8;
3392 u8 xperm = cmd & 0xff;
3393
3394 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3395 ad.u.op = &ioctl;
3396 ad.u.op->cmd = cmd;
3397 ad.u.op->path = file->f_path;
3398
3399 if (ssid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003400 rc = avc_has_perm(&selinux_state,
3401 ssid, fsec->sid,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003402 SECCLASS_FD,
3403 FD__USE,
3404 &ad);
3405 if (rc)
3406 goto out;
3407 }
3408
3409 if (unlikely(IS_PRIVATE(inode)))
3410 return 0;
3411
Paul Moore20cdef82016-04-04 14:14:42 -04003412 isec = inode_security(inode);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003413 rc = avc_has_extended_perms(&selinux_state,
3414 ssid, isec->sid, isec->sclass,
3415 requested, driver, xperm, &ad);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003416out:
3417 return rc;
3418}
3419
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3421 unsigned long arg)
3422{
David Howells88e67f32008-11-14 10:39:21 +11003423 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003424 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Eric Paris0b24dcb2011-02-25 15:39:20 -05003426 switch (cmd) {
3427 case FIONREAD:
3428 /* fall through */
3429 case FIBMAP:
3430 /* fall through */
3431 case FIGETBSZ:
3432 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003433 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003434 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003435 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003436 error = file_has_perm(cred, file, FILE__GETATTR);
3437 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Al Viro2f99c362012-03-23 16:04:05 -04003439 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003440 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003441 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003442 error = file_has_perm(cred, file, FILE__SETATTR);
3443 break;
3444
3445 /* sys_ioctl() checks */
3446 case FIONBIO:
3447 /* fall through */
3448 case FIOASYNC:
3449 error = file_has_perm(cred, file, 0);
3450 break;
3451
3452 case KDSKBENT:
3453 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003454 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003455 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003456 break;
3457
3458 /* default case assumes that the command will go
3459 * to the file's ioctl() function.
3460 */
3461 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003462 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003463 }
3464 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465}
3466
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003467static int default_noexec;
3468
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3470{
David Howells88e67f32008-11-14 10:39:21 +11003471 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003472 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003473 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003474
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003475 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003476 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3477 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 /*
3479 * We are making executable an anonymous mapping or a
3480 * private file mapping that will also be writable.
3481 * This has an additional check.
3482 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003483 rc = avc_has_perm(&selinux_state,
3484 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003485 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003487 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
3490 if (file) {
3491 /* read access is always possible with a mapping */
3492 u32 av = FILE__READ;
3493
3494 /* write access only matters if the mapping is shared */
3495 if (shared && (prot & PROT_WRITE))
3496 av |= FILE__WRITE;
3497
3498 if (prot & PROT_EXEC)
3499 av |= FILE__EXECUTE;
3500
David Howells88e67f32008-11-14 10:39:21 +11003501 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 }
David Howellsd84f4f92008-11-14 10:39:23 +11003503
3504error:
3505 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
Al Viroe5467852012-05-30 13:30:51 -04003508static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003510 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003511
3512 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3513 u32 sid = current_sid();
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003514 rc = avc_has_perm(&selinux_state,
3515 sid, sid, SECCLASS_MEMPROTECT,
Paul Moore98883bf2014-03-19 16:46:11 -04003516 MEMPROTECT__MMAP_ZERO, NULL);
3517 }
3518
3519 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003520}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
Al Viroe5467852012-05-30 13:30:51 -04003522static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3523 unsigned long prot, unsigned long flags)
3524{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003525 struct common_audit_data ad;
3526 int rc;
3527
3528 if (file) {
3529 ad.type = LSM_AUDIT_DATA_FILE;
3530 ad.u.file = file;
3531 rc = inode_has_perm(current_cred(), file_inode(file),
3532 FILE__MAP, &ad);
3533 if (rc)
3534 return rc;
3535 }
3536
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003537 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 prot = reqprot;
3539
3540 return file_map_prot_check(file, prot,
3541 (flags & MAP_TYPE) == MAP_SHARED);
3542}
3543
3544static int selinux_file_mprotect(struct vm_area_struct *vma,
3545 unsigned long reqprot,
3546 unsigned long prot)
3547{
David Howells88e67f32008-11-14 10:39:21 +11003548 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003549 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003551 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 prot = reqprot;
3553
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003554 if (default_noexec &&
3555 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003556 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003557 if (vma->vm_start >= vma->vm_mm->start_brk &&
3558 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003559 rc = avc_has_perm(&selinux_state,
3560 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003561 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003562 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003563 ((vma->vm_start <= vma->vm_mm->start_stack &&
3564 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003565 vma_is_stack_for_current(vma))) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003566 rc = avc_has_perm(&selinux_state,
3567 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003568 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003569 } else if (vma->vm_file && vma->anon_vma) {
3570 /*
3571 * We are making executable a file mapping that has
3572 * had some COW done. Since pages might have been
3573 * written, check ability to execute the possibly
3574 * modified content. This typically should only
3575 * occur for text relocations.
3576 */
David Howellsd84f4f92008-11-14 10:39:23 +11003577 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003578 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003579 if (rc)
3580 return rc;
3581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
3583 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3584}
3585
3586static int selinux_file_lock(struct file *file, unsigned int cmd)
3587{
David Howells88e67f32008-11-14 10:39:21 +11003588 const struct cred *cred = current_cred();
3589
3590 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591}
3592
3593static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3594 unsigned long arg)
3595{
David Howells88e67f32008-11-14 10:39:21 +11003596 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 int err = 0;
3598
3599 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003600 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003601 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003602 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003604 }
3605 /* fall through */
3606 case F_SETOWN:
3607 case F_SETSIG:
3608 case F_GETFL:
3609 case F_GETOWN:
3610 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003611 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003612 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003613 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003614 break;
3615 case F_GETLK:
3616 case F_SETLK:
3617 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003618 case F_OFD_GETLK:
3619 case F_OFD_SETLK:
3620 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003622 case F_GETLK64:
3623 case F_SETLK64:
3624 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625#endif
David Howells88e67f32008-11-14 10:39:21 +11003626 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003627 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 }
3629
3630 return err;
3631}
3632
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003633static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 struct file_security_struct *fsec;
3636
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003638 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639}
3640
3641static int selinux_file_send_sigiotask(struct task_struct *tsk,
3642 struct fown_struct *fown, int signum)
3643{
Eric Paris828dfe12008-04-17 13:17:49 -04003644 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003645 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 struct file_security_struct *fsec;
3648
3649 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003650 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 fsec = file->f_security;
3653
3654 if (!signum)
3655 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3656 else
3657 perm = signal_to_av(signum);
3658
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003659 return avc_has_perm(&selinux_state,
3660 fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 SECCLASS_PROCESS, perm, NULL);
3662}
3663
3664static int selinux_file_receive(struct file *file)
3665{
David Howells88e67f32008-11-14 10:39:21 +11003666 const struct cred *cred = current_cred();
3667
3668 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669}
3670
Al Viro94817692018-07-10 14:13:18 -04003671static int selinux_file_open(struct file *file)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003672{
3673 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003674 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003675
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003676 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003677 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003678 /*
3679 * Save inode label and policy sequence number
3680 * at open-time so that selinux_file_permission
3681 * can determine whether revalidation is necessary.
3682 * Task label is already saved in the file security
3683 * struct as its SID.
3684 */
3685 fsec->isid = isec->sid;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003686 fsec->pseqno = avc_policy_seqno(&selinux_state);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003687 /*
3688 * Since the inode label or policy seqno may have changed
3689 * between the selinux_inode_permission check and the saving
3690 * of state above, recheck that access is still permitted.
3691 * Otherwise, access might never be revalidated against the
3692 * new inode label or new policy.
3693 * This check is not redundant - do not remove.
3694 */
Al Viro94817692018-07-10 14:13:18 -04003695 return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003696}
3697
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698/* task security operations */
3699
Tetsuo Handaa79be232017-03-28 23:08:45 +09003700static int selinux_task_alloc(struct task_struct *task,
3701 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003703 u32 sid = current_sid();
3704
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003705 return avc_has_perm(&selinux_state,
3706 sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707}
3708
David Howellsf1752ee2008-11-14 10:39:17 +11003709/*
David Howellsee18d642009-09-02 09:14:21 +01003710 * allocate the SELinux part of blank credentials
3711 */
3712static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3713{
3714 struct task_security_struct *tsec;
3715
3716 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3717 if (!tsec)
3718 return -ENOMEM;
3719
3720 cred->security = tsec;
3721 return 0;
3722}
3723
3724/*
David Howellsf1752ee2008-11-14 10:39:17 +11003725 * detach and free the LSM part of a set of credentials
3726 */
3727static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728{
David Howellsf1752ee2008-11-14 10:39:17 +11003729 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003730
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003731 /*
3732 * cred->security == NULL if security_cred_alloc_blank() or
3733 * security_prepare_creds() returned an error.
3734 */
3735 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003736 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003737 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738}
3739
David Howellsd84f4f92008-11-14 10:39:23 +11003740/*
3741 * prepare a new set of credentials for modification
3742 */
3743static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3744 gfp_t gfp)
3745{
3746 const struct task_security_struct *old_tsec;
3747 struct task_security_struct *tsec;
3748
3749 old_tsec = old->security;
3750
3751 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3752 if (!tsec)
3753 return -ENOMEM;
3754
3755 new->security = tsec;
3756 return 0;
3757}
3758
3759/*
David Howellsee18d642009-09-02 09:14:21 +01003760 * transfer the SELinux data to a blank set of creds
3761 */
3762static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3763{
3764 const struct task_security_struct *old_tsec = old->security;
3765 struct task_security_struct *tsec = new->security;
3766
3767 *tsec = *old_tsec;
3768}
3769
Matthew Garrett3ec30112018-01-08 13:36:19 -08003770static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3771{
3772 *secid = cred_sid(c);
3773}
3774
David Howellsee18d642009-09-02 09:14:21 +01003775/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003776 * set the security data for a kernel service
3777 * - all the creation contexts are set to unlabelled
3778 */
3779static int selinux_kernel_act_as(struct cred *new, u32 secid)
3780{
3781 struct task_security_struct *tsec = new->security;
3782 u32 sid = current_sid();
3783 int ret;
3784
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003785 ret = avc_has_perm(&selinux_state,
3786 sid, secid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003787 SECCLASS_KERNEL_SERVICE,
3788 KERNEL_SERVICE__USE_AS_OVERRIDE,
3789 NULL);
3790 if (ret == 0) {
3791 tsec->sid = secid;
3792 tsec->create_sid = 0;
3793 tsec->keycreate_sid = 0;
3794 tsec->sockcreate_sid = 0;
3795 }
3796 return ret;
3797}
3798
3799/*
3800 * set the file creation context in a security record to the same as the
3801 * objective context of the specified inode
3802 */
3803static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3804{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003805 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003806 struct task_security_struct *tsec = new->security;
3807 u32 sid = current_sid();
3808 int ret;
3809
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003810 ret = avc_has_perm(&selinux_state,
3811 sid, isec->sid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003812 SECCLASS_KERNEL_SERVICE,
3813 KERNEL_SERVICE__CREATE_FILES_AS,
3814 NULL);
3815
3816 if (ret == 0)
3817 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003818 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003819}
3820
Eric Parisdd8dbf22009-11-03 16:35:32 +11003821static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003822{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003823 struct common_audit_data ad;
3824
Eric Paris50c205f2012-04-04 15:01:43 -04003825 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003826 ad.u.kmod_name = kmod_name;
3827
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003828 return avc_has_perm(&selinux_state,
3829 current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11003830 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003831}
3832
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003833static int selinux_kernel_module_from_file(struct file *file)
3834{
3835 struct common_audit_data ad;
3836 struct inode_security_struct *isec;
3837 struct file_security_struct *fsec;
3838 u32 sid = current_sid();
3839 int rc;
3840
3841 /* init_module */
3842 if (file == NULL)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003843 return avc_has_perm(&selinux_state,
3844 sid, sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003845 SYSTEM__MODULE_LOAD, NULL);
3846
3847 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003848
Vivek Goyal43af5de2016-09-09 11:37:49 -04003849 ad.type = LSM_AUDIT_DATA_FILE;
3850 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003851
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003852 fsec = file->f_security;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003853 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003854 rc = avc_has_perm(&selinux_state,
3855 sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003856 if (rc)
3857 return rc;
3858 }
3859
Paul Moore20cdef82016-04-04 14:14:42 -04003860 isec = inode_security(file_inode(file));
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003861 return avc_has_perm(&selinux_state,
3862 sid, isec->sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003863 SYSTEM__MODULE_LOAD, &ad);
3864}
3865
3866static int selinux_kernel_read_file(struct file *file,
3867 enum kernel_read_file_id id)
3868{
3869 int rc = 0;
3870
3871 switch (id) {
3872 case READING_MODULE:
3873 rc = selinux_kernel_module_from_file(file);
3874 break;
3875 default:
3876 break;
3877 }
3878
3879 return rc;
3880}
3881
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04003882static int selinux_kernel_load_data(enum kernel_load_data_id id)
3883{
3884 int rc = 0;
3885
3886 switch (id) {
3887 case LOADING_MODULE:
3888 rc = selinux_kernel_module_from_file(NULL);
3889 default:
3890 break;
3891 }
3892
3893 return rc;
3894}
3895
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3897{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003898 return avc_has_perm(&selinux_state,
3899 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003900 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901}
3902
3903static int selinux_task_getpgid(struct task_struct *p)
3904{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003905 return avc_has_perm(&selinux_state,
3906 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003907 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908}
3909
3910static int selinux_task_getsid(struct task_struct *p)
3911{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003912 return avc_has_perm(&selinux_state,
3913 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003914 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915}
3916
David Quigleyf9008e4c2006-06-30 01:55:46 -07003917static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3918{
David Howells275bb412008-11-14 10:39:19 +11003919 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003920}
3921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922static int selinux_task_setnice(struct task_struct *p, int nice)
3923{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003924 return avc_has_perm(&selinux_state,
3925 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003926 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927}
3928
James Morris03e68062006-06-23 02:03:58 -07003929static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3930{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003931 return avc_has_perm(&selinux_state,
3932 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003933 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07003934}
3935
David Quigleya1836a42006-06-30 01:55:49 -07003936static int selinux_task_getioprio(struct task_struct *p)
3937{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003938 return avc_has_perm(&selinux_state,
3939 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003940 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07003941}
3942
Corentin LABBE42985552017-10-04 20:32:18 +02003943static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
3944 unsigned int flags)
Stephen Smalley791ec492017-02-17 07:57:00 -05003945{
3946 u32 av = 0;
3947
Stephen Smalley84e68852017-02-28 09:35:08 -05003948 if (!flags)
3949 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05003950 if (flags & LSM_PRLIMIT_WRITE)
3951 av |= PROCESS__SETRLIMIT;
3952 if (flags & LSM_PRLIMIT_READ)
3953 av |= PROCESS__GETRLIMIT;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003954 return avc_has_perm(&selinux_state,
3955 cred_sid(cred), cred_sid(tcred),
Stephen Smalley791ec492017-02-17 07:57:00 -05003956 SECCLASS_PROCESS, av, NULL);
3957}
3958
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003959static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3960 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003962 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
3964 /* Control the ability to change the hard limit (whether
3965 lowering or raising it), so that the hard limit can
3966 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003967 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003969 return avc_has_perm(&selinux_state,
3970 current_sid(), task_sid(p),
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003971 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 return 0;
3974}
3975
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003976static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003978 return avc_has_perm(&selinux_state,
3979 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003980 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981}
3982
3983static int selinux_task_getscheduler(struct task_struct *p)
3984{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003985 return avc_has_perm(&selinux_state,
3986 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003987 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988}
3989
David Quigley35601542006-06-23 02:04:01 -07003990static int selinux_task_movememory(struct task_struct *p)
3991{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003992 return avc_has_perm(&selinux_state,
3993 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003994 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07003995}
3996
Eric W. Biedermanae7795b2018-09-25 11:27:20 +02003997static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04003998 int sig, const struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999{
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004000 u32 secid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 if (!sig)
4004 perm = PROCESS__SIGNULL; /* null signal; existence test */
4005 else
4006 perm = signal_to_av(sig);
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004007 if (!cred)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004008 secid = current_sid();
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04004009 else
4010 secid = cred_sid(cred);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004011 return avc_has_perm(&selinux_state,
4012 secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013}
4014
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015static void selinux_task_to_inode(struct task_struct *p,
4016 struct inode *inode)
4017{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11004019 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004021 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004022 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004023 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004024 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004025 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026}
4027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004029static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004030 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031{
4032 int offset, ihlen, ret = -EINVAL;
4033 struct iphdr _iph, *ih;
4034
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004035 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4037 if (ih == NULL)
4038 goto out;
4039
4040 ihlen = ih->ihl * 4;
4041 if (ihlen < sizeof(_iph))
4042 goto out;
4043
Eric Paris48c62af2012-04-02 13:15:44 -04004044 ad->u.net->v4info.saddr = ih->saddr;
4045 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 ret = 0;
4047
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004048 if (proto)
4049 *proto = ih->protocol;
4050
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004052 case IPPROTO_TCP: {
4053 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Eric Paris828dfe12008-04-17 13:17:49 -04004055 if (ntohs(ih->frag_off) & IP_OFFSET)
4056 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
4058 offset += ihlen;
4059 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4060 if (th == NULL)
4061 break;
4062
Eric Paris48c62af2012-04-02 13:15:44 -04004063 ad->u.net->sport = th->source;
4064 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Eric Paris828dfe12008-04-17 13:17:49 -04004068 case IPPROTO_UDP: {
4069 struct udphdr _udph, *uh;
4070
4071 if (ntohs(ih->frag_off) & IP_OFFSET)
4072 break;
4073
4074 offset += ihlen;
4075 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4076 if (uh == NULL)
4077 break;
4078
Eric Paris48c62af2012-04-02 13:15:44 -04004079 ad->u.net->sport = uh->source;
4080 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004081 break;
4082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
James Morris2ee92d42006-11-13 16:09:01 -08004084 case IPPROTO_DCCP: {
4085 struct dccp_hdr _dccph, *dh;
4086
4087 if (ntohs(ih->frag_off) & IP_OFFSET)
4088 break;
4089
4090 offset += ihlen;
4091 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4092 if (dh == NULL)
4093 break;
4094
Eric Paris48c62af2012-04-02 13:15:44 -04004095 ad->u.net->sport = dh->dccph_sport;
4096 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004097 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004098 }
James Morris2ee92d42006-11-13 16:09:01 -08004099
Richard Hainesd4529302018-02-13 20:57:18 +00004100#if IS_ENABLED(CONFIG_IP_SCTP)
4101 case IPPROTO_SCTP: {
4102 struct sctphdr _sctph, *sh;
4103
4104 if (ntohs(ih->frag_off) & IP_OFFSET)
4105 break;
4106
4107 offset += ihlen;
4108 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4109 if (sh == NULL)
4110 break;
4111
4112 ad->u.net->sport = sh->source;
4113 ad->u.net->dport = sh->dest;
4114 break;
4115 }
4116#endif
Eric Paris828dfe12008-04-17 13:17:49 -04004117 default:
4118 break;
4119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120out:
4121 return ret;
4122}
4123
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004124#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
4126/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004127static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004128 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129{
4130 u8 nexthdr;
4131 int ret = -EINVAL, offset;
4132 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004133 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004135 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4137 if (ip6 == NULL)
4138 goto out;
4139
Eric Paris48c62af2012-04-02 13:15:44 -04004140 ad->u.net->v6info.saddr = ip6->saddr;
4141 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 ret = 0;
4143
4144 nexthdr = ip6->nexthdr;
4145 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004146 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 if (offset < 0)
4148 goto out;
4149
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004150 if (proto)
4151 *proto = nexthdr;
4152
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 switch (nexthdr) {
4154 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004155 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
4157 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4158 if (th == NULL)
4159 break;
4160
Eric Paris48c62af2012-04-02 13:15:44 -04004161 ad->u.net->sport = th->source;
4162 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 break;
4164 }
4165
4166 case IPPROTO_UDP: {
4167 struct udphdr _udph, *uh;
4168
4169 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4170 if (uh == NULL)
4171 break;
4172
Eric Paris48c62af2012-04-02 13:15:44 -04004173 ad->u.net->sport = uh->source;
4174 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 break;
4176 }
4177
James Morris2ee92d42006-11-13 16:09:01 -08004178 case IPPROTO_DCCP: {
4179 struct dccp_hdr _dccph, *dh;
4180
4181 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4182 if (dh == NULL)
4183 break;
4184
Eric Paris48c62af2012-04-02 13:15:44 -04004185 ad->u.net->sport = dh->dccph_sport;
4186 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004187 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004188 }
James Morris2ee92d42006-11-13 16:09:01 -08004189
Richard Hainesd4529302018-02-13 20:57:18 +00004190#if IS_ENABLED(CONFIG_IP_SCTP)
4191 case IPPROTO_SCTP: {
4192 struct sctphdr _sctph, *sh;
4193
4194 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4195 if (sh == NULL)
4196 break;
4197
4198 ad->u.net->sport = sh->source;
4199 ad->u.net->dport = sh->dest;
4200 break;
4201 }
4202#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 /* includes fragments */
4204 default:
4205 break;
4206 }
4207out:
4208 return ret;
4209}
4210
4211#endif /* IPV6 */
4212
Thomas Liu2bf49692009-07-14 12:14:09 -04004213static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004214 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215{
David Howellscf9481e2008-07-27 21:31:07 +10004216 char *addrp;
4217 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
Eric Paris48c62af2012-04-02 13:15:44 -04004219 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004221 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004222 if (ret)
4223 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004224 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4225 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004226 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004228#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004230 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004231 if (ret)
4232 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004233 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4234 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004235 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236#endif /* IPV6 */
4237 default:
David Howellscf9481e2008-07-27 21:31:07 +10004238 addrp = NULL;
4239 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240 }
4241
David Howellscf9481e2008-07-27 21:31:07 +10004242parse_error:
peter enderborgc103a912018-06-12 10:09:03 +02004243 pr_warn(
David Howellscf9481e2008-07-27 21:31:07 +10004244 "SELinux: failure in selinux_parse_skb(),"
4245 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004247
4248okay:
4249 if (_addrp)
4250 *_addrp = addrp;
4251 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252}
4253
Paul Moore4f6a9932007-03-01 14:35:22 -05004254/**
Paul Moore220deb92008-01-29 08:38:23 -05004255 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004256 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004257 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004258 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004259 *
4260 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004261 * Check the various different forms of network peer labeling and determine
4262 * the peer label/SID for the packet; most of the magic actually occurs in
4263 * the security server function security_net_peersid_cmp(). The function
4264 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4265 * or -EACCES if @sid is invalid due to inconsistencies with the different
4266 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004267 *
4268 */
Paul Moore220deb92008-01-29 08:38:23 -05004269static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004270{
Paul Moore71f1cb02008-01-29 08:51:16 -05004271 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004272 u32 xfrm_sid;
4273 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004274 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004275
Paul Moore817eff72013-12-10 14:57:54 -05004276 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004277 if (unlikely(err))
4278 return -EACCES;
4279 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4280 if (unlikely(err))
4281 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004282
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004283 err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
4284 nlbl_type, xfrm_sid, sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004285 if (unlikely(err)) {
peter enderborgc103a912018-06-12 10:09:03 +02004286 pr_warn(
Paul Moore71f1cb02008-01-29 08:51:16 -05004287 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4288 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004289 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004290 }
Paul Moore220deb92008-01-29 08:38:23 -05004291
4292 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004293}
4294
Paul Moore446b8022013-12-04 16:10:51 -05004295/**
4296 * selinux_conn_sid - Determine the child socket label for a connection
4297 * @sk_sid: the parent socket's SID
4298 * @skb_sid: the packet's SID
4299 * @conn_sid: the resulting connection SID
4300 *
4301 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4302 * combined with the MLS information from @skb_sid in order to create
4303 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4304 * of @sk_sid. Returns zero on success, negative values on failure.
4305 *
4306 */
4307static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4308{
4309 int err = 0;
4310
4311 if (skb_sid != SECSID_NULL)
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004312 err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
4313 conn_sid);
Paul Moore446b8022013-12-04 16:10:51 -05004314 else
4315 *conn_sid = sk_sid;
4316
4317 return err;
4318}
4319
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004321
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004322static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4323 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004324{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004325 if (tsec->sockcreate_sid > SECSID_NULL) {
4326 *socksid = tsec->sockcreate_sid;
4327 return 0;
4328 }
4329
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004330 return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
4331 secclass, NULL, socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004332}
4333
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004334static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335{
Paul Moore253bfae2010-04-22 14:46:19 -04004336 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004337 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004338 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
Paul Moore253bfae2010-04-22 14:46:19 -04004340 if (sksec->sid == SECINITSID_KERNEL)
4341 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Eric Paris50c205f2012-04-04 15:01:43 -04004343 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004344 ad.u.net = &net;
4345 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004347 return avc_has_perm(&selinux_state,
4348 current_sid(), sksec->sid, sksec->sclass, perms,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004349 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350}
4351
4352static int selinux_socket_create(int family, int type,
4353 int protocol, int kern)
4354{
Paul Moore5fb49872010-04-22 14:46:19 -04004355 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004356 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004357 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004358 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
4360 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004361 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
David Howells275bb412008-11-14 10:39:19 +11004363 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004364 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4365 if (rc)
4366 return rc;
4367
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004368 return avc_has_perm(&selinux_state,
4369 tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370}
4371
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004372static int selinux_socket_post_create(struct socket *sock, int family,
4373 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374{
Paul Moore5fb49872010-04-22 14:46:19 -04004375 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004376 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004377 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004378 u16 sclass = socket_type_to_security_class(family, type, protocol);
4379 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004380 int err = 0;
4381
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004382 if (!kern) {
4383 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004384 if (err)
4385 return err;
4386 }
David Howells275bb412008-11-14 10:39:19 +11004387
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004388 isec->sclass = sclass;
4389 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004390 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004392 if (sock->sk) {
4393 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004394 sksec->sclass = sclass;
4395 sksec->sid = sid;
Richard Hainesd4529302018-02-13 20:57:18 +00004396 /* Allows detection of the first association on this socket */
4397 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4398 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4399
Paul Moore389fb8002009-03-27 17:10:34 -04004400 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004401 }
4402
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004403 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404}
4405
David Herrmann0b811db2018-05-04 16:28:21 +02004406static int selinux_socket_socketpair(struct socket *socka,
4407 struct socket *sockb)
4408{
4409 struct sk_security_struct *sksec_a = socka->sk->sk_security;
4410 struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4411
4412 sksec_a->peer_sid = sksec_b->sid;
4413 sksec_b->peer_sid = sksec_a->sid;
4414
4415 return 0;
4416}
4417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418/* Range of port numbers used to automatically bind.
4419 Need to determine whether we should perform a name_bind
4420 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
4422static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4423{
Paul Moore253bfae2010-04-22 14:46:19 -04004424 struct sock *sk = sock->sk;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004425 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 u16 family;
4427 int err;
4428
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004429 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 if (err)
4431 goto out;
4432
Richard Hainesd4529302018-02-13 20:57:18 +00004433 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
Paul Moore253bfae2010-04-22 14:46:19 -04004434 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 if (family == PF_INET || family == PF_INET6) {
4436 char *addrp;
Thomas Liu2bf49692009-07-14 12:14:09 -04004437 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004438 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 struct sockaddr_in *addr4 = NULL;
4440 struct sockaddr_in6 *addr6 = NULL;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004441 u16 family_sa = address->sa_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004443 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Richard Hainesd4529302018-02-13 20:57:18 +00004445 /*
4446 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4447 * that validates multiple binding addresses. Because of this
4448 * need to check address->sa_family as it is possible to have
4449 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4450 */
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004451 switch (family_sa) {
4452 case AF_UNSPEC:
Richard Haines68741a8a2018-03-02 19:54:34 +00004453 case AF_INET:
4454 if (addrlen < sizeof(struct sockaddr_in))
4455 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 addr4 = (struct sockaddr_in *)address;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004457 if (family_sa == AF_UNSPEC) {
4458 /* see __inet_bind(), we only want to allow
4459 * AF_UNSPEC if the address is INADDR_ANY
4460 */
4461 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4462 goto err_af;
4463 family_sa = AF_INET;
4464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 addrp = (char *)&addr4->sin_addr.s_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004467 break;
4468 case AF_INET6:
4469 if (addrlen < SIN6_LEN_RFC2133)
4470 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 addr6 = (struct sockaddr_in6 *)address;
4472 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473 addrp = (char *)&addr6->sin6_addr.s6_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004474 break;
4475 default:
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004476 goto err_af;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 }
4478
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004479 ad.type = LSM_AUDIT_DATA_NET;
4480 ad.u.net = &net;
4481 ad.u.net->sport = htons(snum);
4482 ad.u.net->family = family_sa;
4483
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004484 if (snum) {
4485 int low, high;
4486
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004487 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004488
Krister Johansen4548b682017-01-20 17:49:11 -08004489 if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
4490 snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004491 err = sel_netport_sid(sk->sk_protocol,
4492 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004493 if (err)
4494 goto out;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004495 err = avc_has_perm(&selinux_state,
4496 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004497 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004498 SOCKET__NAME_BIND, &ad);
4499 if (err)
4500 goto out;
4501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502 }
Eric Paris828dfe12008-04-17 13:17:49 -04004503
Paul Moore253bfae2010-04-22 14:46:19 -04004504 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004505 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 node_perm = TCP_SOCKET__NODE_BIND;
4507 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004508
James Morris13402582005-09-30 14:24:34 -04004509 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 node_perm = UDP_SOCKET__NODE_BIND;
4511 break;
James Morris2ee92d42006-11-13 16:09:01 -08004512
4513 case SECCLASS_DCCP_SOCKET:
4514 node_perm = DCCP_SOCKET__NODE_BIND;
4515 break;
4516
Richard Hainesd4529302018-02-13 20:57:18 +00004517 case SECCLASS_SCTP_SOCKET:
4518 node_perm = SCTP_SOCKET__NODE_BIND;
4519 break;
4520
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 default:
4522 node_perm = RAWIP_SOCKET__NODE_BIND;
4523 break;
4524 }
Eric Paris828dfe12008-04-17 13:17:49 -04004525
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004526 err = sel_netnode_sid(addrp, family_sa, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 if (err)
4528 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004529
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004530 if (family_sa == AF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004531 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 else
Eric Paris48c62af2012-04-02 13:15:44 -04004533 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004535 err = avc_has_perm(&selinux_state,
4536 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004537 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 if (err)
4539 goto out;
4540 }
4541out:
4542 return err;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004543err_af:
4544 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4545 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4546 return -EINVAL;
4547 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548}
4549
Richard Hainesd4529302018-02-13 20:57:18 +00004550/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
Mauro Carvalho Chehab5fb94e92018-05-08 15:14:57 -03004551 * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.rst
Richard Hainesd4529302018-02-13 20:57:18 +00004552 */
4553static int selinux_socket_connect_helper(struct socket *sock,
4554 struct sockaddr *address, int addrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555{
Paul Moore014ab192008-10-10 10:16:33 -04004556 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004557 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 int err;
4559
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004560 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 if (err)
4562 return err;
4563
4564 /*
Richard Hainesd4529302018-02-13 20:57:18 +00004565 * If a TCP, DCCP or SCTP socket, check name_connect permission
4566 * for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 */
Paul Moore253bfae2010-04-22 14:46:19 -04004568 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004569 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4570 sksec->sclass == SECCLASS_SCTP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004571 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004572 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 struct sockaddr_in *addr4 = NULL;
4574 struct sockaddr_in6 *addr6 = NULL;
4575 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004576 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577
Richard Hainesd4529302018-02-13 20:57:18 +00004578 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4579 * that validates multiple connect addresses. Because of this
4580 * need to check address->sa_family as it is possible to have
4581 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4582 */
Richard Haines68741a8a2018-03-02 19:54:34 +00004583 switch (address->sa_family) {
4584 case AF_INET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004586 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 return -EINVAL;
4588 snum = ntohs(addr4->sin_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004589 break;
4590 case AF_INET6:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004592 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593 return -EINVAL;
4594 snum = ntohs(addr6->sin6_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004595 break;
4596 default:
4597 /* Note that SCTP services expect -EINVAL, whereas
4598 * others expect -EAFNOSUPPORT.
4599 */
4600 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4601 return -EINVAL;
4602 else
4603 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 }
4605
Paul Moore3e1121722008-04-10 10:48:14 -04004606 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004608 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609
Richard Hainesd4529302018-02-13 20:57:18 +00004610 switch (sksec->sclass) {
4611 case SECCLASS_TCP_SOCKET:
4612 perm = TCP_SOCKET__NAME_CONNECT;
4613 break;
4614 case SECCLASS_DCCP_SOCKET:
4615 perm = DCCP_SOCKET__NAME_CONNECT;
4616 break;
4617 case SECCLASS_SCTP_SOCKET:
4618 perm = SCTP_SOCKET__NAME_CONNECT;
4619 break;
4620 }
James Morris2ee92d42006-11-13 16:09:01 -08004621
Eric Paris50c205f2012-04-04 15:01:43 -04004622 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004623 ad.u.net = &net;
4624 ad.u.net->dport = htons(snum);
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004625 ad.u.net->family = address->sa_family;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004626 err = avc_has_perm(&selinux_state,
4627 sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004629 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 }
4631
Richard Hainesd4529302018-02-13 20:57:18 +00004632 return 0;
4633}
Paul Moore014ab192008-10-10 10:16:33 -04004634
Richard Hainesd4529302018-02-13 20:57:18 +00004635/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4636static int selinux_socket_connect(struct socket *sock,
4637 struct sockaddr *address, int addrlen)
4638{
4639 int err;
4640 struct sock *sk = sock->sk;
4641
4642 err = selinux_socket_connect_helper(sock, address, addrlen);
4643 if (err)
4644 return err;
4645
4646 return selinux_netlbl_socket_connect(sk, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647}
4648
4649static int selinux_socket_listen(struct socket *sock, int backlog)
4650{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004651 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652}
4653
4654static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4655{
4656 int err;
4657 struct inode_security_struct *isec;
4658 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004659 u16 sclass;
4660 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004662 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 if (err)
4664 return err;
4665
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004666 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004667 spin_lock(&isec->lock);
4668 sclass = isec->sclass;
4669 sid = isec->sid;
4670 spin_unlock(&isec->lock);
4671
4672 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4673 newisec->sclass = sclass;
4674 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004675 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
4677 return 0;
4678}
4679
4680static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004681 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004683 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684}
4685
4686static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4687 int size, int flags)
4688{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004689 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004690}
4691
4692static int selinux_socket_getsockname(struct socket *sock)
4693{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004694 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695}
4696
4697static int selinux_socket_getpeername(struct socket *sock)
4698{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004699 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700}
4701
Eric Paris828dfe12008-04-17 13:17:49 -04004702static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703{
Paul Mooref8687af2006-10-30 15:22:15 -08004704 int err;
4705
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004706 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004707 if (err)
4708 return err;
4709
4710 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711}
4712
4713static int selinux_socket_getsockopt(struct socket *sock, int level,
4714 int optname)
4715{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004716 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717}
4718
4719static int selinux_socket_shutdown(struct socket *sock, int how)
4720{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004721 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722}
4723
David S. Miller3610cda2011-01-05 15:38:53 -08004724static int selinux_socket_unix_stream_connect(struct sock *sock,
4725 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 struct sock *newsk)
4727{
David S. Miller3610cda2011-01-05 15:38:53 -08004728 struct sk_security_struct *sksec_sock = sock->sk_security;
4729 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004730 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004731 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004732 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 int err;
4734
Eric Paris50c205f2012-04-04 15:01:43 -04004735 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004736 ad.u.net = &net;
4737 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004738
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004739 err = avc_has_perm(&selinux_state,
4740 sksec_sock->sid, sksec_other->sid,
Paul Moore4d1e2452010-04-22 14:46:18 -04004741 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4743 if (err)
4744 return err;
4745
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004747 sksec_new->peer_sid = sksec_sock->sid;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004748 err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
4749 sksec_sock->sid, &sksec_new->sid);
Paul Moore4d1e2452010-04-22 14:46:18 -04004750 if (err)
4751 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004752
Paul Moore4d1e2452010-04-22 14:46:18 -04004753 /* connecting socket */
4754 sksec_sock->peer_sid = sksec_new->sid;
4755
4756 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757}
4758
4759static int selinux_socket_unix_may_send(struct socket *sock,
4760 struct socket *other)
4761{
Paul Moore253bfae2010-04-22 14:46:19 -04004762 struct sk_security_struct *ssec = sock->sk->sk_security;
4763 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004764 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004765 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Eric Paris50c205f2012-04-04 15:01:43 -04004767 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004768 ad.u.net = &net;
4769 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004771 return avc_has_perm(&selinux_state,
4772 ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
Paul Moore253bfae2010-04-22 14:46:19 -04004773 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774}
4775
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004776static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4777 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004778 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004779{
4780 int err;
4781 u32 if_sid;
4782 u32 node_sid;
4783
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004784 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004785 if (err)
4786 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004787 err = avc_has_perm(&selinux_state,
4788 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004789 SECCLASS_NETIF, NETIF__INGRESS, ad);
4790 if (err)
4791 return err;
4792
4793 err = sel_netnode_sid(addrp, family, &node_sid);
4794 if (err)
4795 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004796 return avc_has_perm(&selinux_state,
4797 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004798 SECCLASS_NODE, NODE__RECVFROM, ad);
4799}
4800
Paul Moore220deb92008-01-29 08:38:23 -05004801static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004802 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004803{
Paul Moore277d3422008-12-31 12:54:11 -05004804 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004805 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004806 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004807 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004808 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004809 char *addrp;
4810
Eric Paris50c205f2012-04-04 15:01:43 -04004811 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004812 ad.u.net = &net;
4813 ad.u.net->netif = skb->skb_iif;
4814 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004815 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4816 if (err)
4817 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004818
Paul Moore58bfbb52009-03-27 17:10:41 -04004819 if (selinux_secmark_enabled()) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004820 err = avc_has_perm(&selinux_state,
4821 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004822 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004823 if (err)
4824 return err;
4825 }
Paul Moore220deb92008-01-29 08:38:23 -05004826
Steffen Klassertb9679a72011-02-23 12:55:21 +01004827 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4828 if (err)
4829 return err;
4830 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004831
James Morris4e5ab4c2006-06-09 00:33:33 -07004832 return err;
4833}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004834
James Morris4e5ab4c2006-06-09 00:33:33 -07004835static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4836{
Paul Moore220deb92008-01-29 08:38:23 -05004837 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004838 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004839 u16 family = sk->sk_family;
4840 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004841 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004842 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004843 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004844 u8 secmark_active;
4845 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004846
James Morris4e5ab4c2006-06-09 00:33:33 -07004847 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004848 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004849
4850 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004851 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004852 family = PF_INET;
4853
Paul Moored8395c82008-10-10 10:16:30 -04004854 /* If any sort of compatibility mode is enabled then handoff processing
4855 * to the selinux_sock_rcv_skb_compat() function to deal with the
4856 * special handling. We do this in an attempt to keep this function
4857 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004858 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04004859 return selinux_sock_rcv_skb_compat(sk, skb, family);
4860
4861 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004862 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004863 if (!secmark_active && !peerlbl_active)
4864 return 0;
4865
Eric Paris50c205f2012-04-04 15:01:43 -04004866 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004867 ad.u.net = &net;
4868 ad.u.net->netif = skb->skb_iif;
4869 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004870 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004871 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004872 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004873
Paul Moored8395c82008-10-10 10:16:30 -04004874 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004875 u32 peer_sid;
4876
4877 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4878 if (err)
4879 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004880 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4881 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004882 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004883 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004884 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004885 }
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004886 err = avc_has_perm(&selinux_state,
4887 sk_sid, peer_sid, SECCLASS_PEER,
Paul Moored621d352008-01-29 08:43:36 -05004888 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004889 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004890 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004891 return err;
4892 }
Paul Moored621d352008-01-29 08:43:36 -05004893 }
4894
Paul Moored8395c82008-10-10 10:16:30 -04004895 if (secmark_active) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004896 err = avc_has_perm(&selinux_state,
4897 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004898 PACKET__RECV, &ad);
4899 if (err)
4900 return err;
4901 }
4902
Paul Moored621d352008-01-29 08:43:36 -05004903 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904}
4905
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004906static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4907 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908{
4909 int err = 0;
4910 char *scontext;
4911 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004912 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004913 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914
Paul Moore253bfae2010-04-22 14:46:19 -04004915 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004916 sksec->sclass == SECCLASS_TCP_SOCKET ||
4917 sksec->sclass == SECCLASS_SCTP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004918 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004919 if (peer_sid == SECSID_NULL)
4920 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004922 err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
4923 &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004925 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926
4927 if (scontext_len > len) {
4928 err = -ERANGE;
4929 goto out_len;
4930 }
4931
4932 if (copy_to_user(optval, scontext, scontext_len))
4933 err = -EFAULT;
4934
4935out_len:
4936 if (put_user(scontext_len, optlen))
4937 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 return err;
4940}
4941
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004942static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004943{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004944 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004945 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004946 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004947
Paul Mooreaa862902008-10-10 10:16:29 -04004948 if (skb && skb->protocol == htons(ETH_P_IP))
4949 family = PF_INET;
4950 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4951 family = PF_INET6;
4952 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004953 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004954 else
4955 goto out;
4956
Paul Moore899134f2016-03-28 15:19:10 -04004957 if (sock && family == PF_UNIX) {
4958 isec = inode_security_novalidate(SOCK_INODE(sock));
4959 peer_secid = isec->sid;
4960 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004961 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004962
Paul Moore75e22912008-01-29 08:38:04 -05004963out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004964 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004965 if (peer_secid == SECSID_NULL)
4966 return -EINVAL;
4967 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004968}
4969
Al Viro7d877f32005-10-21 03:20:43 -04004970static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971{
Paul Moore84914b72010-04-22 14:46:18 -04004972 struct sk_security_struct *sksec;
4973
4974 sksec = kzalloc(sizeof(*sksec), priority);
4975 if (!sksec)
4976 return -ENOMEM;
4977
4978 sksec->peer_sid = SECINITSID_UNLABELED;
4979 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004980 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004981 selinux_netlbl_sk_security_reset(sksec);
4982 sk->sk_security = sksec;
4983
4984 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985}
4986
4987static void selinux_sk_free_security(struct sock *sk)
4988{
Paul Moore84914b72010-04-22 14:46:18 -04004989 struct sk_security_struct *sksec = sk->sk_security;
4990
4991 sk->sk_security = NULL;
4992 selinux_netlbl_sk_security_free(sksec);
4993 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994}
4995
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004996static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4997{
Eric Parisdd3e7832010-04-07 15:08:46 -04004998 struct sk_security_struct *sksec = sk->sk_security;
4999 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005000
Eric Parisdd3e7832010-04-07 15:08:46 -04005001 newsksec->sid = sksec->sid;
5002 newsksec->peer_sid = sksec->peer_sid;
5003 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07005004
Eric Parisdd3e7832010-04-07 15:08:46 -04005005 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005006}
5007
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005008static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005009{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005010 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005011 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005012 else {
5013 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005014
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07005015 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005016 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005017}
5018
Eric Paris828dfe12008-04-17 13:17:49 -04005019static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005020{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05005021 struct inode_security_struct *isec =
5022 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005023 struct sk_security_struct *sksec = sk->sk_security;
5024
Paul Moore2873ead2014-07-28 10:42:48 -04005025 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5026 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07005027 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05005028 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005029}
5030
Richard Hainesd4529302018-02-13 20:57:18 +00005031/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5032 * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5033 * already present).
5034 */
5035static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5036 struct sk_buff *skb)
5037{
5038 struct sk_security_struct *sksec = ep->base.sk->sk_security;
5039 struct common_audit_data ad;
5040 struct lsm_network_audit net = {0,};
5041 u8 peerlbl_active;
5042 u32 peer_sid = SECINITSID_UNLABELED;
5043 u32 conn_sid;
5044 int err = 0;
5045
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005046 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005047 return 0;
5048
5049 peerlbl_active = selinux_peerlbl_enabled();
5050
5051 if (peerlbl_active) {
5052 /* This will return peer_sid = SECSID_NULL if there are
5053 * no peer labels, see security_net_peersid_resolve().
5054 */
5055 err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5056 &peer_sid);
5057 if (err)
5058 return err;
5059
5060 if (peer_sid == SECSID_NULL)
5061 peer_sid = SECINITSID_UNLABELED;
5062 }
5063
5064 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5065 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5066
5067 /* Here as first association on socket. As the peer SID
5068 * was allowed by peer recv (and the netif/node checks),
5069 * then it is approved by policy and used as the primary
5070 * peer SID for getpeercon(3).
5071 */
5072 sksec->peer_sid = peer_sid;
5073 } else if (sksec->peer_sid != peer_sid) {
5074 /* Other association peer SIDs are checked to enforce
5075 * consistency among the peer SIDs.
5076 */
5077 ad.type = LSM_AUDIT_DATA_NET;
5078 ad.u.net = &net;
5079 ad.u.net->sk = ep->base.sk;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005080 err = avc_has_perm(&selinux_state,
5081 sksec->peer_sid, peer_sid, sksec->sclass,
Richard Hainesd4529302018-02-13 20:57:18 +00005082 SCTP_SOCKET__ASSOCIATION, &ad);
5083 if (err)
5084 return err;
5085 }
5086
5087 /* Compute the MLS component for the connection and store
5088 * the information in ep. This will be used by SCTP TCP type
5089 * sockets and peeled off connections as they cause a new
5090 * socket to be generated. selinux_sctp_sk_clone() will then
5091 * plug this into the new socket.
5092 */
5093 err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5094 if (err)
5095 return err;
5096
5097 ep->secid = conn_sid;
5098 ep->peer_secid = peer_sid;
5099
5100 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
5101 return selinux_netlbl_sctp_assoc_request(ep, skb);
5102}
5103
5104/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5105 * based on their @optname.
5106 */
5107static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5108 struct sockaddr *address,
5109 int addrlen)
5110{
5111 int len, err = 0, walk_size = 0;
5112 void *addr_buf;
5113 struct sockaddr *addr;
5114 struct socket *sock;
5115
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005116 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005117 return 0;
5118
5119 /* Process one or more addresses that may be IPv4 or IPv6 */
5120 sock = sk->sk_socket;
5121 addr_buf = address;
5122
5123 while (walk_size < addrlen) {
5124 addr = addr_buf;
5125 switch (addr->sa_family) {
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005126 case AF_UNSPEC:
Richard Hainesd4529302018-02-13 20:57:18 +00005127 case AF_INET:
5128 len = sizeof(struct sockaddr_in);
5129 break;
5130 case AF_INET6:
5131 len = sizeof(struct sockaddr_in6);
5132 break;
5133 default:
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005134 return -EINVAL;
Richard Hainesd4529302018-02-13 20:57:18 +00005135 }
5136
5137 err = -EINVAL;
5138 switch (optname) {
5139 /* Bind checks */
5140 case SCTP_PRIMARY_ADDR:
5141 case SCTP_SET_PEER_PRIMARY_ADDR:
5142 case SCTP_SOCKOPT_BINDX_ADD:
5143 err = selinux_socket_bind(sock, addr, len);
5144 break;
5145 /* Connect checks */
5146 case SCTP_SOCKOPT_CONNECTX:
5147 case SCTP_PARAM_SET_PRIMARY:
5148 case SCTP_PARAM_ADD_IP:
5149 case SCTP_SENDMSG_CONNECT:
5150 err = selinux_socket_connect_helper(sock, addr, len);
5151 if (err)
5152 return err;
5153
5154 /* As selinux_sctp_bind_connect() is called by the
5155 * SCTP protocol layer, the socket is already locked,
5156 * therefore selinux_netlbl_socket_connect_locked() is
5157 * is called here. The situations handled are:
5158 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5159 * whenever a new IP address is added or when a new
5160 * primary address is selected.
5161 * Note that an SCTP connect(2) call happens before
5162 * the SCTP protocol layer and is handled via
5163 * selinux_socket_connect().
5164 */
5165 err = selinux_netlbl_socket_connect_locked(sk, addr);
5166 break;
5167 }
5168
5169 if (err)
5170 return err;
5171
5172 addr_buf += len;
5173 walk_size += len;
5174 }
5175
5176 return 0;
5177}
5178
5179/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
5180static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5181 struct sock *newsk)
5182{
5183 struct sk_security_struct *sksec = sk->sk_security;
5184 struct sk_security_struct *newsksec = newsk->sk_security;
5185
5186 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5187 * the non-sctp clone version.
5188 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005189 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005190 return selinux_sk_clone_security(sk, newsk);
5191
5192 newsksec->sid = ep->secid;
5193 newsksec->peer_sid = ep->peer_secid;
5194 newsksec->sclass = sksec->sclass;
5195 selinux_netlbl_sctp_sk_clone(sk, newsk);
5196}
5197
Adrian Bunk9a673e52006-08-15 00:03:53 -07005198static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
5199 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005200{
5201 struct sk_security_struct *sksec = sk->sk_security;
5202 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05005203 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05005204 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005205 u32 peersid;
5206
Paul Mooreaa862902008-10-10 10:16:29 -04005207 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05005208 if (err)
5209 return err;
Paul Moore446b8022013-12-04 16:10:51 -05005210 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5211 if (err)
5212 return err;
5213 req->secid = connsid;
5214 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07005215
Paul Moore389fb8002009-03-27 17:10:34 -04005216 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005217}
5218
Adrian Bunk9a673e52006-08-15 00:03:53 -07005219static void selinux_inet_csk_clone(struct sock *newsk,
5220 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005221{
5222 struct sk_security_struct *newsksec = newsk->sk_security;
5223
5224 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005225 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005226 /* NOTE: Ideally, we should also get the isec->sid for the
5227 new socket in sync, but we don't have the isec available yet.
5228 So we will wait until sock_graft to do it, by which
5229 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07005230
Paul Moore9f2ad662006-11-17 17:38:53 -05005231 /* We don't need to take any sort of lock here as we are the only
5232 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04005233 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005234}
5235
Paul Moore014ab192008-10-10 10:16:33 -04005236static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005237{
Paul Mooreaa862902008-10-10 10:16:29 -04005238 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005239 struct sk_security_struct *sksec = sk->sk_security;
5240
Paul Mooreaa862902008-10-10 10:16:29 -04005241 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5242 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5243 family = PF_INET;
5244
5245 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005246}
5247
Eric Paris2606fd12010-10-13 16:24:41 -04005248static int selinux_secmark_relabel_packet(u32 sid)
5249{
5250 const struct task_security_struct *__tsec;
5251 u32 tsid;
5252
5253 __tsec = current_security();
5254 tsid = __tsec->sid;
5255
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005256 return avc_has_perm(&selinux_state,
5257 tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
5258 NULL);
Eric Paris2606fd12010-10-13 16:24:41 -04005259}
5260
5261static void selinux_secmark_refcount_inc(void)
5262{
5263 atomic_inc(&selinux_secmark_refcount);
5264}
5265
5266static void selinux_secmark_refcount_dec(void)
5267{
5268 atomic_dec(&selinux_secmark_refcount);
5269}
5270
Adrian Bunk9a673e52006-08-15 00:03:53 -07005271static void selinux_req_classify_flow(const struct request_sock *req,
5272 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005273{
David S. Miller1d28f422011-03-12 00:29:39 -05005274 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005275}
5276
Paul Moore5dbbaf22013-01-14 07:12:19 +00005277static int selinux_tun_dev_alloc_security(void **security)
5278{
5279 struct tun_security_struct *tunsec;
5280
5281 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5282 if (!tunsec)
5283 return -ENOMEM;
5284 tunsec->sid = current_sid();
5285
5286 *security = tunsec;
5287 return 0;
5288}
5289
5290static void selinux_tun_dev_free_security(void *security)
5291{
5292 kfree(security);
5293}
5294
Paul Mooreed6d76e2009-08-28 18:12:49 -04005295static int selinux_tun_dev_create(void)
5296{
5297 u32 sid = current_sid();
5298
5299 /* we aren't taking into account the "sockcreate" SID since the socket
5300 * that is being created here is not a socket in the traditional sense,
5301 * instead it is a private sock, accessible only to the kernel, and
5302 * representing a wide range of network traffic spanning multiple
5303 * connections unlike traditional sockets - check the TUN driver to
5304 * get a better understanding of why this socket is special */
5305
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005306 return avc_has_perm(&selinux_state,
5307 sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005308 NULL);
5309}
5310
Paul Moore5dbbaf22013-01-14 07:12:19 +00005311static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005312{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005313 struct tun_security_struct *tunsec = security;
5314
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005315 return avc_has_perm(&selinux_state,
5316 current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005317 TUN_SOCKET__ATTACH_QUEUE, NULL);
5318}
5319
5320static int selinux_tun_dev_attach(struct sock *sk, void *security)
5321{
5322 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005323 struct sk_security_struct *sksec = sk->sk_security;
5324
5325 /* we don't currently perform any NetLabel based labeling here and it
5326 * isn't clear that we would want to do so anyway; while we could apply
5327 * labeling without the support of the TUN user the resulting labeled
5328 * traffic from the other end of the connection would almost certainly
5329 * cause confusion to the TUN user that had no idea network labeling
5330 * protocols were being used */
5331
Paul Moore5dbbaf22013-01-14 07:12:19 +00005332 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005333 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005334
5335 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005336}
5337
Paul Moore5dbbaf22013-01-14 07:12:19 +00005338static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005339{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005340 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005341 u32 sid = current_sid();
5342 int err;
5343
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005344 err = avc_has_perm(&selinux_state,
5345 sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005346 TUN_SOCKET__RELABELFROM, NULL);
5347 if (err)
5348 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005349 err = avc_has_perm(&selinux_state,
5350 sid, sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005351 TUN_SOCKET__RELABELTO, NULL);
5352 if (err)
5353 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005354 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005355
5356 return 0;
5357}
5358
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
5360{
5361 int err = 0;
5362 u32 perm;
5363 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005364 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005365
Hong zhi guo77954982013-03-27 06:49:35 +00005366 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 err = -EINVAL;
5368 goto out;
5369 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005370 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005371
Paul Moore253bfae2010-04-22 14:46:19 -04005372 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 if (err) {
5374 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005375 pr_warn_ratelimited("SELinux: unrecognized netlink"
5376 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5377 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005378 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005379 secclass_map[sksec->sclass - 1].name,
5380 task_pid_nr(current), current->comm);
Paul Mooree5a5ca92018-03-01 17:38:30 -05005381 if (!enforcing_enabled(&selinux_state) ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005382 security_get_allow_unknown(&selinux_state))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383 err = 0;
5384 }
5385
5386 /* Ignore */
5387 if (err == -ENOENT)
5388 err = 0;
5389 goto out;
5390 }
5391
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005392 err = sock_has_perm(sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393out:
5394 return err;
5395}
5396
5397#ifdef CONFIG_NETFILTER
5398
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005399static unsigned int selinux_ip_forward(struct sk_buff *skb,
5400 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005401 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402{
Paul Mooredfaebe92008-10-10 10:16:31 -04005403 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005404 char *addrp;
5405 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005406 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005407 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005408 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005409 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005410 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005411
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005412 if (!selinux_policycap_netpeer())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005413 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005414
Paul Mooreeffad8d2008-01-29 08:49:27 -05005415 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005416 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005417 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005418 if (!secmark_active && !peerlbl_active)
5419 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005420
Paul Moored8395c82008-10-10 10:16:30 -04005421 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5422 return NF_DROP;
5423
Eric Paris50c205f2012-04-04 15:01:43 -04005424 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005425 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005426 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005427 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005428 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5429 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
Paul Mooredfaebe92008-10-10 10:16:31 -04005431 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005432 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5433 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005434 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005435 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005436 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005437 }
5438 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005439
5440 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005441 if (avc_has_perm(&selinux_state,
5442 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005443 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5444 return NF_DROP;
5445
Paul Moore948bf852008-10-10 10:16:32 -04005446 if (netlbl_active)
5447 /* we do this in the FORWARD path and not the POST_ROUTING
5448 * path because we want to make sure we apply the necessary
5449 * labeling before IPsec is applied so we can leverage AH
5450 * protection */
5451 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5452 return NF_DROP;
5453
Paul Mooreeffad8d2008-01-29 08:49:27 -05005454 return NF_ACCEPT;
5455}
5456
Eric W. Biederman06198b32015-09-18 14:33:06 -05005457static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005458 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005459 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005460{
David S. Miller238e54c2015-04-03 20:32:56 -04005461 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005462}
5463
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005464#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005465static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005466 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005467 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005468{
David S. Miller238e54c2015-04-03 20:32:56 -04005469 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005470}
5471#endif /* IPV6 */
5472
Paul Moore948bf852008-10-10 10:16:32 -04005473static unsigned int selinux_ip_output(struct sk_buff *skb,
5474 u16 family)
5475{
Paul Moore47180062013-12-04 16:10:45 -05005476 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005477 u32 sid;
5478
5479 if (!netlbl_enabled())
5480 return NF_ACCEPT;
5481
5482 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5483 * because we want to make sure we apply the necessary labeling
5484 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005485 sk = skb->sk;
5486 if (sk) {
5487 struct sk_security_struct *sksec;
5488
Eric Dumazete446f9d2015-10-08 05:01:55 -07005489 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005490 /* if the socket is the listening state then this
5491 * packet is a SYN-ACK packet which means it needs to
5492 * be labeled based on the connection/request_sock and
5493 * not the parent socket. unfortunately, we can't
5494 * lookup the request_sock yet as it isn't queued on
5495 * the parent socket until after the SYN-ACK is sent.
5496 * the "solution" is to simply pass the packet as-is
5497 * as any IP option based labeling should be copied
5498 * from the initial connection request (in the IP
5499 * layer). it is far from ideal, but until we get a
5500 * security label in the packet itself this is the
5501 * best we can do. */
5502 return NF_ACCEPT;
5503
5504 /* standard practice, label using the parent socket */
5505 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005506 sid = sksec->sid;
5507 } else
5508 sid = SECINITSID_KERNEL;
5509 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5510 return NF_DROP;
5511
5512 return NF_ACCEPT;
5513}
5514
Eric W. Biederman06198b32015-09-18 14:33:06 -05005515static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005516 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005517 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005518{
5519 return selinux_ip_output(skb, PF_INET);
5520}
5521
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005522#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005523static unsigned int selinux_ipv6_output(void *priv,
5524 struct sk_buff *skb,
5525 const struct nf_hook_state *state)
5526{
5527 return selinux_ip_output(skb, PF_INET6);
5528}
5529#endif /* IPV6 */
5530
Paul Mooreeffad8d2008-01-29 08:49:27 -05005531static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5532 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005533 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005534{
Eric Dumazet54abc682015-11-08 10:54:07 -08005535 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005536 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005537 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005538 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005539 char *addrp;
5540 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005541
Paul Mooreeffad8d2008-01-29 08:49:27 -05005542 if (sk == NULL)
5543 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005544 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005545
Eric Paris50c205f2012-04-04 15:01:43 -04005546 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005547 ad.u.net = &net;
5548 ad.u.net->netif = ifindex;
5549 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005550 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5551 return NF_DROP;
5552
Paul Moore58bfbb52009-03-27 17:10:41 -04005553 if (selinux_secmark_enabled())
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005554 if (avc_has_perm(&selinux_state,
5555 sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005556 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005557 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005558
Steffen Klassertb9679a72011-02-23 12:55:21 +01005559 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5560 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005561
Paul Mooreeffad8d2008-01-29 08:49:27 -05005562 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563}
5564
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005565static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5566 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005567 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005569 u32 secmark_perm;
5570 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005571 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005572 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005573 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005574 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005575 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005576 u8 secmark_active;
5577 u8 peerlbl_active;
5578
Paul Mooreeffad8d2008-01-29 08:49:27 -05005579 /* If any sort of compatibility mode is enabled then handoff processing
5580 * to the selinux_ip_postroute_compat() function to deal with the
5581 * special handling. We do this in an attempt to keep this function
5582 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005583 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005584 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005585
Paul Mooreeffad8d2008-01-29 08:49:27 -05005586 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005587 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005588 if (!secmark_active && !peerlbl_active)
5589 return NF_ACCEPT;
5590
Eric Dumazet54abc682015-11-08 10:54:07 -08005591 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005592
Paul Mooreeffad8d2008-01-29 08:49:27 -05005593#ifdef CONFIG_XFRM
5594 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5595 * packet transformation so allow the packet to pass without any checks
5596 * since we'll have another chance to perform access control checks
5597 * when the packet is on it's final way out.
5598 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005599 * is NULL, in this case go ahead and apply access control.
5600 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5601 * TCP listening state we cannot wait until the XFRM processing
5602 * is done as we will miss out on the SA label if we do;
5603 * unfortunately, this means more work, but it is only once per
5604 * connection. */
5605 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005606 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005607 return NF_ACCEPT;
5608#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005609
Paul Moored8395c82008-10-10 10:16:30 -04005610 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005611 /* Without an associated socket the packet is either coming
5612 * from the kernel or it is being forwarded; check the packet
5613 * to determine which and if the packet is being forwarded
5614 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005615 if (skb->skb_iif) {
5616 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005617 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005618 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005619 } else {
5620 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005621 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005622 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005623 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005624 /* Locally generated packet but the associated socket is in the
5625 * listening state which means this is a SYN-ACK packet. In
5626 * this particular case the correct security label is assigned
5627 * to the connection/request_sock but unfortunately we can't
5628 * query the request_sock as it isn't queued on the parent
5629 * socket until after the SYN-ACK packet is sent; the only
5630 * viable choice is to regenerate the label like we do in
5631 * selinux_inet_conn_request(). See also selinux_ip_output()
5632 * for similar problems. */
5633 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005634 struct sk_security_struct *sksec;
5635
Eric Dumazete446f9d2015-10-08 05:01:55 -07005636 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005637 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5638 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005639 /* At this point, if the returned skb peerlbl is SECSID_NULL
5640 * and the packet has been through at least one XFRM
5641 * transformation then we must be dealing with the "final"
5642 * form of labeled IPsec packet; since we've already applied
5643 * all of our access controls on this packet we can safely
5644 * pass the packet. */
5645 if (skb_sid == SECSID_NULL) {
5646 switch (family) {
5647 case PF_INET:
5648 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5649 return NF_ACCEPT;
5650 break;
5651 case PF_INET6:
5652 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5653 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005654 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005655 default:
5656 return NF_DROP_ERR(-ECONNREFUSED);
5657 }
5658 }
Paul Moore446b8022013-12-04 16:10:51 -05005659 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5660 return NF_DROP;
5661 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005662 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005663 /* Locally generated packet, fetch the security label from the
5664 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005665 struct sk_security_struct *sksec = sk->sk_security;
5666 peer_sid = sksec->sid;
5667 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005668 }
5669
Eric Paris50c205f2012-04-04 15:01:43 -04005670 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005671 ad.u.net = &net;
5672 ad.u.net->netif = ifindex;
5673 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005674 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005675 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005676
Paul Mooreeffad8d2008-01-29 08:49:27 -05005677 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005678 if (avc_has_perm(&selinux_state,
5679 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005680 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005681 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005682
5683 if (peerlbl_active) {
5684 u32 if_sid;
5685 u32 node_sid;
5686
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005687 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005688 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005689 if (avc_has_perm(&selinux_state,
5690 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005691 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005692 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005693
5694 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005695 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005696 if (avc_has_perm(&selinux_state,
5697 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005698 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005699 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005700 }
5701
5702 return NF_ACCEPT;
5703}
5704
Eric W. Biederman06198b32015-09-18 14:33:06 -05005705static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005706 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005707 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005708{
David S. Miller238e54c2015-04-03 20:32:56 -04005709 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710}
5711
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005712#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005713static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005714 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005715 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716{
David S. Miller238e54c2015-04-03 20:32:56 -04005717 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719#endif /* IPV6 */
5720
5721#endif /* CONFIG_NETFILTER */
5722
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5724{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005725 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726}
5727
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005728static int ipc_alloc_security(struct kern_ipc_perm *perm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 u16 sclass)
5730{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731 struct ipc_security_struct *isec;
5732
James Morris89d155e2005-10-30 14:59:21 -08005733 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734 if (!isec)
5735 return -ENOMEM;
5736
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005738 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739 perm->security = isec;
5740
5741 return 0;
5742}
5743
5744static void ipc_free_security(struct kern_ipc_perm *perm)
5745{
5746 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747 perm->security = NULL;
5748 kfree(isec);
5749}
5750
5751static int msg_msg_alloc_security(struct msg_msg *msg)
5752{
5753 struct msg_security_struct *msec;
5754
James Morris89d155e2005-10-30 14:59:21 -08005755 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756 if (!msec)
5757 return -ENOMEM;
5758
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759 msec->sid = SECINITSID_UNLABELED;
5760 msg->security = msec;
5761
5762 return 0;
5763}
5764
5765static void msg_msg_free_security(struct msg_msg *msg)
5766{
5767 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768
5769 msg->security = NULL;
5770 kfree(msec);
5771}
5772
5773static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005774 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005777 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005778 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780 isec = ipc_perms->security;
5781
Eric Paris50c205f2012-04-04 15:01:43 -04005782 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 ad.u.ipc_id = ipc_perms->key;
5784
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005785 return avc_has_perm(&selinux_state,
5786 sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787}
5788
5789static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5790{
5791 return msg_msg_alloc_security(msg);
5792}
5793
5794static void selinux_msg_msg_free_security(struct msg_msg *msg)
5795{
5796 msg_msg_free_security(msg);
5797}
5798
5799/* message queue security operations */
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005800static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005803 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005804 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 int rc;
5806
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005807 rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808 if (rc)
5809 return rc;
5810
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005811 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
Eric Paris50c205f2012-04-04 15:01:43 -04005813 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005814 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005816 rc = avc_has_perm(&selinux_state,
5817 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818 MSGQ__CREATE, &ad);
5819 if (rc) {
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005820 ipc_free_security(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821 return rc;
5822 }
5823 return 0;
5824}
5825
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005826static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827{
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005828 ipc_free_security(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829}
5830
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005831static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005834 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005835 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005837 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838
Eric Paris50c205f2012-04-04 15:01:43 -04005839 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005840 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005842 return avc_has_perm(&selinux_state,
5843 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844 MSGQ__ASSOCIATE, &ad);
5845}
5846
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005847static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848{
5849 int err;
5850 int perms;
5851
Eric Paris828dfe12008-04-17 13:17:49 -04005852 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005853 case IPC_INFO:
5854 case MSG_INFO:
5855 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005856 return avc_has_perm(&selinux_state,
5857 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005858 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859 case IPC_STAT:
5860 case MSG_STAT:
Davidlohr Bueso23c8cec2018-04-10 16:35:30 -07005861 case MSG_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5863 break;
5864 case IPC_SET:
5865 perms = MSGQ__SETATTR;
5866 break;
5867 case IPC_RMID:
5868 perms = MSGQ__DESTROY;
5869 break;
5870 default:
5871 return 0;
5872 }
5873
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005874 err = ipc_has_perm(msq, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875 return err;
5876}
5877
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005878static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880 struct ipc_security_struct *isec;
5881 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005882 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005883 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884 int rc;
5885
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005886 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887 msec = msg->security;
5888
5889 /*
5890 * First time through, need to assign label to the message
5891 */
5892 if (msec->sid == SECINITSID_UNLABELED) {
5893 /*
5894 * Compute new sid based on current process and
5895 * message queue this message will be stored in
5896 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005897 rc = security_transition_sid(&selinux_state, sid, isec->sid,
5898 SECCLASS_MSG, NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899 if (rc)
5900 return rc;
5901 }
5902
Eric Paris50c205f2012-04-04 15:01:43 -04005903 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005904 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905
5906 /* Can this process write to the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005907 rc = avc_has_perm(&selinux_state,
5908 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909 MSGQ__WRITE, &ad);
5910 if (!rc)
5911 /* Can this process send the message */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005912 rc = avc_has_perm(&selinux_state,
5913 sid, msec->sid, SECCLASS_MSG,
David Howells275bb412008-11-14 10:39:19 +11005914 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 if (!rc)
5916 /* Can the message be put in the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005917 rc = avc_has_perm(&selinux_state,
5918 msec->sid, isec->sid, SECCLASS_MSGQ,
David Howells275bb412008-11-14 10:39:19 +11005919 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920
5921 return rc;
5922}
5923
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005924static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 struct task_struct *target,
5926 long type, int mode)
5927{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928 struct ipc_security_struct *isec;
5929 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005930 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005931 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932 int rc;
5933
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005934 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935 msec = msg->security;
5936
Eric Paris50c205f2012-04-04 15:01:43 -04005937 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005938 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005940 rc = avc_has_perm(&selinux_state,
5941 sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 SECCLASS_MSGQ, MSGQ__READ, &ad);
5943 if (!rc)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005944 rc = avc_has_perm(&selinux_state,
5945 sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946 SECCLASS_MSG, MSG__RECEIVE, &ad);
5947 return rc;
5948}
5949
5950/* Shared Memory security operations */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005951static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005954 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005955 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 int rc;
5957
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005958 rc = ipc_alloc_security(shp, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959 if (rc)
5960 return rc;
5961
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005962 isec = shp->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Eric Paris50c205f2012-04-04 15:01:43 -04005964 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005965 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005967 rc = avc_has_perm(&selinux_state,
5968 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969 SHM__CREATE, &ad);
5970 if (rc) {
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005971 ipc_free_security(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972 return rc;
5973 }
5974 return 0;
5975}
5976
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005977static void selinux_shm_free_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978{
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005979 ipc_free_security(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980}
5981
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005982static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005985 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005986 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005988 isec = shp->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989
Eric Paris50c205f2012-04-04 15:01:43 -04005990 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005991 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005993 return avc_has_perm(&selinux_state,
5994 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995 SHM__ASSOCIATE, &ad);
5996}
5997
5998/* Note, at this point, shp is locked down */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005999static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000{
6001 int perms;
6002 int err;
6003
Eric Paris828dfe12008-04-17 13:17:49 -04006004 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005 case IPC_INFO:
6006 case SHM_INFO:
6007 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006008 return avc_has_perm(&selinux_state,
6009 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006010 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011 case IPC_STAT:
6012 case SHM_STAT:
Davidlohr Buesoc21a6972018-04-10 16:35:23 -07006013 case SHM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014 perms = SHM__GETATTR | SHM__ASSOCIATE;
6015 break;
6016 case IPC_SET:
6017 perms = SHM__SETATTR;
6018 break;
6019 case SHM_LOCK:
6020 case SHM_UNLOCK:
6021 perms = SHM__LOCK;
6022 break;
6023 case IPC_RMID:
6024 perms = SHM__DESTROY;
6025 break;
6026 default:
6027 return 0;
6028 }
6029
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006030 err = ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031 return err;
6032}
6033
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006034static int selinux_shm_shmat(struct kern_ipc_perm *shp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035 char __user *shmaddr, int shmflg)
6036{
6037 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
6039 if (shmflg & SHM_RDONLY)
6040 perms = SHM__READ;
6041 else
6042 perms = SHM__READ | SHM__WRITE;
6043
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006044 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045}
6046
6047/* Semaphore security operations */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006048static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006050 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006051 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006052 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053 int rc;
6054
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006055 rc = ipc_alloc_security(sma, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056 if (rc)
6057 return rc;
6058
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006059 isec = sma->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Eric Paris50c205f2012-04-04 15:01:43 -04006061 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006062 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006064 rc = avc_has_perm(&selinux_state,
6065 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066 SEM__CREATE, &ad);
6067 if (rc) {
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006068 ipc_free_security(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069 return rc;
6070 }
6071 return 0;
6072}
6073
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006074static void selinux_sem_free_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075{
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006076 ipc_free_security(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077}
6078
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006079static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006080{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006082 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006083 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006085 isec = sma->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Eric Paris50c205f2012-04-04 15:01:43 -04006087 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006088 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006090 return avc_has_perm(&selinux_state,
6091 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092 SEM__ASSOCIATE, &ad);
6093}
6094
6095/* Note, at this point, sma is locked down */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006096static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097{
6098 int err;
6099 u32 perms;
6100
Eric Paris828dfe12008-04-17 13:17:49 -04006101 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102 case IPC_INFO:
6103 case SEM_INFO:
6104 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006105 return avc_has_perm(&selinux_state,
6106 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006107 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108 case GETPID:
6109 case GETNCNT:
6110 case GETZCNT:
6111 perms = SEM__GETATTR;
6112 break;
6113 case GETVAL:
6114 case GETALL:
6115 perms = SEM__READ;
6116 break;
6117 case SETVAL:
6118 case SETALL:
6119 perms = SEM__WRITE;
6120 break;
6121 case IPC_RMID:
6122 perms = SEM__DESTROY;
6123 break;
6124 case IPC_SET:
6125 perms = SEM__SETATTR;
6126 break;
6127 case IPC_STAT:
6128 case SEM_STAT:
Davidlohr Buesoa280d6d2018-04-10 16:35:26 -07006129 case SEM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 perms = SEM__GETATTR | SEM__ASSOCIATE;
6131 break;
6132 default:
6133 return 0;
6134 }
6135
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006136 err = ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137 return err;
6138}
6139
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006140static int selinux_sem_semop(struct kern_ipc_perm *sma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141 struct sembuf *sops, unsigned nsops, int alter)
6142{
6143 u32 perms;
6144
6145 if (alter)
6146 perms = SEM__READ | SEM__WRITE;
6147 else
6148 perms = SEM__READ;
6149
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006150 return ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151}
6152
6153static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6154{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006155 u32 av = 0;
6156
Linus Torvalds1da177e2005-04-16 15:20:36 -07006157 av = 0;
6158 if (flag & S_IRUGO)
6159 av |= IPC__UNIX_READ;
6160 if (flag & S_IWUGO)
6161 av |= IPC__UNIX_WRITE;
6162
6163 if (av == 0)
6164 return 0;
6165
Stephen Smalley6af963f2005-05-01 08:58:39 -07006166 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006167}
6168
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006169static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6170{
6171 struct ipc_security_struct *isec = ipcp->security;
6172 *secid = isec->sid;
6173}
6174
Eric Paris828dfe12008-04-17 13:17:49 -04006175static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176{
6177 if (inode)
6178 inode_doinit_with_dentry(inode, dentry);
6179}
6180
6181static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00006182 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183{
David Howells275bb412008-11-14 10:39:19 +11006184 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00006185 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186 int error;
Al Viro04ff9702007-03-12 16:17:58 +00006187 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188
David Howells275bb412008-11-14 10:39:19 +11006189 rcu_read_lock();
6190 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006192 if (current != p) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006193 error = avc_has_perm(&selinux_state,
6194 current_sid(), __tsec->sid,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006195 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6196 if (error)
6197 goto bad;
6198 }
6199
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11006201 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11006203 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11006205 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11006207 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006208 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11006209 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07006210 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11006211 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006212 else {
6213 error = -EINVAL;
6214 goto bad;
6215 }
David Howells275bb412008-11-14 10:39:19 +11006216 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217
6218 if (!sid)
6219 return 0;
6220
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006221 error = security_sid_to_context(&selinux_state, sid, value, &len);
Al Viro04ff9702007-03-12 16:17:58 +00006222 if (error)
6223 return error;
6224 return len;
David Howells275bb412008-11-14 10:39:19 +11006225
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006226bad:
David Howells275bb412008-11-14 10:39:19 +11006227 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006228 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229}
6230
Stephen Smalleyb21507e2017-01-09 10:07:31 -05006231static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232{
6233 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11006234 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006235 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006236 int error;
6237 char *str = value;
6238
Linus Torvalds1da177e2005-04-16 15:20:36 -07006239 /*
6240 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006241 */
6242 if (!strcmp(name, "exec"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006243 error = avc_has_perm(&selinux_state,
6244 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006245 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246 else if (!strcmp(name, "fscreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006247 error = avc_has_perm(&selinux_state,
6248 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006249 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006250 else if (!strcmp(name, "keycreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006251 error = avc_has_perm(&selinux_state,
6252 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006253 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07006254 else if (!strcmp(name, "sockcreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006255 error = avc_has_perm(&selinux_state,
6256 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006257 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258 else if (!strcmp(name, "current"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006259 error = avc_has_perm(&selinux_state,
6260 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006261 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262 else
6263 error = -EINVAL;
6264 if (error)
6265 return error;
6266
6267 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05006268 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269 if (str[size-1] == '\n') {
6270 str[size-1] = 0;
6271 size--;
6272 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006273 error = security_context_to_sid(&selinux_state, value, size,
6274 &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006275 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04006276 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04006277 struct audit_buffer *ab;
6278 size_t audit_size;
6279
6280 /* We strip a nul only if it is at the end, otherwise the
6281 * context contains a nul and we should audit that */
6282 if (str[size - 1] == '\0')
6283 audit_size = size - 1;
6284 else
6285 audit_size = size;
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04006286 ab = audit_log_start(audit_context(),
6287 GFP_ATOMIC,
6288 AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04006289 audit_log_format(ab, "op=fscreate invalid_context=");
6290 audit_log_n_untrustedstring(ab, value, audit_size);
6291 audit_log_end(ab);
6292
Stephen Smalley12b29f32008-05-07 13:03:20 -04006293 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006294 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006295 error = security_context_to_sid_force(
6296 &selinux_state,
6297 value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299 if (error)
6300 return error;
6301 }
6302
David Howellsd84f4f92008-11-14 10:39:23 +11006303 new = prepare_creds();
6304 if (!new)
6305 return -ENOMEM;
6306
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307 /* Permission checking based on the specified context is
6308 performed during the actual operation (execve,
6309 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11006310 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 checks and may_create for the file creation checks. The
6312 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11006313 tsec = new->security;
6314 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006316 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006317 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006318 } else if (!strcmp(name, "keycreate")) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006319 error = avc_has_perm(&selinux_state,
6320 mysid, sid, SECCLASS_KEY, KEY__CREATE,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006321 NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006322 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006323 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006324 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006325 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006326 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006327 } else if (!strcmp(name, "current")) {
6328 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006330 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006331
David Howellsd84f4f92008-11-14 10:39:23 +11006332 /* Only allow single threaded processes to change context */
6333 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006334 if (!current_is_single_threaded()) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006335 error = security_bounded_transition(&selinux_state,
6336 tsec->sid, sid);
David Howellsd84f4f92008-11-14 10:39:23 +11006337 if (error)
6338 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006340
6341 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006342 error = avc_has_perm(&selinux_state,
6343 tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006344 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006345 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006346 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347
6348 /* Check for ptracing, and update the task SID if ok.
6349 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006350 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006351 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006352 error = avc_has_perm(&selinux_state,
6353 ptsid, sid, SECCLASS_PROCESS,
David Howellsd84f4f92008-11-14 10:39:23 +11006354 PROCESS__PTRACE, NULL);
6355 if (error)
6356 goto abort_change;
6357 }
6358
6359 tsec->sid = sid;
6360 } else {
6361 error = -EINVAL;
6362 goto abort_change;
6363 }
6364
6365 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006366 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006367
6368abort_change:
6369 abort_creds(new);
6370 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006371}
6372
David Quigley746df9b2013-05-22 12:50:35 -04006373static int selinux_ismaclabel(const char *name)
6374{
6375 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6376}
6377
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006378static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6379{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006380 return security_sid_to_context(&selinux_state, secid,
6381 secdata, seclen);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006382}
6383
David Howells7bf570d2008-04-29 20:52:51 +01006384static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006385{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006386 return security_context_to_sid(&selinux_state, secdata, seclen,
6387 secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006388}
6389
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006390static void selinux_release_secctx(char *secdata, u32 seclen)
6391{
Paul Moore088999e2007-08-01 11:12:58 -04006392 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006393}
6394
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006395static void selinux_inode_invalidate_secctx(struct inode *inode)
6396{
6397 struct inode_security_struct *isec = inode->i_security;
6398
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006399 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006400 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006401 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006402}
6403
David P. Quigley1ee65e32009-09-03 14:25:57 -04006404/*
6405 * called with inode->i_mutex locked
6406 */
6407static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6408{
6409 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6410}
6411
6412/*
6413 * called with inode->i_mutex locked
6414 */
6415static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6416{
6417 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6418}
6419
6420static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6421{
6422 int len = 0;
6423 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6424 ctx, true);
6425 if (len < 0)
6426 return len;
6427 *ctxlen = len;
6428 return 0;
6429}
Michael LeMayd7200242006-06-22 14:47:17 -07006430#ifdef CONFIG_KEYS
6431
David Howellsd84f4f92008-11-14 10:39:23 +11006432static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006433 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006434{
David Howellsd84f4f92008-11-14 10:39:23 +11006435 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006436 struct key_security_struct *ksec;
6437
6438 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6439 if (!ksec)
6440 return -ENOMEM;
6441
David Howellsd84f4f92008-11-14 10:39:23 +11006442 tsec = cred->security;
6443 if (tsec->keycreate_sid)
6444 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006445 else
David Howellsd84f4f92008-11-14 10:39:23 +11006446 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006447
David Howells275bb412008-11-14 10:39:19 +11006448 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006449 return 0;
6450}
6451
6452static void selinux_key_free(struct key *k)
6453{
6454 struct key_security_struct *ksec = k->security;
6455
6456 k->security = NULL;
6457 kfree(ksec);
6458}
6459
6460static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006461 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006462 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006463{
6464 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006465 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006466 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006467
6468 /* if no specific permissions are requested, we skip the
6469 permission check. No serious, additional covert channels
6470 appear to be created. */
6471 if (perm == 0)
6472 return 0;
6473
David Howellsd84f4f92008-11-14 10:39:23 +11006474 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006475
6476 key = key_ref_to_ptr(key_ref);
6477 ksec = key->security;
6478
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006479 return avc_has_perm(&selinux_state,
6480 sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006481}
6482
David Howells70a5bb72008-04-29 01:01:26 -07006483static int selinux_key_getsecurity(struct key *key, char **_buffer)
6484{
6485 struct key_security_struct *ksec = key->security;
6486 char *context = NULL;
6487 unsigned len;
6488 int rc;
6489
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006490 rc = security_sid_to_context(&selinux_state, ksec->sid,
6491 &context, &len);
David Howells70a5bb72008-04-29 01:01:26 -07006492 if (!rc)
6493 rc = len;
6494 *_buffer = context;
6495 return rc;
6496}
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006497#endif
David Howells70a5bb72008-04-29 01:01:26 -07006498
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006499#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006500static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6501{
6502 struct common_audit_data ad;
6503 int err;
6504 u32 sid = 0;
6505 struct ib_security_struct *sec = ib_sec;
6506 struct lsm_ibpkey_audit ibpkey;
6507
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006508 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006509 if (err)
6510 return err;
6511
6512 ad.type = LSM_AUDIT_DATA_IBPKEY;
6513 ibpkey.subnet_prefix = subnet_prefix;
6514 ibpkey.pkey = pkey_val;
6515 ad.u.ibpkey = &ibpkey;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006516 return avc_has_perm(&selinux_state,
6517 sec->sid, sid,
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006518 SECCLASS_INFINIBAND_PKEY,
6519 INFINIBAND_PKEY__ACCESS, &ad);
6520}
6521
Daniel Jurgensab861df2017-05-19 15:48:58 +03006522static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6523 u8 port_num)
6524{
6525 struct common_audit_data ad;
6526 int err;
6527 u32 sid = 0;
6528 struct ib_security_struct *sec = ib_sec;
6529 struct lsm_ibendport_audit ibendport;
6530
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006531 err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
6532 &sid);
Daniel Jurgensab861df2017-05-19 15:48:58 +03006533
6534 if (err)
6535 return err;
6536
6537 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6538 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6539 ibendport.port = port_num;
6540 ad.u.ibendport = &ibendport;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006541 return avc_has_perm(&selinux_state,
6542 sec->sid, sid,
Daniel Jurgensab861df2017-05-19 15:48:58 +03006543 SECCLASS_INFINIBAND_ENDPORT,
6544 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6545}
6546
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006547static int selinux_ib_alloc_security(void **ib_sec)
6548{
6549 struct ib_security_struct *sec;
6550
6551 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6552 if (!sec)
6553 return -ENOMEM;
6554 sec->sid = current_sid();
6555
6556 *ib_sec = sec;
6557 return 0;
6558}
6559
6560static void selinux_ib_free_security(void *ib_sec)
6561{
6562 kfree(ib_sec);
6563}
Michael LeMayd7200242006-06-22 14:47:17 -07006564#endif
6565
Chenbo Fengec27c352017-10-18 13:00:25 -07006566#ifdef CONFIG_BPF_SYSCALL
6567static int selinux_bpf(int cmd, union bpf_attr *attr,
6568 unsigned int size)
6569{
6570 u32 sid = current_sid();
6571 int ret;
6572
6573 switch (cmd) {
6574 case BPF_MAP_CREATE:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006575 ret = avc_has_perm(&selinux_state,
6576 sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
Chenbo Fengec27c352017-10-18 13:00:25 -07006577 NULL);
6578 break;
6579 case BPF_PROG_LOAD:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006580 ret = avc_has_perm(&selinux_state,
6581 sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
Chenbo Fengec27c352017-10-18 13:00:25 -07006582 NULL);
6583 break;
6584 default:
6585 ret = 0;
6586 break;
6587 }
6588
6589 return ret;
6590}
6591
6592static u32 bpf_map_fmode_to_av(fmode_t fmode)
6593{
6594 u32 av = 0;
6595
6596 if (fmode & FMODE_READ)
6597 av |= BPF__MAP_READ;
6598 if (fmode & FMODE_WRITE)
6599 av |= BPF__MAP_WRITE;
6600 return av;
6601}
6602
Chenbo Fengf66e4482017-10-18 13:00:26 -07006603/* This function will check the file pass through unix socket or binder to see
6604 * if it is a bpf related object. And apply correspinding checks on the bpf
6605 * object based on the type. The bpf maps and programs, not like other files and
6606 * socket, are using a shared anonymous inode inside the kernel as their inode.
6607 * So checking that inode cannot identify if the process have privilege to
6608 * access the bpf object and that's why we have to add this additional check in
6609 * selinux_file_receive and selinux_binder_transfer_files.
6610 */
6611static int bpf_fd_pass(struct file *file, u32 sid)
6612{
6613 struct bpf_security_struct *bpfsec;
6614 struct bpf_prog *prog;
6615 struct bpf_map *map;
6616 int ret;
6617
6618 if (file->f_op == &bpf_map_fops) {
6619 map = file->private_data;
6620 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006621 ret = avc_has_perm(&selinux_state,
6622 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006623 bpf_map_fmode_to_av(file->f_mode), NULL);
6624 if (ret)
6625 return ret;
6626 } else if (file->f_op == &bpf_prog_fops) {
6627 prog = file->private_data;
6628 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006629 ret = avc_has_perm(&selinux_state,
6630 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006631 BPF__PROG_RUN, NULL);
6632 if (ret)
6633 return ret;
6634 }
6635 return 0;
6636}
6637
Chenbo Fengec27c352017-10-18 13:00:25 -07006638static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6639{
6640 u32 sid = current_sid();
6641 struct bpf_security_struct *bpfsec;
6642
6643 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006644 return avc_has_perm(&selinux_state,
6645 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006646 bpf_map_fmode_to_av(fmode), NULL);
6647}
6648
6649static int selinux_bpf_prog(struct bpf_prog *prog)
6650{
6651 u32 sid = current_sid();
6652 struct bpf_security_struct *bpfsec;
6653
6654 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006655 return avc_has_perm(&selinux_state,
6656 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006657 BPF__PROG_RUN, NULL);
6658}
6659
6660static int selinux_bpf_map_alloc(struct bpf_map *map)
6661{
6662 struct bpf_security_struct *bpfsec;
6663
6664 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6665 if (!bpfsec)
6666 return -ENOMEM;
6667
6668 bpfsec->sid = current_sid();
6669 map->security = bpfsec;
6670
6671 return 0;
6672}
6673
6674static void selinux_bpf_map_free(struct bpf_map *map)
6675{
6676 struct bpf_security_struct *bpfsec = map->security;
6677
6678 map->security = NULL;
6679 kfree(bpfsec);
6680}
6681
6682static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6683{
6684 struct bpf_security_struct *bpfsec;
6685
6686 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6687 if (!bpfsec)
6688 return -ENOMEM;
6689
6690 bpfsec->sid = current_sid();
6691 aux->security = bpfsec;
6692
6693 return 0;
6694}
6695
6696static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6697{
6698 struct bpf_security_struct *bpfsec = aux->security;
6699
6700 aux->security = NULL;
6701 kfree(bpfsec);
6702}
6703#endif
6704
James Morrisca97d932017-02-15 00:18:51 +11006705static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006706 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6707 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6708 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6709 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006710
Casey Schauflere20b0432015-05-02 15:11:36 -07006711 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6712 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6713 LSM_HOOK_INIT(capget, selinux_capget),
6714 LSM_HOOK_INIT(capset, selinux_capset),
6715 LSM_HOOK_INIT(capable, selinux_capable),
6716 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6717 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6718 LSM_HOOK_INIT(syslog, selinux_syslog),
6719 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006720
Casey Schauflere20b0432015-05-02 15:11:36 -07006721 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722
Casey Schauflere20b0432015-05-02 15:11:36 -07006723 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6724 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6725 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006726
Casey Schauflere20b0432015-05-02 15:11:36 -07006727 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6728 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
Al Viro5b400232018-12-12 20:13:29 -05006729 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
Al Viro204cc0c2018-12-13 13:41:47 -05006730 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
Casey Schauflere20b0432015-05-02 15:11:36 -07006731 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6732 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6733 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6734 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6735 LSM_HOOK_INIT(sb_mount, selinux_mount),
6736 LSM_HOOK_INIT(sb_umount, selinux_umount),
6737 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6738 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
6739 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006740
Casey Schauflere20b0432015-05-02 15:11:36 -07006741 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006742 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006743
Casey Schauflere20b0432015-05-02 15:11:36 -07006744 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6745 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6746 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6747 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6748 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6749 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6750 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6751 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6752 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6753 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6754 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6755 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6756 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6757 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6758 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6759 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6760 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6761 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6762 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6763 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6764 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6765 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6766 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6767 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6768 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006769 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006770 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006771
Casey Schauflere20b0432015-05-02 15:11:36 -07006772 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6773 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6774 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6775 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6776 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6777 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6778 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6779 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6780 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6781 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6782 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6783 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006784
Casey Schauflere20b0432015-05-02 15:11:36 -07006785 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006786
Tetsuo Handaa79be232017-03-28 23:08:45 +09006787 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07006788 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6789 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6790 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6791 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
Matthew Garrett3ec30112018-01-08 13:36:19 -08006792 LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
Casey Schauflere20b0432015-05-02 15:11:36 -07006793 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6794 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6795 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04006796 LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006797 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006798 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6799 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6800 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6801 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6802 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6803 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6804 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05006805 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07006806 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6807 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6808 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6809 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6810 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07006811 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006812
Casey Schauflere20b0432015-05-02 15:11:36 -07006813 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6814 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815
Casey Schauflere20b0432015-05-02 15:11:36 -07006816 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6817 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006818
Casey Schauflere20b0432015-05-02 15:11:36 -07006819 LSM_HOOK_INIT(msg_queue_alloc_security,
6820 selinux_msg_queue_alloc_security),
6821 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6822 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6823 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6824 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6825 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826
Casey Schauflere20b0432015-05-02 15:11:36 -07006827 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6828 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6829 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6830 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6831 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006832
Casey Schauflere20b0432015-05-02 15:11:36 -07006833 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6834 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6835 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6836 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6837 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838
Casey Schauflere20b0432015-05-02 15:11:36 -07006839 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006840
Casey Schauflere20b0432015-05-02 15:11:36 -07006841 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6842 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843
Casey Schauflere20b0432015-05-02 15:11:36 -07006844 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6845 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6846 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6847 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006848 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006849 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6850 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6851 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006852
Casey Schauflere20b0432015-05-02 15:11:36 -07006853 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6854 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006855
Casey Schauflere20b0432015-05-02 15:11:36 -07006856 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6857 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
David Herrmann0b811db2018-05-04 16:28:21 +02006858 LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
Casey Schauflere20b0432015-05-02 15:11:36 -07006859 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6860 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6861 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6862 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6863 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6864 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6865 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6866 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6867 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6868 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6869 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6870 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6871 LSM_HOOK_INIT(socket_getpeersec_stream,
6872 selinux_socket_getpeersec_stream),
6873 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6874 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6875 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6876 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6877 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6878 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
Richard Hainesd4529302018-02-13 20:57:18 +00006879 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
6880 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
6881 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
Casey Schauflere20b0432015-05-02 15:11:36 -07006882 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6883 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6884 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6885 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6886 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6887 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6888 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6889 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6890 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6891 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6892 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6893 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6894 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006895#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006896 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03006897 LSM_HOOK_INIT(ib_endport_manage_subnet,
6898 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006899 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6900 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6901#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006902#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006903 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6904 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6905 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6906 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6907 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6908 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6909 selinux_xfrm_state_alloc_acquire),
6910 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6911 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6912 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6913 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6914 selinux_xfrm_state_pol_flow_match),
6915 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006916#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006917
6918#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006919 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6920 LSM_HOOK_INIT(key_free, selinux_key_free),
6921 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6922 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006923#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006924
6925#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006926 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6927 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6928 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6929 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006930#endif
Chenbo Fengec27c352017-10-18 13:00:25 -07006931
6932#ifdef CONFIG_BPF_SYSCALL
6933 LSM_HOOK_INIT(bpf, selinux_bpf),
6934 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
6935 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
6936 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
6937 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
6938 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
6939 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
6940#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006941};
6942
6943static __init int selinux_init(void)
6944{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006945 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006946 selinux_enabled = 0;
6947 return 0;
6948 }
6949
Linus Torvalds1da177e2005-04-16 15:20:36 -07006950 if (!selinux_enabled) {
peter enderborgc103a912018-06-12 10:09:03 +02006951 pr_info("SELinux: Disabled at boot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006952 return 0;
6953 }
6954
peter enderborgc103a912018-06-12 10:09:03 +02006955 pr_info("SELinux: Initializing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006956
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006957 memset(&selinux_state, 0, sizeof(selinux_state));
Paul Mooree5a5ca92018-03-01 17:38:30 -05006958 enforcing_set(&selinux_state, selinux_enforcing_boot);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006959 selinux_state.checkreqprot = selinux_checkreqprot_boot;
6960 selinux_ss_init(&selinux_state.ss);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006961 selinux_avc_init(&selinux_state.avc);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006962
Linus Torvalds1da177e2005-04-16 15:20:36 -07006963 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006964 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006965
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006966 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6967
James Morris7cae7e22006-03-22 00:09:22 -08006968 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6969 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006970 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006971 file_security_cache = kmem_cache_create("selinux_file_security",
6972 sizeof(struct file_security_struct),
6973 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006974 avc_init();
6975
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006976 avtab_cache_init();
6977
6978 ebitmap_cache_init();
6979
6980 hashtab_cache_init();
6981
Casey Schauflerd69dece52017-01-18 17:09:05 -08006982 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006983
Paul Moore615e51f2014-06-26 14:33:56 -04006984 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6985 panic("SELinux: Unable to register AVC netcache callback\n");
6986
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03006987 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6988 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6989
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006990 if (selinux_enforcing_boot)
peter enderborgc103a912018-06-12 10:09:03 +02006991 pr_debug("SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006992 else
peter enderborgc103a912018-06-12 10:09:03 +02006993 pr_debug("SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006994
Linus Torvalds1da177e2005-04-16 15:20:36 -07006995 return 0;
6996}
6997
Al Viroe8c26252010-03-23 06:36:54 -04006998static void delayed_superblock_init(struct super_block *sb, void *unused)
6999{
Al Viro204cc0c2018-12-13 13:41:47 -05007000 selinux_set_mnt_opts(sb, NULL, 0, NULL);
Al Viroe8c26252010-03-23 06:36:54 -04007001}
7002
Linus Torvalds1da177e2005-04-16 15:20:36 -07007003void selinux_complete_init(void)
7004{
peter enderborgc103a912018-06-12 10:09:03 +02007005 pr_debug("SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007006
7007 /* Set up any superblocks initialized prior to the policy load. */
peter enderborgc103a912018-06-12 10:09:03 +02007008 pr_debug("SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04007009 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010}
7011
7012/* SELinux requires early initialization in order to label
7013 all processes and objects when they are created. */
Kees Cook3d6e5f62018-10-10 17:18:23 -07007014DEFINE_LSM(selinux) = {
Kees Cook07aed2f2018-10-10 17:18:24 -07007015 .name = "selinux",
Kees Cook3d6e5f62018-10-10 17:18:23 -07007016 .init = selinux_init,
7017};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007018
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007019#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007020
Florian Westphal591bb272017-07-26 11:40:52 +02007021static const struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05007022 {
7023 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007024 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007025 .hooknum = NF_INET_POST_ROUTING,
7026 .priority = NF_IP_PRI_SELINUX_LAST,
7027 },
7028 {
7029 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007030 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007031 .hooknum = NF_INET_FORWARD,
7032 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04007033 },
7034 {
7035 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00007036 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04007037 .hooknum = NF_INET_LOCAL_OUT,
7038 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007039 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04007040#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05007041 {
7042 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007043 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007044 .hooknum = NF_INET_POST_ROUTING,
7045 .priority = NF_IP6_PRI_SELINUX_LAST,
7046 },
7047 {
7048 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007049 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007050 .hooknum = NF_INET_FORWARD,
7051 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007052 },
Huw Davies2917f572016-06-27 15:06:15 -04007053 {
7054 .hook = selinux_ipv6_output,
7055 .pf = NFPROTO_IPV6,
7056 .hooknum = NF_INET_LOCAL_OUT,
7057 .priority = NF_IP6_PRI_SELINUX_FIRST,
7058 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02007060};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007061
Florian Westphal8e71bf72017-04-21 11:49:09 +02007062static int __net_init selinux_nf_register(struct net *net)
7063{
7064 return nf_register_net_hooks(net, selinux_nf_ops,
7065 ARRAY_SIZE(selinux_nf_ops));
7066}
7067
7068static void __net_exit selinux_nf_unregister(struct net *net)
7069{
7070 nf_unregister_net_hooks(net, selinux_nf_ops,
7071 ARRAY_SIZE(selinux_nf_ops));
7072}
7073
7074static struct pernet_operations selinux_net_ops = {
7075 .init = selinux_nf_register,
7076 .exit = selinux_nf_unregister,
7077};
7078
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079static int __init selinux_nf_ip_init(void)
7080{
Jiri Pirko25db6be2014-09-03 17:42:13 +02007081 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082
7083 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02007084 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05007085
peter enderborgc103a912018-06-12 10:09:03 +02007086 pr_debug("SELinux: Registering netfilter hooks\n");
Eric Parisfadcdb42007-02-22 18:11:31 -05007087
Florian Westphal8e71bf72017-04-21 11:49:09 +02007088 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07007089 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02007090 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091
Jiri Pirko25db6be2014-09-03 17:42:13 +02007092 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007093}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094__initcall(selinux_nf_ip_init);
7095
7096#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7097static void selinux_nf_ip_exit(void)
7098{
peter enderborgc103a912018-06-12 10:09:03 +02007099 pr_debug("SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100
Florian Westphal8e71bf72017-04-21 11:49:09 +02007101 unregister_pernet_subsys(&selinux_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007102}
7103#endif
7104
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007105#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
7107#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7108#define selinux_nf_ip_exit()
7109#endif
7110
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007111#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112
7113#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007114int selinux_disable(struct selinux_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007115{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007116 if (state->initialized) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117 /* Not permitted after initial policy load. */
7118 return -EINVAL;
7119 }
7120
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007121 if (state->disabled) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007122 /* Only do this once. */
7123 return -EINVAL;
7124 }
7125
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007126 state->disabled = 1;
7127
peter enderborgc103a912018-06-12 10:09:03 +02007128 pr_info("SELinux: Disabled at runtime.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007129
Stephen Smalley30d55282006-05-03 10:52:36 -04007130 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007131
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07007132 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007133
Eric Parisaf8ff042009-09-20 21:23:01 -04007134 /* Try to destroy the avc node cache */
7135 avc_disable();
7136
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137 /* Unregister netfilter hooks. */
7138 selinux_nf_ip_exit();
7139
7140 /* Unregister selinuxfs. */
7141 exit_sel_fs();
7142
7143 return 0;
7144}
7145#endif