blob: beec1de5c2dae263f08a33c2fce800f53036aece [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
Kees Cookbe6ec882018-10-01 17:08:57 -0700124int selinux_enabled __lsm_ro_after_init = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126static int __init selinux_enabled_setup(char *str)
127{
Eric Parisf5269712008-05-14 11:27:45 -0400128 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900129 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400130 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 return 1;
132}
133__setup("selinux=", selinux_enabled_setup);
134#endif
135
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500136static unsigned int selinux_checkreqprot_boot =
137 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
138
139static int __init checkreqprot_setup(char *str)
140{
141 unsigned long checkreqprot;
142
143 if (!kstrtoul(str, 0, &checkreqprot))
144 selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
145 return 1;
146}
147__setup("checkreqprot=", checkreqprot_setup);
148
Christoph Lametere18b8902006-12-06 20:33:20 -0800149static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400150static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800151
Paul Moored621d352008-01-29 08:43:36 -0500152/**
153 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
154 *
155 * Description:
156 * This function checks the SECMARK reference counter to see if any SECMARK
157 * targets are currently configured, if the reference counter is greater than
158 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400159 * enabled, false (0) if SECMARK is disabled. If the always_check_network
160 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500161 *
162 */
163static int selinux_secmark_enabled(void)
164{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500165 return (selinux_policycap_alwaysnetwork() ||
166 atomic_read(&selinux_secmark_refcount));
Chris PeBenito2be4d742013-05-03 09:05:39 -0400167}
168
169/**
170 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
171 *
172 * Description:
173 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
174 * (1) if any are enabled or false (0) if neither are enabled. If the
175 * always_check_network policy capability is enabled, peer labeling
176 * is always considered enabled.
177 *
178 */
179static int selinux_peerlbl_enabled(void)
180{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500181 return (selinux_policycap_alwaysnetwork() ||
182 netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500183}
184
Paul Moore615e51f2014-06-26 14:33:56 -0400185static int selinux_netcache_avc_callback(u32 event)
186{
187 if (event == AVC_CALLBACK_RESET) {
188 sel_netif_flush();
189 sel_netnode_flush();
190 sel_netport_flush();
191 synchronize_net();
192 }
193 return 0;
194}
195
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300196static int selinux_lsm_notifier_avc_callback(u32 event)
197{
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300198 if (event == AVC_CALLBACK_RESET) {
199 sel_ib_pkey_flush();
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300200 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300201 }
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300202
203 return 0;
204}
205
David Howellsd84f4f92008-11-14 10:39:23 +1100206/*
207 * initialise the security for the init task
208 */
209static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
David Howells3b11a1d2008-11-14 10:39:26 +1100211 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 struct task_security_struct *tsec;
213
James Morris89d155e2005-10-30 14:59:21 -0800214 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100216 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
David Howellsd84f4f92008-11-14 10:39:23 +1100218 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100219 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
221
David Howells275bb412008-11-14 10:39:19 +1100222/*
David Howells88e67f32008-11-14 10:39:21 +1100223 * get the security ID of a set of credentials
224 */
225static inline u32 cred_sid(const struct cred *cred)
226{
227 const struct task_security_struct *tsec;
228
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700229 tsec = selinux_cred(cred);
David Howells88e67f32008-11-14 10:39:21 +1100230 return tsec->sid;
231}
232
233/*
David Howells3b11a1d2008-11-14 10:39:26 +1100234 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100235 */
236static inline u32 task_sid(const struct task_struct *task)
237{
David Howells275bb412008-11-14 10:39:19 +1100238 u32 sid;
239
240 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100241 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100242 rcu_read_unlock();
243 return sid;
244}
245
David Howells88e67f32008-11-14 10:39:21 +1100246/* Allocate and free functions for each kind of security blob. */
247
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248static int inode_alloc_security(struct inode *inode)
249{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100251 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Josef Bacika02fe132008-04-04 09:35:05 +1100253 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 if (!isec)
255 return -ENOMEM;
256
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +0100257 spin_lock_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 isec->inode = inode;
260 isec->sid = SECINITSID_UNLABELED;
261 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100262 isec->task_sid = sid;
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100263 isec->initialized = LABEL_INVALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 inode->i_security = isec;
265
266 return 0;
267}
268
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500269static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
270
271/*
272 * Try reloading inode security labels that have been marked as invalid. The
273 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100274 * allowed; when set to false, returns -ECHILD when the label is
Al Viroe9193282018-04-24 21:31:02 -0400275 * invalid. The @dentry parameter should be set to a dentry of the inode.
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500276 */
277static int __inode_security_revalidate(struct inode *inode,
Al Viroe9193282018-04-24 21:31:02 -0400278 struct dentry *dentry,
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500279 bool may_sleep)
280{
281 struct inode_security_struct *isec = inode->i_security;
282
283 might_sleep_if(may_sleep);
284
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500285 if (selinux_state.initialized &&
286 isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500287 if (!may_sleep)
288 return -ECHILD;
289
290 /*
291 * Try reloading the inode security label. This will fail if
292 * @opt_dentry is NULL and no dentry for this inode can be
293 * found; in that case, continue using the old label.
294 */
Al Viroe9193282018-04-24 21:31:02 -0400295 inode_doinit_with_dentry(inode, dentry);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500296 }
297 return 0;
298}
299
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500300static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
301{
302 return inode->i_security;
303}
304
305static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
306{
307 int error;
308
309 error = __inode_security_revalidate(inode, NULL, !rcu);
310 if (error)
311 return ERR_PTR(error);
312 return inode->i_security;
313}
314
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500315/*
316 * Get the security label of an inode.
317 */
318static struct inode_security_struct *inode_security(struct inode *inode)
319{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500320 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500321 return inode->i_security;
322}
323
Paul Moore2c971652016-04-19 16:36:28 -0400324static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
325{
326 struct inode *inode = d_backing_inode(dentry);
327
328 return inode->i_security;
329}
330
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500331/*
332 * Get the security label of a dentry's backing inode.
333 */
334static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
335{
336 struct inode *inode = d_backing_inode(dentry);
337
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500338 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500339 return inode->i_security;
340}
341
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500342static void inode_free_rcu(struct rcu_head *head)
343{
344 struct inode_security_struct *isec;
345
346 isec = container_of(head, struct inode_security_struct, rcu);
347 kmem_cache_free(sel_inode_cache, isec);
348}
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350static void inode_free_security(struct inode *inode)
351{
352 struct inode_security_struct *isec = inode->i_security;
353 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
354
Waiman Long9629d042015-07-10 17:19:56 -0400355 /*
356 * As not all inode security structures are in a list, we check for
357 * empty list outside of the lock to make sure that we won't waste
358 * time taking a lock doing nothing.
359 *
360 * The list_del_init() function can be safely called more than once.
361 * It should not be possible for this function to be called with
362 * concurrent list_add(), but for better safety against future changes
363 * in the code, we use list_empty_careful() here.
364 */
365 if (!list_empty_careful(&isec->list)) {
366 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400368 spin_unlock(&sbsec->isec_lock);
369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500371 /*
372 * The inode may still be referenced in a path walk and
373 * a call to selinux_inode_permission() can be made
374 * after inode_free_security() is called. Ideally, the VFS
375 * wouldn't do this, but fixing that is a much harder
376 * job. For now, simply free the i_security via RCU, and
377 * leave the current inode->i_security pointer intact.
378 * The inode will be freed after the RCU grace period too.
379 */
380 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
382
383static int file_alloc_security(struct file *file)
384{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100386 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Sangwoo63205652015-10-21 17:44:30 -0400388 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (!fsec)
390 return -ENOMEM;
391
David Howells275bb412008-11-14 10:39:19 +1100392 fsec->sid = sid;
393 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 file->f_security = fsec;
395
396 return 0;
397}
398
399static void file_free_security(struct file *file)
400{
401 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400403 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404}
405
406static int superblock_alloc_security(struct super_block *sb)
407{
408 struct superblock_security_struct *sbsec;
409
James Morris89d155e2005-10-30 14:59:21 -0800410 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (!sbsec)
412 return -ENOMEM;
413
Eric Parisbc7e9822006-09-25 23:32:02 -0700414 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 INIT_LIST_HEAD(&sbsec->isec_head);
416 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 sbsec->sb = sb;
418 sbsec->sid = SECINITSID_UNLABELED;
419 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700420 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 sb->s_security = sbsec;
422
423 return 0;
424}
425
426static void superblock_free_security(struct super_block *sb)
427{
428 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 sb->s_security = NULL;
430 kfree(sbsec);
431}
432
Al Virobd323652018-12-13 15:04:59 -0500433struct selinux_mnt_opts {
434 const char *fscontext, *context, *rootcontext, *defcontext;
435};
436
Al Viro204cc0c2018-12-13 13:41:47 -0500437static void selinux_free_mnt_opts(void *mnt_opts)
438{
Al Virobd323652018-12-13 15:04:59 -0500439 struct selinux_mnt_opts *opts = mnt_opts;
440 kfree(opts->fscontext);
441 kfree(opts->context);
442 kfree(opts->rootcontext);
443 kfree(opts->defcontext);
Al Viro204cc0c2018-12-13 13:41:47 -0500444 kfree(opts);
445}
446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447static inline int inode_doinit(struct inode *inode)
448{
449 return inode_doinit_with_dentry(inode, NULL);
450}
451
452enum {
Eric Paris31e87932007-09-19 17:19:12 -0400453 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 Opt_context = 1,
455 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500456 Opt_defcontext = 3,
457 Opt_rootcontext = 4,
Al Viroda3d76a2018-12-17 10:14:16 -0500458 Opt_seclabel = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459};
460
Al Viroda3d76a2018-12-17 10:14:16 -0500461#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
Al Viro169d68efb2018-12-14 22:44:50 -0500462static struct {
463 const char *name;
464 int len;
465 int opt;
466 bool has_arg;
467} tokens[] = {
Al Viroda3d76a2018-12-17 10:14:16 -0500468 A(context, true),
469 A(fscontext, true),
470 A(defcontext, true),
471 A(rootcontext, true),
472 A(seclabel, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473};
Al Viro169d68efb2018-12-14 22:44:50 -0500474#undef A
475
476static int match_opt_prefix(char *s, int l, char **arg)
477{
478 int i;
479
480 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
481 size_t len = tokens[i].len;
482 if (len > l || memcmp(s, tokens[i].name, len))
483 continue;
484 if (tokens[i].has_arg) {
485 if (len == l || s[len] != '=')
486 continue;
487 *arg = s + len + 1;
488 } else if (len != l)
489 continue;
490 return tokens[i].opt;
491 }
492 return Opt_error;
493}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
495#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
496
Eric Parisc312feb2006-07-10 04:43:53 -0700497static int may_context_mount_sb_relabel(u32 sid,
498 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100499 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700500{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700501 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Parisc312feb2006-07-10 04:43:53 -0700502 int rc;
503
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500504 rc = avc_has_perm(&selinux_state,
505 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700506 FILESYSTEM__RELABELFROM, NULL);
507 if (rc)
508 return rc;
509
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500510 rc = avc_has_perm(&selinux_state,
511 tsec->sid, sid, SECCLASS_FILESYSTEM,
Eric Parisc312feb2006-07-10 04:43:53 -0700512 FILESYSTEM__RELABELTO, NULL);
513 return rc;
514}
515
Eric Paris08089252006-07-10 04:43:55 -0700516static int may_context_mount_inode_relabel(u32 sid,
517 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100518 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700519{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -0700520 const struct task_security_struct *tsec = selinux_cred(cred);
Eric Paris08089252006-07-10 04:43:55 -0700521 int rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500522 rc = avc_has_perm(&selinux_state,
523 tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700524 FILESYSTEM__RELABELFROM, NULL);
525 if (rc)
526 return rc;
527
Stephen Smalley6b6bc622018-03-05 11:47:56 -0500528 rc = avc_has_perm(&selinux_state,
529 sid, sbsec->sid, SECCLASS_FILESYSTEM,
Eric Paris08089252006-07-10 04:43:55 -0700530 FILESYSTEM__ASSOCIATE, NULL);
531 return rc;
532}
533
Eric Parisb43e7252012-10-10 14:27:35 -0400534static int selinux_is_sblabel_mnt(struct super_block *sb)
535{
536 struct superblock_security_struct *sbsec = sb->s_security;
537
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500538 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
539 sbsec->behavior == SECURITY_FS_USE_TRANS ||
540 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400541 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500542 /* Special handling. Genfs but also in-core setxattr handler */
543 !strcmp(sb->s_type->name, "sysfs") ||
544 !strcmp(sb->s_type->name, "pstore") ||
545 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500546 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500547 !strcmp(sb->s_type->name, "rootfs") ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500548 (selinux_policycap_cgroupseclabel() &&
Stephen Smalley2651225b2017-02-28 10:35:56 -0500549 (!strcmp(sb->s_type->name, "cgroup") ||
550 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400551}
552
Eric Parisc9180a52007-11-30 13:00:35 -0500553static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
555 struct superblock_security_struct *sbsec = sb->s_security;
556 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000557 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 int rc = 0;
559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
561 /* Make sure that the xattr handler exists and that no
562 error other than -ENODATA is returned by getxattr on
563 the root directory. -ENODATA is ok, as this may be
564 the first boot of the SELinux kernel before we have
565 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200566 if (!(root_inode->i_opflags & IOP_XATTR)) {
peter enderborgc103a912018-06-12 10:09:03 +0200567 pr_warn("SELinux: (dev %s, type %s) has no "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800568 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 rc = -EOPNOTSUPP;
570 goto out;
571 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200572
573 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 if (rc < 0 && rc != -ENODATA) {
575 if (rc == -EOPNOTSUPP)
peter enderborgc103a912018-06-12 10:09:03 +0200576 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800577 "%s) has no security xattr handler\n",
578 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 else
peter enderborgc103a912018-06-12 10:09:03 +0200580 pr_warn("SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800581 "%s) getxattr errno %d\n", sb->s_id,
582 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 goto out;
584 }
585 }
586
Eric Pariseadcabc2012-08-24 15:59:14 -0400587 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400588
589 /*
590 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
591 * leave the flag untouched because sb_clone_mnt_opts might be handing
592 * us a superblock that needs the flag to be cleared.
593 */
Eric Parisb43e7252012-10-10 14:27:35 -0400594 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400595 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400596 else
597 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400598
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500600 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 /* Initialize any other inodes associated with the superblock, e.g.
603 inodes created prior to initial policy load or inodes created
604 during get_sb by a pseudo filesystem that directly
605 populates itself. */
606 spin_lock(&sbsec->isec_lock);
Al Viro8d641242018-12-10 15:34:12 -0500607 while (!list_empty(&sbsec->isec_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 struct inode_security_struct *isec =
Al Viro8d641242018-12-10 15:34:12 -0500609 list_first_entry(&sbsec->isec_head,
Eric Parisc9180a52007-11-30 13:00:35 -0500610 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400612 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 spin_unlock(&sbsec->isec_lock);
614 inode = igrab(inode);
615 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500616 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 inode_doinit(inode);
618 iput(inode);
619 }
620 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 }
622 spin_unlock(&sbsec->isec_lock);
623out:
Eric Parisc9180a52007-11-30 13:00:35 -0500624 return rc;
625}
626
Eric Parisc9180a52007-11-30 13:00:35 -0500627static int bad_option(struct superblock_security_struct *sbsec, char flag,
628 u32 old_sid, u32 new_sid)
629{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500630 char mnt_flags = sbsec->flags & SE_MNTMASK;
631
Eric Parisc9180a52007-11-30 13:00:35 -0500632 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500633 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500634 if (!(sbsec->flags & flag) ||
635 (old_sid != new_sid))
636 return 1;
637
638 /* check if we were passed the same options twice,
639 * aka someone passed context=a,context=b
640 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500641 if (!(sbsec->flags & SE_SBINITIALIZED))
642 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500643 return 1;
644 return 0;
645}
Eric Parise0007522008-03-05 10:31:54 -0500646
Al Virobd323652018-12-13 15:04:59 -0500647static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
648{
649 int rc = security_context_str_to_sid(&selinux_state, s,
650 sid, GFP_KERNEL);
651 if (rc)
652 pr_warn("SELinux: security_context_str_to_sid"
653 "(%s) failed for (dev %s, type %s) errno=%d\n",
654 s, sb->s_id, sb->s_type->name, rc);
655 return rc;
656}
657
Eric Parisc9180a52007-11-30 13:00:35 -0500658/*
659 * Allow filesystems with binary mount data to explicitly set mount point
660 * labeling information.
661 */
Eric Parise0007522008-03-05 10:31:54 -0500662static int selinux_set_mnt_opts(struct super_block *sb,
Al Viro204cc0c2018-12-13 13:41:47 -0500663 void *mnt_opts,
David Quigley649f6e72013-05-22 12:50:36 -0400664 unsigned long kern_flags,
665 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500666{
David Howells275bb412008-11-14 10:39:19 +1100667 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500668 struct superblock_security_struct *sbsec = sb->s_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500669 struct dentry *root = sbsec->sb->s_root;
Al Virobd323652018-12-13 15:04:59 -0500670 struct selinux_mnt_opts *opts = mnt_opts;
Paul Moore2c971652016-04-19 16:36:28 -0400671 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500672 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
673 u32 defcontext_sid = 0;
Al Virobd323652018-12-13 15:04:59 -0500674 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500675
676 mutex_lock(&sbsec->lock);
677
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500678 if (!selinux_state.initialized) {
Al Virobd323652018-12-13 15:04:59 -0500679 if (!opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500680 /* Defer initialization until selinux_complete_init,
681 after the initial policy is loaded and the security
682 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500683 goto out;
684 }
685 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200686 pr_warn("SELinux: Unable to set superblock options "
Eric Paris744ba352008-04-17 11:52:44 -0400687 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500688 goto out;
689 }
David Quigley649f6e72013-05-22 12:50:36 -0400690 if (kern_flags && !set_kern_flags) {
691 /* Specifying internal flags without providing a place to
692 * place the results is not allowed */
693 rc = -EINVAL;
694 goto out;
695 }
Eric Parisc9180a52007-11-30 13:00:35 -0500696
697 /*
Eric Parise0007522008-03-05 10:31:54 -0500698 * Binary mount data FS will come through this function twice. Once
699 * from an explicit call and once from the generic calls from the vfs.
700 * Since the generic VFS calls will not contain any security mount data
701 * we need to skip the double mount verification.
702 *
703 * This does open a hole in which we will not notice if the first
704 * mount using this sb set explict options and a second mount using
705 * this sb does not set any security options. (The first options
706 * will be used for both mounts)
707 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500708 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Al Virobd323652018-12-13 15:04:59 -0500709 && !opts)
Eric Parisf5269712008-05-14 11:27:45 -0400710 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500711
Paul Moore2c971652016-04-19 16:36:28 -0400712 root_isec = backing_inode_security_novalidate(root);
713
Eric Parise0007522008-03-05 10:31:54 -0500714 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500715 * parse the mount options, check if they are valid sids.
716 * also check if someone is trying to mount the same sb more
717 * than once with different security options.
718 */
Al Virobd323652018-12-13 15:04:59 -0500719 if (opts) {
720 if (opts->fscontext) {
721 rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
722 if (rc)
723 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500724 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
725 fscontext_sid))
726 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500727 sbsec->flags |= FSCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500728 }
729 if (opts->context) {
730 rc = parse_sid(sb, opts->context, &context_sid);
731 if (rc)
732 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500733 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
734 context_sid))
735 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500736 sbsec->flags |= CONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500737 }
738 if (opts->rootcontext) {
739 rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
740 if (rc)
741 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500742 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
743 rootcontext_sid))
744 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500745 sbsec->flags |= ROOTCONTEXT_MNT;
Al Virobd323652018-12-13 15:04:59 -0500746 }
747 if (opts->defcontext) {
748 rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
749 if (rc)
750 goto out;
Eric Parisc9180a52007-11-30 13:00:35 -0500751 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
752 defcontext_sid))
753 goto out_double_mount;
Eric Parisc9180a52007-11-30 13:00:35 -0500754 sbsec->flags |= DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500755 }
756 }
757
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500758 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500759 /* previously mounted with options, but not on this attempt? */
Al Virobd323652018-12-13 15:04:59 -0500760 if ((sbsec->flags & SE_MNTMASK) && !opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500761 goto out_double_mount;
762 rc = 0;
763 goto out;
764 }
765
James Morris089be432008-07-15 18:32:49 +1000766 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400767 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
768
Stephen Smalley8e014722015-06-04 16:22:17 -0400769 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700770 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley8e014722015-06-04 16:22:17 -0400771 !strcmp(sb->s_type->name, "sysfs") ||
Antonio Murdaca901ef842017-02-09 17:02:42 +0100772 !strcmp(sb->s_type->name, "pstore") ||
773 !strcmp(sb->s_type->name, "cgroup") ||
774 !strcmp(sb->s_type->name, "cgroup2"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400775 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500776
David Quigleyeb9ae682013-05-22 12:50:37 -0400777 if (!sbsec->behavior) {
778 /*
779 * Determine the labeling behavior to use for this
780 * filesystem type.
781 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500782 rc = security_fs_use(&selinux_state, sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400783 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +0200784 pr_warn("%s: security_fs_use(%s) returned %d\n",
David Quigleyeb9ae682013-05-22 12:50:37 -0400785 __func__, sb->s_type->name, rc);
786 goto out;
787 }
Eric Parisc9180a52007-11-30 13:00:35 -0500788 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500789
790 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500791 * If this is a user namespace mount and the filesystem type is not
792 * explicitly whitelisted, then no contexts are allowed on the command
793 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500794 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500795 if (sb->s_user_ns != &init_user_ns &&
796 strcmp(sb->s_type->name, "tmpfs") &&
797 strcmp(sb->s_type->name, "ramfs") &&
798 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500799 if (context_sid || fscontext_sid || rootcontext_sid ||
800 defcontext_sid) {
801 rc = -EACCES;
802 goto out;
803 }
804 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
805 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500806 rc = security_transition_sid(&selinux_state,
807 current_sid(),
808 current_sid(),
Seth Forsheeaad82892016-04-26 14:36:20 -0500809 SECCLASS_FILE, NULL,
810 &sbsec->mntpoint_sid);
811 if (rc)
812 goto out;
813 }
814 goto out_set_opts;
815 }
816
Eric Parisc9180a52007-11-30 13:00:35 -0500817 /* sets the context of the superblock for the fs being mounted. */
818 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100819 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500820 if (rc)
821 goto out;
822
823 sbsec->sid = fscontext_sid;
824 }
825
826 /*
827 * Switch to using mount point labeling behavior.
828 * sets the label used on all file below the mountpoint, and will set
829 * the superblock context if not already set.
830 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400831 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
832 sbsec->behavior = SECURITY_FS_USE_NATIVE;
833 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
834 }
835
Eric Parisc9180a52007-11-30 13:00:35 -0500836 if (context_sid) {
837 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100838 rc = may_context_mount_sb_relabel(context_sid, sbsec,
839 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500840 if (rc)
841 goto out;
842 sbsec->sid = context_sid;
843 } else {
David Howells275bb412008-11-14 10:39:19 +1100844 rc = may_context_mount_inode_relabel(context_sid, sbsec,
845 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500846 if (rc)
847 goto out;
848 }
849 if (!rootcontext_sid)
850 rootcontext_sid = context_sid;
851
852 sbsec->mntpoint_sid = context_sid;
853 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
854 }
855
856 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100857 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
858 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500859 if (rc)
860 goto out;
861
862 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500863 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500864 }
865
866 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400867 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
868 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500869 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200870 pr_warn("SELinux: defcontext option is "
Eric Parisc9180a52007-11-30 13:00:35 -0500871 "invalid for this filesystem type\n");
872 goto out;
873 }
874
875 if (defcontext_sid != sbsec->def_sid) {
876 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100877 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500878 if (rc)
879 goto out;
880 }
881
882 sbsec->def_sid = defcontext_sid;
883 }
884
Seth Forsheeaad82892016-04-26 14:36:20 -0500885out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500886 rc = sb_finish_set_opts(sb);
887out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700888 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500890out_double_mount:
891 rc = -EINVAL;
peter enderborgc103a912018-06-12 10:09:03 +0200892 pr_warn("SELinux: mount invalid. Same superblock, different "
Al Virobd323652018-12-13 15:04:59 -0500893 "security settings for (dev %s, type %s)\n", sb->s_id,
894 sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500895 goto out;
896}
897
Jeff Layton094f7b62013-04-01 08:14:24 -0400898static int selinux_cmp_sb_context(const struct super_block *oldsb,
899 const struct super_block *newsb)
900{
901 struct superblock_security_struct *old = oldsb->s_security;
902 struct superblock_security_struct *new = newsb->s_security;
903 char oldflags = old->flags & SE_MNTMASK;
904 char newflags = new->flags & SE_MNTMASK;
905
906 if (oldflags != newflags)
907 goto mismatch;
908 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
909 goto mismatch;
910 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
911 goto mismatch;
912 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
913 goto mismatch;
914 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500915 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
916 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400917 if (oldroot->sid != newroot->sid)
918 goto mismatch;
919 }
920 return 0;
921mismatch:
peter enderborgc103a912018-06-12 10:09:03 +0200922 pr_warn("SELinux: mount invalid. Same superblock, "
Jeff Layton094f7b62013-04-01 08:14:24 -0400923 "different security settings for (dev %s, "
924 "type %s)\n", newsb->s_id, newsb->s_type->name);
925 return -EBUSY;
926}
927
928static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400929 struct super_block *newsb,
930 unsigned long kern_flags,
931 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500932{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400933 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500934 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
935 struct superblock_security_struct *newsbsec = newsb->s_security;
936
937 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
938 int set_context = (oldsbsec->flags & CONTEXT_MNT);
939 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
940
Eric Paris0f5e6422008-04-21 16:24:11 -0400941 /*
942 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400943 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400944 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500945 if (!selinux_state.initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400946 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500947
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400948 /*
949 * Specifying internal flags without providing a place to
950 * place the results is not allowed.
951 */
952 if (kern_flags && !set_kern_flags)
953 return -EINVAL;
954
Eric Parisc9180a52007-11-30 13:00:35 -0500955 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500956 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500957
Jeff Layton094f7b62013-04-01 08:14:24 -0400958 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500959 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400960 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400961
Eric Parisc9180a52007-11-30 13:00:35 -0500962 mutex_lock(&newsbsec->lock);
963
964 newsbsec->flags = oldsbsec->flags;
965
966 newsbsec->sid = oldsbsec->sid;
967 newsbsec->def_sid = oldsbsec->def_sid;
968 newsbsec->behavior = oldsbsec->behavior;
969
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400970 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
971 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500972 rc = security_fs_use(&selinux_state, newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400973 if (rc)
974 goto out;
975 }
976
977 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
978 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
979 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
980 }
981
Eric Parisc9180a52007-11-30 13:00:35 -0500982 if (set_context) {
983 u32 sid = oldsbsec->mntpoint_sid;
984
985 if (!set_fscontext)
986 newsbsec->sid = sid;
987 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500988 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500989 newisec->sid = sid;
990 }
991 newsbsec->mntpoint_sid = sid;
992 }
993 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500994 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
995 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500996
997 newisec->sid = oldisec->sid;
998 }
999
1000 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -04001001out:
Eric Parisc9180a52007-11-30 13:00:35 -05001002 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -04001003 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -05001004}
1005
Al Viroba641862018-12-14 20:28:15 -05001006static int selinux_add_opt(int token, const char *s, void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001007{
Al Viroba641862018-12-14 20:28:15 -05001008 struct selinux_mnt_opts *opts = *mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -05001009
Al Viroda3d76a2018-12-17 10:14:16 -05001010 if (token == Opt_seclabel) /* eaten and completely ignored */
Al Viro169d68efb2018-12-14 22:44:50 -05001011 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001012
Al Viroba641862018-12-14 20:28:15 -05001013 if (!opts) {
1014 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
1015 if (!opts)
1016 return -ENOMEM;
1017 *mnt_opts = opts;
1018 }
1019 if (!s)
1020 return -ENOMEM;
1021 switch (token) {
1022 case Opt_context:
1023 if (opts->context || opts->defcontext)
1024 goto Einval;
1025 opts->context = s;
1026 break;
1027 case Opt_fscontext:
1028 if (opts->fscontext)
1029 goto Einval;
1030 opts->fscontext = s;
1031 break;
1032 case Opt_rootcontext:
1033 if (opts->rootcontext)
1034 goto Einval;
1035 opts->rootcontext = s;
1036 break;
1037 case Opt_defcontext:
1038 if (opts->context || opts->defcontext)
1039 goto Einval;
1040 opts->defcontext = s;
1041 break;
1042 }
1043 return 0;
1044Einval:
1045 pr_warn(SEL_MOUNT_FAIL_MSG);
Al Viroba641862018-12-14 20:28:15 -05001046 return -EINVAL;
1047}
Eric Parisc9180a52007-11-30 13:00:35 -05001048
Al Viro757cbe52018-12-14 23:42:21 -05001049static int selinux_add_mnt_opt(const char *option, const char *val, int len,
1050 void **mnt_opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001051{
Al Viro757cbe52018-12-14 23:42:21 -05001052 int token = Opt_error;
1053 int rc, i;
Eric Parisc9180a52007-11-30 13:00:35 -05001054
Al Viro757cbe52018-12-14 23:42:21 -05001055 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
1056 if (strcmp(option, tokens[i].name) == 0) {
1057 token = tokens[i].opt;
Eric Parisc9180a52007-11-30 13:00:35 -05001058 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001059 }
1060 }
1061
Al Viro757cbe52018-12-14 23:42:21 -05001062 if (token == Opt_error)
1063 return -EINVAL;
Eric Parise0007522008-03-05 10:31:54 -05001064
Al Viro757cbe52018-12-14 23:42:21 -05001065 if (token != Opt_seclabel)
1066 val = kmemdup_nul(val, len, GFP_KERNEL);
1067 rc = selinux_add_opt(token, val, mnt_opts);
1068 if (unlikely(rc)) {
1069 kfree(val);
1070 if (*mnt_opts) {
1071 selinux_free_mnt_opts(*mnt_opts);
1072 *mnt_opts = NULL;
1073 }
1074 }
1075 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Al Viroe3489f82018-12-13 00:24:36 -05001078static int show_sid(struct seq_file *m, u32 sid)
Eric Paris2069f452008-07-04 09:47:13 +10001079{
Al Viroe3489f82018-12-13 00:24:36 -05001080 char *context = NULL;
1081 u32 len;
1082 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Al Viroe3489f82018-12-13 00:24:36 -05001084 rc = security_sid_to_context(&selinux_state, sid,
1085 &context, &len);
1086 if (!rc) {
1087 bool has_comma = context && strchr(context, ',');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Eric Paris2069f452008-07-04 09:47:13 +10001089 if (has_comma)
1090 seq_putc(m, '\"');
Al Viroe3489f82018-12-13 00:24:36 -05001091 seq_escape(m, context, "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001092 if (has_comma)
1093 seq_putc(m, '\"');
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 return rc;
1097}
Eric Paris2069f452008-07-04 09:47:13 +10001098
1099static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1100{
Al Viroe3489f82018-12-13 00:24:36 -05001101 struct superblock_security_struct *sbsec = sb->s_security;
Eric Paris2069f452008-07-04 09:47:13 +10001102 int rc;
1103
Al Viroe3489f82018-12-13 00:24:36 -05001104 if (!(sbsec->flags & SE_SBINITIALIZED))
1105 return 0;
1106
1107 if (!selinux_state.initialized)
1108 return 0;
1109
1110 if (sbsec->flags & FSCONTEXT_MNT) {
1111 seq_putc(m, ',');
1112 seq_puts(m, FSCONTEXT_STR);
1113 rc = show_sid(m, sbsec->sid);
1114 if (rc)
1115 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001116 }
Al Viroe3489f82018-12-13 00:24:36 -05001117 if (sbsec->flags & CONTEXT_MNT) {
1118 seq_putc(m, ',');
1119 seq_puts(m, CONTEXT_STR);
1120 rc = show_sid(m, sbsec->mntpoint_sid);
1121 if (rc)
1122 return rc;
1123 }
1124 if (sbsec->flags & DEFCONTEXT_MNT) {
1125 seq_putc(m, ',');
1126 seq_puts(m, DEFCONTEXT_STR);
1127 rc = show_sid(m, sbsec->def_sid);
1128 if (rc)
1129 return rc;
1130 }
1131 if (sbsec->flags & ROOTCONTEXT_MNT) {
1132 struct dentry *root = sbsec->sb->s_root;
1133 struct inode_security_struct *isec = backing_inode_security(root);
1134 seq_putc(m, ',');
1135 seq_puts(m, ROOTCONTEXT_STR);
1136 rc = show_sid(m, isec->sid);
1137 if (rc)
1138 return rc;
1139 }
1140 if (sbsec->flags & SBLABEL_MNT) {
1141 seq_putc(m, ',');
1142 seq_puts(m, LABELSUPP_STR);
1143 }
1144 return 0;
Eric Paris2069f452008-07-04 09:47:13 +10001145}
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147static inline u16 inode_mode_to_security_class(umode_t mode)
1148{
1149 switch (mode & S_IFMT) {
1150 case S_IFSOCK:
1151 return SECCLASS_SOCK_FILE;
1152 case S_IFLNK:
1153 return SECCLASS_LNK_FILE;
1154 case S_IFREG:
1155 return SECCLASS_FILE;
1156 case S_IFBLK:
1157 return SECCLASS_BLK_FILE;
1158 case S_IFDIR:
1159 return SECCLASS_DIR;
1160 case S_IFCHR:
1161 return SECCLASS_CHR_FILE;
1162 case S_IFIFO:
1163 return SECCLASS_FIFO_FILE;
1164
1165 }
1166
1167 return SECCLASS_FILE;
1168}
1169
James Morris13402582005-09-30 14:24:34 -04001170static inline int default_protocol_stream(int protocol)
1171{
1172 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1173}
1174
1175static inline int default_protocol_dgram(int protocol)
1176{
1177 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1178}
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1181{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001182 int extsockclass = selinux_policycap_extsockclass();
Stephen Smalleyda69a532017-01-09 10:07:30 -05001183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 switch (family) {
1185 case PF_UNIX:
1186 switch (type) {
1187 case SOCK_STREAM:
1188 case SOCK_SEQPACKET:
1189 return SECCLASS_UNIX_STREAM_SOCKET;
1190 case SOCK_DGRAM:
Luis Ressel2a764b52017-07-25 15:13:41 -04001191 case SOCK_RAW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 return SECCLASS_UNIX_DGRAM_SOCKET;
1193 }
1194 break;
1195 case PF_INET:
1196 case PF_INET6:
1197 switch (type) {
1198 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001199 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001200 if (default_protocol_stream(protocol))
1201 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001202 else if (extsockclass && protocol == IPPROTO_SCTP)
1203 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001204 else
1205 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001207 if (default_protocol_dgram(protocol))
1208 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001209 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1210 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001211 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001212 else
1213 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001214 case SOCK_DCCP:
1215 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001216 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 return SECCLASS_RAWIP_SOCKET;
1218 }
1219 break;
1220 case PF_NETLINK:
1221 switch (protocol) {
1222 case NETLINK_ROUTE:
1223 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001224 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1226 case NETLINK_NFLOG:
1227 return SECCLASS_NETLINK_NFLOG_SOCKET;
1228 case NETLINK_XFRM:
1229 return SECCLASS_NETLINK_XFRM_SOCKET;
1230 case NETLINK_SELINUX:
1231 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001232 case NETLINK_ISCSI:
1233 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 case NETLINK_AUDIT:
1235 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001236 case NETLINK_FIB_LOOKUP:
1237 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1238 case NETLINK_CONNECTOR:
1239 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1240 case NETLINK_NETFILTER:
1241 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 case NETLINK_DNRTMSG:
1243 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001244 case NETLINK_KOBJECT_UEVENT:
1245 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001246 case NETLINK_GENERIC:
1247 return SECCLASS_NETLINK_GENERIC_SOCKET;
1248 case NETLINK_SCSITRANSPORT:
1249 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1250 case NETLINK_RDMA:
1251 return SECCLASS_NETLINK_RDMA_SOCKET;
1252 case NETLINK_CRYPTO:
1253 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 default:
1255 return SECCLASS_NETLINK_SOCKET;
1256 }
1257 case PF_PACKET:
1258 return SECCLASS_PACKET_SOCKET;
1259 case PF_KEY:
1260 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001261 case PF_APPLETALK:
1262 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 }
1264
Stephen Smalleyda69a532017-01-09 10:07:30 -05001265 if (extsockclass) {
1266 switch (family) {
1267 case PF_AX25:
1268 return SECCLASS_AX25_SOCKET;
1269 case PF_IPX:
1270 return SECCLASS_IPX_SOCKET;
1271 case PF_NETROM:
1272 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001273 case PF_ATMPVC:
1274 return SECCLASS_ATMPVC_SOCKET;
1275 case PF_X25:
1276 return SECCLASS_X25_SOCKET;
1277 case PF_ROSE:
1278 return SECCLASS_ROSE_SOCKET;
1279 case PF_DECnet:
1280 return SECCLASS_DECNET_SOCKET;
1281 case PF_ATMSVC:
1282 return SECCLASS_ATMSVC_SOCKET;
1283 case PF_RDS:
1284 return SECCLASS_RDS_SOCKET;
1285 case PF_IRDA:
1286 return SECCLASS_IRDA_SOCKET;
1287 case PF_PPPOX:
1288 return SECCLASS_PPPOX_SOCKET;
1289 case PF_LLC:
1290 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001291 case PF_CAN:
1292 return SECCLASS_CAN_SOCKET;
1293 case PF_TIPC:
1294 return SECCLASS_TIPC_SOCKET;
1295 case PF_BLUETOOTH:
1296 return SECCLASS_BLUETOOTH_SOCKET;
1297 case PF_IUCV:
1298 return SECCLASS_IUCV_SOCKET;
1299 case PF_RXRPC:
1300 return SECCLASS_RXRPC_SOCKET;
1301 case PF_ISDN:
1302 return SECCLASS_ISDN_SOCKET;
1303 case PF_PHONET:
1304 return SECCLASS_PHONET_SOCKET;
1305 case PF_IEEE802154:
1306 return SECCLASS_IEEE802154_SOCKET;
1307 case PF_CAIF:
1308 return SECCLASS_CAIF_SOCKET;
1309 case PF_ALG:
1310 return SECCLASS_ALG_SOCKET;
1311 case PF_NFC:
1312 return SECCLASS_NFC_SOCKET;
1313 case PF_VSOCK:
1314 return SECCLASS_VSOCK_SOCKET;
1315 case PF_KCM:
1316 return SECCLASS_KCM_SOCKET;
1317 case PF_QIPCRTR:
1318 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001319 case PF_SMC:
1320 return SECCLASS_SMC_SOCKET;
Björn Töpel68e8b842018-05-02 13:01:22 +02001321 case PF_XDP:
1322 return SECCLASS_XDP_SOCKET;
1323#if PF_MAX > 45
Stephen Smalleyda69a532017-01-09 10:07:30 -05001324#error New address family defined, please update this function.
1325#endif
1326 }
1327 }
1328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return SECCLASS_SOCKET;
1330}
1331
Stephen Smalley134509d2015-06-04 16:22:17 -04001332static int selinux_genfs_get_sid(struct dentry *dentry,
1333 u16 tclass,
1334 u16 flags,
1335 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001337 int rc;
Al Virofc640052016-04-10 01:33:30 -04001338 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001339 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Eric Paris828dfe12008-04-17 13:17:49 -04001341 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (!buffer)
1343 return -ENOMEM;
1344
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001345 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1346 if (IS_ERR(path))
1347 rc = PTR_ERR(path);
1348 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001349 if (flags & SE_SBPROC) {
1350 /* each process gets a /proc/PID/ entry. Strip off the
1351 * PID part to get a valid selinux labeling.
1352 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1353 while (path[1] >= '0' && path[1] <= '9') {
1354 path[1] = '/';
1355 path++;
1356 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001357 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001358 rc = security_genfs_sid(&selinux_state, sb->s_type->name,
1359 path, tclass, sid);
Stephen Smalley7bb185e2018-09-04 16:51:36 -04001360 if (rc == -ENOENT) {
1361 /* No match in policy, mark as unlabeled. */
1362 *sid = SECINITSID_UNLABELED;
1363 rc = 0;
1364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 free_page((unsigned long)buffer);
1367 return rc;
1368}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
1370/* The inode's security attributes must be initialized before first use. */
1371static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1372{
1373 struct superblock_security_struct *sbsec = NULL;
1374 struct inode_security_struct *isec = inode->i_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001375 u32 task_sid, sid = 0;
1376 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 struct dentry *dentry;
1378#define INITCONTEXTLEN 255
1379 char *context = NULL;
1380 unsigned len = 0;
1381 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001383 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001384 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001386 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001387 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001388 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001390 if (isec->sclass == SECCLASS_FILE)
1391 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001394 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 /* Defer initialization until selinux_complete_init,
1396 after the initial policy is loaded and the security
1397 server is ready to handle calls. */
1398 spin_lock(&sbsec->isec_lock);
1399 if (list_empty(&isec->list))
1400 list_add(&isec->list, &sbsec->isec_head);
1401 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001402 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 }
1404
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001405 sclass = isec->sclass;
1406 task_sid = isec->task_sid;
1407 sid = isec->sid;
1408 isec->initialized = LABEL_PENDING;
1409 spin_unlock(&isec->lock);
1410
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001412 case SECURITY_FS_USE_NATIVE:
1413 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001415 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001416 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 break;
1418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 /* Need a dentry, since the xattr API requires one.
1420 Life would be simpler if we could just pass the inode. */
1421 if (opt_dentry) {
1422 /* Called from d_instantiate or d_splice_alias. */
1423 dentry = dget(opt_dentry);
1424 } else {
Al Virob1271252018-04-25 10:28:38 -04001425 /*
1426 * Called from selinux_complete_init, try to find a dentry.
1427 * Some filesystems really want a connected one, so try
1428 * that first. We could split SECURITY_FS_USE_XATTR in
1429 * two, depending upon that...
1430 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001432 if (!dentry)
1433 dentry = d_find_any_alias(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 }
1435 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001436 /*
1437 * this is can be hit on boot when a file is accessed
1438 * before the policy is loaded. When we load policy we
1439 * may find inodes that have no dentry on the
1440 * sbsec->isec_head list. No reason to complain as these
1441 * will get fixed up the next time we go through
1442 * inode_doinit with a dentry, before these inodes could
1443 * be used again by userspace.
1444 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001445 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 }
1447
1448 len = INITCONTEXTLEN;
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 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001458 kfree(context);
1459
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001461 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 if (rc < 0) {
1463 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001464 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001467 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (!context) {
1469 rc = -ENOMEM;
1470 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001471 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001473 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001474 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 }
1476 dput(dentry);
1477 if (rc < 0) {
1478 if (rc != -ENODATA) {
peter enderborgc103a912018-06-12 10:09:03 +02001479 pr_warn("SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001480 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 -rc, inode->i_sb->s_id, inode->i_ino);
1482 kfree(context);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001483 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 }
1485 /* Map ENODATA to the default file SID */
1486 sid = sbsec->def_sid;
1487 rc = 0;
1488 } else {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001489 rc = security_context_to_sid_default(&selinux_state,
1490 context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001491 sbsec->def_sid,
1492 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001494 char *dev = inode->i_sb->s_id;
1495 unsigned long ino = inode->i_ino;
1496
1497 if (rc == -EINVAL) {
1498 if (printk_ratelimit())
peter enderborgc103a912018-06-12 10:09:03 +02001499 pr_notice("SELinux: inode=%lu on dev=%s was found to have an invalid "
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001500 "context=%s. This indicates you may need to relabel the inode or the "
1501 "filesystem in question.\n", ino, dev, context);
1502 } else {
peter enderborgc103a912018-06-12 10:09:03 +02001503 pr_warn("SELinux: %s: context_to_sid(%s) "
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001504 "returned %d for dev=%s ino=%ld\n",
1505 __func__, context, -rc, dev, ino);
1506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 kfree(context);
1508 /* Leave with the unlabeled SID */
1509 rc = 0;
1510 break;
1511 }
1512 }
1513 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 break;
1515 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001516 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 break;
1518 case SECURITY_FS_USE_TRANS:
1519 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001520 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
1522 /* Try to obtain a transition SID. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001523 rc = security_transition_sid(&selinux_state, task_sid, sid,
1524 sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001526 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001528 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001529 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001530 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001532 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001533 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Stephen Smalley134509d2015-06-04 16:22:17 -04001535 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001536 /* We must have a dentry to determine the label on
1537 * procfs inodes */
Al Virob1271252018-04-25 10:28:38 -04001538 if (opt_dentry) {
Paul Mooref64410e2014-03-19 16:46:18 -04001539 /* Called from d_instantiate or
1540 * d_splice_alias. */
1541 dentry = dget(opt_dentry);
Al Virob1271252018-04-25 10:28:38 -04001542 } else {
Paul Mooref64410e2014-03-19 16:46:18 -04001543 /* Called from selinux_complete_init, try to
Al Virob1271252018-04-25 10:28:38 -04001544 * find a dentry. Some filesystems really want
1545 * a connected one, so try that first.
1546 */
Paul Mooref64410e2014-03-19 16:46:18 -04001547 dentry = d_find_alias(inode);
Al Virob1271252018-04-25 10:28:38 -04001548 if (!dentry)
1549 dentry = d_find_any_alias(inode);
1550 }
Paul Mooref64410e2014-03-19 16:46:18 -04001551 /*
1552 * This can be hit on boot when a file is accessed
1553 * before the policy is loaded. When we load policy we
1554 * may find inodes that have no dentry on the
1555 * sbsec->isec_head list. No reason to complain as
1556 * these will get fixed up the next time we go through
1557 * inode_doinit() with a dentry, before these inodes
1558 * could be used again by userspace.
1559 */
1560 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001561 goto out;
1562 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001563 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001564 dput(dentry);
1565 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001566 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 }
1568 break;
1569 }
1570
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001571out:
1572 spin_lock(&isec->lock);
1573 if (isec->initialized == LABEL_PENDING) {
1574 if (!sid || rc) {
1575 isec->initialized = LABEL_INVALID;
1576 goto out_unlock;
1577 }
1578
1579 isec->initialized = LABEL_INITIALIZED;
1580 isec->sid = sid;
1581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Eric Paris23970742006-09-25 23:32:01 -07001583out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001584 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return rc;
1586}
1587
1588/* Convert a Linux signal to an access vector. */
1589static inline u32 signal_to_av(int sig)
1590{
1591 u32 perm = 0;
1592
1593 switch (sig) {
1594 case SIGCHLD:
1595 /* Commonly granted from child to parent. */
1596 perm = PROCESS__SIGCHLD;
1597 break;
1598 case SIGKILL:
1599 /* Cannot be caught or ignored */
1600 perm = PROCESS__SIGKILL;
1601 break;
1602 case SIGSTOP:
1603 /* Cannot be caught or ignored */
1604 perm = PROCESS__SIGSTOP;
1605 break;
1606 default:
1607 /* All other signals. */
1608 perm = PROCESS__SIGNAL;
1609 break;
1610 }
1611
1612 return perm;
1613}
1614
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001615#if CAP_LAST_CAP > 63
1616#error Fix SELinux to handle capabilities > 63.
1617#endif
1618
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001620static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001621 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622{
Thomas Liu2bf49692009-07-14 12:14:09 -04001623 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001624 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001625 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001626 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001627 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001628 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Eric Paris50c205f2012-04-04 15:01:43 -04001630 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 ad.u.cap = cap;
1632
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001633 switch (CAP_TO_INDEX(cap)) {
1634 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001635 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001636 break;
1637 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001638 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001639 break;
1640 default:
peter enderborgc103a912018-06-12 10:09:03 +02001641 pr_err("SELinux: out of range capability %d\n", cap);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001642 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001643 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001644 }
Eric Paris06112162008-11-11 22:02:50 +11001645
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001646 rc = avc_has_perm_noaudit(&selinux_state,
1647 sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001648 if (audit == SECURITY_CAP_AUDIT) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001649 int rc2 = avc_audit(&selinux_state,
1650 sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001651 if (rc2)
1652 return rc2;
1653 }
Eric Paris06112162008-11-11 22:02:50 +11001654 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655}
1656
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657/* Check whether a task has a particular permission to an inode.
1658 The 'adp' parameter is optional and allows other audit
1659 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001660static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 struct inode *inode,
1662 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001663 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001666 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
David Howellse0e81732009-09-02 09:13:40 +01001668 validate_creds(cred);
1669
Eric Paris828dfe12008-04-17 13:17:49 -04001670 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001671 return 0;
1672
David Howells88e67f32008-11-14 10:39:21 +11001673 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 isec = inode->i_security;
1675
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001676 return avc_has_perm(&selinux_state,
1677 sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
1680/* Same as inode_has_perm, but pass explicit audit data containing
1681 the dentry to help the auditing code to more easily generate the
1682 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001683static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 struct dentry *dentry,
1685 u32 av)
1686{
David Howellsc6f493d2015-03-17 22:26:22 +00001687 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001688 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001689
Eric Paris50c205f2012-04-04 15:01:43 -04001690 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001691 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001692 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001693 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001694}
1695
1696/* Same as inode_has_perm, but pass explicit audit data containing
1697 the path to help the auditing code to more easily generate the
1698 pathname if needed. */
1699static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001700 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001701 u32 av)
1702{
David Howellsc6f493d2015-03-17 22:26:22 +00001703 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001704 struct common_audit_data ad;
1705
Eric Paris50c205f2012-04-04 15:01:43 -04001706 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001707 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001708 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001709 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710}
1711
David Howells13f8e982013-06-13 23:37:55 +01001712/* Same as path_has_perm, but uses the inode from the file struct. */
1713static inline int file_path_has_perm(const struct cred *cred,
1714 struct file *file,
1715 u32 av)
1716{
1717 struct common_audit_data ad;
1718
Vivek Goyal43af5de2016-09-09 11:37:49 -04001719 ad.type = LSM_AUDIT_DATA_FILE;
1720 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001721 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001722}
1723
Chenbo Fengf66e4482017-10-18 13:00:26 -07001724#ifdef CONFIG_BPF_SYSCALL
1725static int bpf_fd_pass(struct file *file, u32 sid);
1726#endif
1727
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728/* Check whether a task can use an open file descriptor to
1729 access an inode in a given way. Check access to the
1730 descriptor itself, and then use dentry_has_perm to
1731 check a particular permission to the file.
1732 Access to the descriptor is implicitly granted if it
1733 has the same SID as the process. If av is zero, then
1734 access to the file is not checked, e.g. for cases
1735 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001736static int file_has_perm(const struct cred *cred,
1737 struct file *file,
1738 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001741 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001742 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001743 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 int rc;
1745
Vivek Goyal43af5de2016-09-09 11:37:49 -04001746 ad.type = LSM_AUDIT_DATA_FILE;
1747 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
David Howells275bb412008-11-14 10:39:19 +11001749 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001750 rc = avc_has_perm(&selinux_state,
1751 sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 SECCLASS_FD,
1753 FD__USE,
1754 &ad);
1755 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001756 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 }
1758
Chenbo Fengf66e4482017-10-18 13:00:26 -07001759#ifdef CONFIG_BPF_SYSCALL
1760 rc = bpf_fd_pass(file, cred_sid(cred));
1761 if (rc)
1762 return rc;
1763#endif
1764
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001766 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001768 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
David Howells88e67f32008-11-14 10:39:21 +11001770out:
1771 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772}
1773
David Howellsc3c188b2015-07-10 17:19:58 -04001774/*
1775 * Determine the label for an inode that might be unioned.
1776 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001777static int
1778selinux_determine_inode_label(const struct task_security_struct *tsec,
1779 struct inode *dir,
1780 const struct qstr *name, u16 tclass,
1781 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001782{
1783 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001784
1785 if ((sbsec->flags & SE_SBINITIALIZED) &&
1786 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1787 *_new_isid = sbsec->mntpoint_sid;
1788 } else if ((sbsec->flags & SBLABEL_MNT) &&
1789 tsec->create_sid) {
1790 *_new_isid = tsec->create_sid;
1791 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001792 const struct inode_security_struct *dsec = inode_security(dir);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05001793 return security_transition_sid(&selinux_state, tsec->sid,
1794 dsec->sid, tclass,
David Howellsc3c188b2015-07-10 17:19:58 -04001795 name, _new_isid);
1796 }
1797
1798 return 0;
1799}
1800
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801/* Check whether a task can create a file. */
1802static int may_create(struct inode *dir,
1803 struct dentry *dentry,
1804 u16 tclass)
1805{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07001806 const struct task_security_struct *tsec = selinux_cred(current_cred());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 struct inode_security_struct *dsec;
1808 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001809 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001810 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 int rc;
1812
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001813 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 sbsec = dir->i_sb->s_security;
1815
David Howells275bb412008-11-14 10:39:19 +11001816 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001817
Eric Paris50c205f2012-04-04 15:01:43 -04001818 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001819 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001821 rc = avc_has_perm(&selinux_state,
1822 sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 DIR__ADD_NAME | DIR__SEARCH,
1824 &ad);
1825 if (rc)
1826 return rc;
1827
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07001828 rc = selinux_determine_inode_label(selinux_cred(current_cred()), dir,
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001829 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001830 if (rc)
1831 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001833 rc = avc_has_perm(&selinux_state,
1834 sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 if (rc)
1836 return rc;
1837
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001838 return avc_has_perm(&selinux_state,
1839 newsid, sbsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 SECCLASS_FILESYSTEM,
1841 FILESYSTEM__ASSOCIATE, &ad);
1842}
1843
Eric Paris828dfe12008-04-17 13:17:49 -04001844#define MAY_LINK 0
1845#define MAY_UNLINK 1
1846#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848/* Check whether a task can link, unlink, or rmdir a file/directory. */
1849static int may_link(struct inode *dir,
1850 struct dentry *dentry,
1851 int kind)
1852
1853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001855 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001856 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 u32 av;
1858 int rc;
1859
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001860 dsec = inode_security(dir);
1861 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Eric Paris50c205f2012-04-04 15:01:43 -04001863 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001864 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
1866 av = DIR__SEARCH;
1867 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001868 rc = avc_has_perm(&selinux_state,
1869 sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 if (rc)
1871 return rc;
1872
1873 switch (kind) {
1874 case MAY_LINK:
1875 av = FILE__LINK;
1876 break;
1877 case MAY_UNLINK:
1878 av = FILE__UNLINK;
1879 break;
1880 case MAY_RMDIR:
1881 av = DIR__RMDIR;
1882 break;
1883 default:
peter enderborgc103a912018-06-12 10:09:03 +02001884 pr_warn("SELinux: %s: unrecognized kind %d\n",
Eric Paris744ba352008-04-17 11:52:44 -04001885 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 return 0;
1887 }
1888
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001889 rc = avc_has_perm(&selinux_state,
1890 sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 return rc;
1892}
1893
1894static inline int may_rename(struct inode *old_dir,
1895 struct dentry *old_dentry,
1896 struct inode *new_dir,
1897 struct dentry *new_dentry)
1898{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001900 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001901 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 u32 av;
1903 int old_is_dir, new_is_dir;
1904 int rc;
1905
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001906 old_dsec = inode_security(old_dir);
1907 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001908 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001909 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
Eric Paris50c205f2012-04-04 15:01:43 -04001911 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Eric Parisa2694342011-04-25 13:10:27 -04001913 ad.u.dentry = old_dentry;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001914 rc = avc_has_perm(&selinux_state,
1915 sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1917 if (rc)
1918 return rc;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001919 rc = avc_has_perm(&selinux_state,
1920 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 old_isec->sclass, FILE__RENAME, &ad);
1922 if (rc)
1923 return rc;
1924 if (old_is_dir && new_dir != old_dir) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001925 rc = avc_has_perm(&selinux_state,
1926 sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 old_isec->sclass, DIR__REPARENT, &ad);
1928 if (rc)
1929 return rc;
1930 }
1931
Eric Parisa2694342011-04-25 13:10:27 -04001932 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001934 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 av |= DIR__REMOVE_NAME;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001936 rc = avc_has_perm(&selinux_state,
1937 sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 if (rc)
1939 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001940 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001941 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001942 new_is_dir = d_is_dir(new_dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001943 rc = avc_has_perm(&selinux_state,
1944 sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 new_isec->sclass,
1946 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1947 if (rc)
1948 return rc;
1949 }
1950
1951 return 0;
1952}
1953
1954/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001955static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 struct super_block *sb,
1957 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001958 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001961 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 sbsec = sb->s_security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05001964 return avc_has_perm(&selinux_state,
1965 sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966}
1967
1968/* Convert a Linux mode and permission mask to an access vector. */
1969static inline u32 file_mask_to_av(int mode, int mask)
1970{
1971 u32 av = 0;
1972
Al Virodba19c62011-07-25 20:49:29 -04001973 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 if (mask & MAY_EXEC)
1975 av |= FILE__EXECUTE;
1976 if (mask & MAY_READ)
1977 av |= FILE__READ;
1978
1979 if (mask & MAY_APPEND)
1980 av |= FILE__APPEND;
1981 else if (mask & MAY_WRITE)
1982 av |= FILE__WRITE;
1983
1984 } else {
1985 if (mask & MAY_EXEC)
1986 av |= DIR__SEARCH;
1987 if (mask & MAY_WRITE)
1988 av |= DIR__WRITE;
1989 if (mask & MAY_READ)
1990 av |= DIR__READ;
1991 }
1992
1993 return av;
1994}
1995
1996/* Convert a Linux file to an access vector. */
1997static inline u32 file_to_av(struct file *file)
1998{
1999 u32 av = 0;
2000
2001 if (file->f_mode & FMODE_READ)
2002 av |= FILE__READ;
2003 if (file->f_mode & FMODE_WRITE) {
2004 if (file->f_flags & O_APPEND)
2005 av |= FILE__APPEND;
2006 else
2007 av |= FILE__WRITE;
2008 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002009 if (!av) {
2010 /*
2011 * Special file opened with flags 3 for ioctl-only use.
2012 */
2013 av = FILE__IOCTL;
2014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
2016 return av;
2017}
2018
Eric Paris8b6a5a32008-10-29 17:06:46 -04002019/*
2020 * Convert a file to an access vector and include the correct open
2021 * open permission.
2022 */
2023static inline u32 open_file_to_av(struct file *file)
2024{
2025 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04002026 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002027
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002028 if (selinux_policycap_openperm() &&
2029 inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002030 av |= FILE__OPEN;
2031
Eric Paris8b6a5a32008-10-29 17:06:46 -04002032 return av;
2033}
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035/* Hook functions begin here. */
2036
Stephen Smalley79af7302015-01-21 10:54:10 -05002037static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2038{
2039 u32 mysid = current_sid();
2040 u32 mgrsid = task_sid(mgr);
2041
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002042 return avc_has_perm(&selinux_state,
2043 mysid, mgrsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002044 BINDER__SET_CONTEXT_MGR, NULL);
2045}
2046
2047static int selinux_binder_transaction(struct task_struct *from,
2048 struct task_struct *to)
2049{
2050 u32 mysid = current_sid();
2051 u32 fromsid = task_sid(from);
2052 u32 tosid = task_sid(to);
2053 int rc;
2054
2055 if (mysid != fromsid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002056 rc = avc_has_perm(&selinux_state,
2057 mysid, fromsid, SECCLASS_BINDER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002058 BINDER__IMPERSONATE, NULL);
2059 if (rc)
2060 return rc;
2061 }
2062
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002063 return avc_has_perm(&selinux_state,
2064 fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
Stephen Smalley79af7302015-01-21 10:54:10 -05002065 NULL);
2066}
2067
2068static int selinux_binder_transfer_binder(struct task_struct *from,
2069 struct task_struct *to)
2070{
2071 u32 fromsid = task_sid(from);
2072 u32 tosid = task_sid(to);
2073
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002074 return avc_has_perm(&selinux_state,
2075 fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
Stephen Smalley79af7302015-01-21 10:54:10 -05002076 NULL);
2077}
2078
2079static int selinux_binder_transfer_file(struct task_struct *from,
2080 struct task_struct *to,
2081 struct file *file)
2082{
2083 u32 sid = task_sid(to);
2084 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002085 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002086 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002087 struct common_audit_data ad;
2088 int rc;
2089
2090 ad.type = LSM_AUDIT_DATA_PATH;
2091 ad.u.path = file->f_path;
2092
2093 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002094 rc = avc_has_perm(&selinux_state,
2095 sid, fsec->sid,
Stephen Smalley79af7302015-01-21 10:54:10 -05002096 SECCLASS_FD,
2097 FD__USE,
2098 &ad);
2099 if (rc)
2100 return rc;
2101 }
2102
Chenbo Fengf66e4482017-10-18 13:00:26 -07002103#ifdef CONFIG_BPF_SYSCALL
2104 rc = bpf_fd_pass(file, sid);
2105 if (rc)
2106 return rc;
2107#endif
2108
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002109 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002110 return 0;
2111
Paul Moore20cdef82016-04-04 14:14:42 -04002112 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002113 return avc_has_perm(&selinux_state,
2114 sid, isec->sid, isec->sclass, file_to_av(file),
Stephen Smalley79af7302015-01-21 10:54:10 -05002115 &ad);
2116}
2117
Ingo Molnar9e488582009-05-07 19:26:19 +10002118static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002119 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002121 u32 sid = current_sid();
2122 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002123
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002124 if (mode & PTRACE_MODE_READ)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002125 return avc_has_perm(&selinux_state,
2126 sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002127
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002128 return avc_has_perm(&selinux_state,
2129 sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002130}
2131
2132static int selinux_ptrace_traceme(struct task_struct *parent)
2133{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002134 return avc_has_perm(&selinux_state,
2135 task_sid(parent), current_sid(), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002136 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137}
2138
2139static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002140 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002142 return avc_has_perm(&selinux_state,
2143 current_sid(), task_sid(target), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002144 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145}
2146
David Howellsd84f4f92008-11-14 10:39:23 +11002147static int selinux_capset(struct cred *new, const struct cred *old,
2148 const kernel_cap_t *effective,
2149 const kernel_cap_t *inheritable,
2150 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002152 return avc_has_perm(&selinux_state,
2153 cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002154 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155}
2156
James Morris5626d3e2009-01-30 10:05:06 +11002157/*
2158 * (This comment used to live with the selinux_task_setuid hook,
2159 * which was removed).
2160 *
2161 * Since setuid only affects the current process, and since the SELinux
2162 * controls are not based on the Linux identity attributes, SELinux does not
2163 * need to control this operation. However, SELinux does control the use of
2164 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2165 */
2166
Eric Paris6a9de492012-01-03 12:25:14 -05002167static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2168 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002170 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171}
2172
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2174{
David Howells88e67f32008-11-14 10:39:21 +11002175 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 int rc = 0;
2177
2178 if (!sb)
2179 return 0;
2180
2181 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002182 case Q_SYNC:
2183 case Q_QUOTAON:
2184 case Q_QUOTAOFF:
2185 case Q_SETINFO:
2186 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002187 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002188 break;
2189 case Q_GETFMT:
2190 case Q_GETINFO:
2191 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002192 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002193 break;
2194 default:
2195 rc = 0; /* let the kernel handle invalid cmds */
2196 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 }
2198 return rc;
2199}
2200
2201static int selinux_quota_on(struct dentry *dentry)
2202{
David Howells88e67f32008-11-14 10:39:21 +11002203 const struct cred *cred = current_cred();
2204
Eric Paris2875fa02011-04-28 16:04:24 -04002205 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206}
2207
Eric Paris12b30522010-11-15 18:36:29 -05002208static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002211 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2212 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002213 return avc_has_perm(&selinux_state,
2214 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002215 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002216 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2217 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2218 /* Set level of messages printed to console */
2219 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002220 return avc_has_perm(&selinux_state,
2221 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002222 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2223 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002225 /* All other syslog types */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002226 return avc_has_perm(&selinux_state,
2227 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002228 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229}
2230
2231/*
2232 * Check that a process has enough memory to allocate a new virtual
2233 * mapping. 0 means there is enough memory for the allocation to
2234 * succeed and -ENOMEM implies there is not.
2235 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 * Do not audit the selinux permission check, as this is applied to all
2237 * processes that allocate mappings.
2238 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002239static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240{
2241 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002243 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002244 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 if (rc == 0)
2246 cap_sys_admin = 1;
2247
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002248 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249}
2250
2251/* binprm security operations */
2252
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002253static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002254{
2255 u32 sid = 0;
2256 struct task_struct *tracer;
2257
2258 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002259 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002260 if (tracer)
2261 sid = task_sid(tracer);
2262 rcu_read_unlock();
2263
2264 return sid;
2265}
2266
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002267static int check_nnp_nosuid(const struct linux_binprm *bprm,
2268 const struct task_security_struct *old_tsec,
2269 const struct task_security_struct *new_tsec)
2270{
2271 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002272 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002273 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002274 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002275
2276 if (!nnp && !nosuid)
2277 return 0; /* neither NNP nor nosuid */
2278
2279 if (new_tsec->sid == old_tsec->sid)
2280 return 0; /* No change in credentials */
2281
2282 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002283 * If the policy enables the nnp_nosuid_transition policy capability,
2284 * then we permit transitions under NNP or nosuid if the
2285 * policy allows the corresponding permission between
2286 * the old and new contexts.
2287 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002288 if (selinux_policycap_nnp_nosuid_transition()) {
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002289 av = 0;
2290 if (nnp)
2291 av |= PROCESS2__NNP_TRANSITION;
2292 if (nosuid)
2293 av |= PROCESS2__NOSUID_TRANSITION;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002294 rc = avc_has_perm(&selinux_state,
2295 old_tsec->sid, new_tsec->sid,
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002296 SECCLASS_PROCESS2, av, NULL);
2297 if (!rc)
2298 return 0;
2299 }
2300
2301 /*
2302 * We also permit NNP or nosuid transitions to bounded SIDs,
2303 * i.e. SIDs that are guaranteed to only be allowed a subset
2304 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002305 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002306 rc = security_bounded_transition(&selinux_state, old_tsec->sid,
2307 new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002308 if (!rc)
2309 return 0;
2310
2311 /*
2312 * On failure, preserve the errno values for NNP vs nosuid.
2313 * NNP: Operation not permitted for caller.
2314 * nosuid: Permission denied to file.
2315 */
2316 if (nnp)
2317 return -EPERM;
2318 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002319}
2320
David Howellsa6f76f22008-11-14 10:39:24 +11002321static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322{
David Howellsa6f76f22008-11-14 10:39:24 +11002323 const struct task_security_struct *old_tsec;
2324 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002326 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002327 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 int rc;
2329
David Howellsa6f76f22008-11-14 10:39:24 +11002330 /* SELinux context only depends on initial program or script and not
2331 * the script interpreter */
Kees Cookddb4a142017-07-18 15:25:23 -07002332 if (bprm->called_set_creds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 return 0;
2334
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002335 old_tsec = selinux_cred(current_cred());
2336 new_tsec = selinux_cred(bprm->cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002337 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
2339 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002340 new_tsec->sid = old_tsec->sid;
2341 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
Michael LeMay28eba5b2006-06-27 02:53:42 -07002343 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002344 new_tsec->create_sid = 0;
2345 new_tsec->keycreate_sid = 0;
2346 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
David Howellsa6f76f22008-11-14 10:39:24 +11002348 if (old_tsec->exec_sid) {
2349 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002351 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002352
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002353 /* Fail on NNP or nosuid if not an allowed transition. */
2354 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2355 if (rc)
2356 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 } else {
2358 /* Check for a default transition on this program. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002359 rc = security_transition_sid(&selinux_state, old_tsec->sid,
2360 isec->sid, SECCLASS_PROCESS, NULL,
Eric Paris652bb9b2011-02-01 11:05:40 -05002361 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 if (rc)
2363 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002364
2365 /*
2366 * Fallback to old SID on NNP or nosuid if not an allowed
2367 * transition.
2368 */
2369 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2370 if (rc)
2371 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 }
2373
Vivek Goyal43af5de2016-09-09 11:37:49 -04002374 ad.type = LSM_AUDIT_DATA_FILE;
2375 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
David Howellsa6f76f22008-11-14 10:39:24 +11002377 if (new_tsec->sid == old_tsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002378 rc = avc_has_perm(&selinux_state,
2379 old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2381 if (rc)
2382 return rc;
2383 } else {
2384 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002385 rc = avc_has_perm(&selinux_state,
2386 old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2388 if (rc)
2389 return rc;
2390
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002391 rc = avc_has_perm(&selinux_state,
2392 new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2394 if (rc)
2395 return rc;
2396
David Howellsa6f76f22008-11-14 10:39:24 +11002397 /* Check for shared state */
2398 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002399 rc = avc_has_perm(&selinux_state,
2400 old_tsec->sid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002401 SECCLASS_PROCESS, PROCESS__SHARE,
2402 NULL);
2403 if (rc)
2404 return -EPERM;
2405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
David Howellsa6f76f22008-11-14 10:39:24 +11002407 /* Make sure that anyone attempting to ptrace over a task that
2408 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002409 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002410 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002411 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002412 rc = avc_has_perm(&selinux_state,
2413 ptsid, new_tsec->sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002414 SECCLASS_PROCESS,
2415 PROCESS__PTRACE, NULL);
2416 if (rc)
2417 return -EPERM;
2418 }
2419 }
2420
2421 /* Clear any possibly unsafe personality bits on exec: */
2422 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 /* Enable secure mode for SIDs transitions unless
2425 the noatsecure permission is granted between
2426 the two SIDs, i.e. ahp returns 0. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002427 rc = avc_has_perm(&selinux_state,
2428 old_tsec->sid, new_tsec->sid,
Kees Cook62874c32017-07-18 15:25:25 -07002429 SECCLASS_PROCESS, PROCESS__NOATSECURE,
2430 NULL);
2431 bprm->secureexec |= !!rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 }
2433
Kees Cook62874c32017-07-18 15:25:25 -07002434 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435}
2436
Al Viroc3c073f2012-08-21 22:32:06 -04002437static int match_file(const void *p, struct file *file, unsigned fd)
2438{
2439 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2440}
2441
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002443static inline void flush_unauthorized_files(const struct cred *cred,
2444 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002447 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002448 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002449 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002451 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002453 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002454 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002455 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002458 Use file_path_has_perm on the tty path directly
2459 rather than using file_has_perm, as this particular
2460 open file may belong to another process and we are
2461 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002462 file_priv = list_first_entry(&tty->tty_files,
2463 struct tty_file_private, list);
2464 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002465 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002466 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 }
Peter Hurley4a510962016-01-09 21:35:23 -08002468 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002469 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002471 /* Reset controlling tty. */
2472 if (drop_tty)
2473 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
2475 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002476 n = iterate_fd(files, 0, match_file, cred);
2477 if (!n) /* none found? */
2478 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Al Viroc3c073f2012-08-21 22:32:06 -04002480 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002481 if (IS_ERR(devnull))
2482 devnull = NULL;
2483 /* replace all the matching ones with this */
2484 do {
2485 replace_fd(n - 1, devnull, 0);
2486 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2487 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002488 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489}
2490
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491/*
David Howellsa6f76f22008-11-14 10:39:24 +11002492 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 */
David Howellsa6f76f22008-11-14 10:39:24 +11002494static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495{
David Howellsa6f76f22008-11-14 10:39:24 +11002496 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 int rc, i;
2499
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002500 new_tsec = selinux_cred(bprm->cred);
David Howellsa6f76f22008-11-14 10:39:24 +11002501 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 return;
2503
2504 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002505 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
David Howellsa6f76f22008-11-14 10:39:24 +11002507 /* Always clear parent death signal on SID transitions. */
2508 current->pdeath_signal = 0;
2509
2510 /* Check whether the new SID can inherit resource limits from the old
2511 * SID. If not, reset all soft limits to the lower of the current
2512 * task's hard limit and the init task's soft limit.
2513 *
2514 * Note that the setting of hard limits (even to lower them) can be
2515 * controlled by the setrlimit check. The inclusion of the init task's
2516 * soft limit into the computation is to avoid resetting soft limits
2517 * higher than the default soft limit for cases where the default is
2518 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2519 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002520 rc = avc_has_perm(&selinux_state,
2521 new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
David Howellsa6f76f22008-11-14 10:39:24 +11002522 PROCESS__RLIMITINH, NULL);
2523 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002524 /* protect against do_prlimit() */
2525 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002526 for (i = 0; i < RLIM_NLIMITS; i++) {
2527 rlim = current->signal->rlim + i;
2528 initrlim = init_task.signal->rlim + i;
2529 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2530 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002531 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002532 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2533 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002534 }
2535}
2536
2537/*
2538 * Clean up the process immediately after the installation of new credentials
2539 * due to exec
2540 */
2541static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2542{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002543 const struct task_security_struct *tsec = selinux_cred(current_cred());
David Howellsa6f76f22008-11-14 10:39:24 +11002544 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002545 u32 osid, sid;
2546 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002547
David Howellsa6f76f22008-11-14 10:39:24 +11002548 osid = tsec->osid;
2549 sid = tsec->sid;
2550
2551 if (sid == osid)
2552 return;
2553
2554 /* Check whether the new SID can inherit signal state from the old SID.
2555 * If not, clear itimers to avoid subsequent signal generation and
2556 * flush and unblock signals.
2557 *
2558 * This must occur _after_ the task SID has been updated so that any
2559 * kill done after the flush will be checked against the new SID.
2560 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002561 rc = avc_has_perm(&selinux_state,
2562 osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 if (rc) {
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002564 if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
2565 memset(&itimer, 0, sizeof itimer);
2566 for (i = 0; i < 3; i++)
2567 do_setitimer(i, &itimer, NULL);
2568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002570 if (!fatal_signal_pending(current)) {
2571 flush_sigqueue(&current->pending);
2572 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002573 flush_signal_handlers(current, 1);
2574 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002575 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 spin_unlock_irq(&current->sighand->siglock);
2578 }
2579
David Howellsa6f76f22008-11-14 10:39:24 +11002580 /* Wake up the parent if it is waiting so that it can recheck
2581 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002582 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002583 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002584 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585}
2586
2587/* superblock security operations */
2588
2589static int selinux_sb_alloc_security(struct super_block *sb)
2590{
2591 return superblock_alloc_security(sb);
2592}
2593
2594static void selinux_sb_free_security(struct super_block *sb)
2595{
2596 superblock_free_security(sb);
2597}
2598
Al Viro99dbbb52018-12-14 21:56:23 -05002599static inline int opt_len(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600{
Al Viro99dbbb52018-12-14 21:56:23 -05002601 bool open_quote = false;
2602 int len;
2603 char c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
Al Viro99dbbb52018-12-14 21:56:23 -05002605 for (len = 0; (c = s[len]) != '\0'; len++) {
2606 if (c == '"')
Cory Olmo3528a952006-09-29 01:58:44 -07002607 open_quote = !open_quote;
Al Viro99dbbb52018-12-14 21:56:23 -05002608 if (c == ',' && !open_quote)
2609 break;
2610 }
2611 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612}
2613
Al Viro204cc0c2018-12-13 13:41:47 -05002614static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002615{
Al Viro99dbbb52018-12-14 21:56:23 -05002616 char *from = options;
2617 char *to = options;
2618 bool first = true;
Al Viro5b400232018-12-12 20:13:29 -05002619
Al Viro99dbbb52018-12-14 21:56:23 -05002620 while (1) {
2621 int len = opt_len(from);
2622 int token, rc;
2623 char *arg = NULL;
2624
2625 token = match_opt_prefix(from, len, &arg);
2626
2627 if (token != Opt_error) {
2628 char *p, *q;
2629
2630 /* strip quotes */
2631 if (arg) {
2632 for (p = q = arg; p < from + len; p++) {
2633 char c = *p;
2634 if (c != '"')
2635 *q++ = c;
2636 }
2637 arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
2638 }
2639 rc = selinux_add_opt(token, arg, mnt_opts);
2640 if (unlikely(rc)) {
2641 kfree(arg);
2642 if (*mnt_opts) {
2643 selinux_free_mnt_opts(*mnt_opts);
2644 *mnt_opts = NULL;
2645 }
2646 return rc;
2647 }
2648 } else {
2649 if (!first) { // copy with preceding comma
2650 from--;
2651 len++;
2652 }
2653 if (to != from)
2654 memmove(to, from, len);
2655 to += len;
2656 first = false;
2657 }
2658 if (!from[len])
2659 break;
2660 from += len + 1;
2661 }
2662 *to = '\0';
2663 return 0;
Al Viro5b400232018-12-12 20:13:29 -05002664}
2665
Al Viro204cc0c2018-12-13 13:41:47 -05002666static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
Eric Paris026eb162011-03-03 16:09:14 -05002667{
Al Virobd323652018-12-13 15:04:59 -05002668 struct selinux_mnt_opts *opts = mnt_opts;
Eric Paris026eb162011-03-03 16:09:14 -05002669 struct superblock_security_struct *sbsec = sb->s_security;
Al Virobd323652018-12-13 15:04:59 -05002670 u32 sid;
2671 int rc;
Eric Paris026eb162011-03-03 16:09:14 -05002672
2673 if (!(sbsec->flags & SE_SBINITIALIZED))
2674 return 0;
2675
Al Viro204cc0c2018-12-13 13:41:47 -05002676 if (!opts)
Eric Paris026eb162011-03-03 16:09:14 -05002677 return 0;
2678
Al Virobd323652018-12-13 15:04:59 -05002679 if (opts->fscontext) {
2680 rc = parse_sid(sb, opts->fscontext, &sid);
2681 if (rc)
Al Viroc039bc32018-12-01 23:06:57 -05002682 return rc;
Al Virobd323652018-12-13 15:04:59 -05002683 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2684 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002685 }
Al Virobd323652018-12-13 15:04:59 -05002686 if (opts->context) {
2687 rc = parse_sid(sb, opts->context, &sid);
2688 if (rc)
2689 return rc;
2690 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2691 goto out_bad_option;
2692 }
2693 if (opts->rootcontext) {
2694 struct inode_security_struct *root_isec;
2695 root_isec = backing_inode_security(sb->s_root);
2696 rc = parse_sid(sb, opts->rootcontext, &sid);
2697 if (rc)
2698 return rc;
2699 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2700 goto out_bad_option;
2701 }
2702 if (opts->defcontext) {
2703 rc = parse_sid(sb, opts->defcontext, &sid);
2704 if (rc)
2705 return rc;
2706 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2707 goto out_bad_option;
Eric Paris026eb162011-03-03 16:09:14 -05002708 }
Al Viroc039bc32018-12-01 23:06:57 -05002709 return 0;
Eric Paris026eb162011-03-03 16:09:14 -05002710
Eric Paris026eb162011-03-03 16:09:14 -05002711out_bad_option:
peter enderborgc103a912018-06-12 10:09:03 +02002712 pr_warn("SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002713 "during remount (dev %s, type=%s)\n", sb->s_id,
2714 sb->s_type->name);
Al Viroc039bc32018-12-01 23:06:57 -05002715 return -EINVAL;
Eric Paris026eb162011-03-03 16:09:14 -05002716}
2717
Al Viroa10d7c22018-12-05 11:58:35 -05002718static int selinux_sb_kern_mount(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
David Howells88e67f32008-11-14 10:39:21 +11002720 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002721 struct common_audit_data ad;
James Morris74192242008-12-19 11:41:10 +11002722
Eric Paris50c205f2012-04-04 15:01:43 -04002723 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002724 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002725 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726}
2727
David Howells726c3342006-06-23 02:02:58 -07002728static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
David Howells88e67f32008-11-14 10:39:21 +11002730 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002731 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
Eric Paris50c205f2012-04-04 15:01:43 -04002733 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002734 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002735 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736}
2737
Al Viro808d4e32012-10-11 11:42:01 -04002738static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002739 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002740 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002741 unsigned long flags,
2742 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743{
David Howells88e67f32008-11-14 10:39:21 +11002744 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
2746 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002747 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002748 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 else
Eric Paris2875fa02011-04-28 16:04:24 -04002750 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751}
2752
2753static int selinux_umount(struct vfsmount *mnt, int flags)
2754{
David Howells88e67f32008-11-14 10:39:21 +11002755 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756
David Howells88e67f32008-11-14 10:39:21 +11002757 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002758 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759}
2760
2761/* inode security operations */
2762
2763static int selinux_inode_alloc_security(struct inode *inode)
2764{
2765 return inode_alloc_security(inode);
2766}
2767
2768static void selinux_inode_free_security(struct inode *inode)
2769{
2770 inode_free_security(inode);
2771}
2772
David Quigleyd47be3d2013-05-22 12:50:34 -04002773static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002774 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002775 u32 *ctxlen)
2776{
David Quigleyd47be3d2013-05-22 12:50:34 -04002777 u32 newsid;
2778 int rc;
2779
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002780 rc = selinux_determine_inode_label(selinux_cred(current_cred()),
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002781 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002782 inode_mode_to_security_class(mode),
2783 &newsid);
2784 if (rc)
2785 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002786
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002787 return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
2788 ctxlen);
David Quigleyd47be3d2013-05-22 12:50:34 -04002789}
2790
Vivek Goyala518b0a2016-07-13 10:44:53 -04002791static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2792 struct qstr *name,
2793 const struct cred *old,
2794 struct cred *new)
2795{
2796 u32 newsid;
2797 int rc;
2798 struct task_security_struct *tsec;
2799
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002800 rc = selinux_determine_inode_label(selinux_cred(old),
Vivek Goyala518b0a2016-07-13 10:44:53 -04002801 d_inode(dentry->d_parent), name,
2802 inode_mode_to_security_class(mode),
2803 &newsid);
2804 if (rc)
2805 return rc;
2806
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002807 tsec = selinux_cred(new);
Vivek Goyala518b0a2016-07-13 10:44:53 -04002808 tsec->create_sid = newsid;
2809 return 0;
2810}
2811
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002812static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002813 const struct qstr *qstr,
2814 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002815 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002816{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002817 const struct task_security_struct *tsec = selinux_cred(current_cred());
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002818 struct superblock_security_struct *sbsec;
Corentin LABBEc0d4f462017-10-04 20:32:17 +02002819 u32 newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002820 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002821 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002822
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002823 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002824
David Howells275bb412008-11-14 10:39:19 +11002825 newsid = tsec->create_sid;
2826
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07002827 rc = selinux_determine_inode_label(selinux_cred(current_cred()),
David Howellsc3c188b2015-07-10 17:19:58 -04002828 dir, qstr,
2829 inode_mode_to_security_class(inode->i_mode),
2830 &newsid);
2831 if (rc)
2832 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002833
Eric Paris296fddf2006-09-25 23:32:00 -07002834 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002835 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002836 struct inode_security_struct *isec = inode->i_security;
2837 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2838 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002839 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002840 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002841
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002842 if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002843 return -EOPNOTSUPP;
2844
Tetsuo Handa95489062013-07-25 05:44:02 +09002845 if (name)
2846 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002847
2848 if (value && len) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05002849 rc = security_sid_to_context_force(&selinux_state, newsid,
2850 &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002851 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002852 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002853 *value = context;
2854 *len = clen;
2855 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002856
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002857 return 0;
2858}
2859
Al Viro4acdaf22011-07-26 01:42:34 -04002860static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861{
2862 return may_create(dir, dentry, SECCLASS_FILE);
2863}
2864
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2866{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 return may_link(dir, old_dentry, MAY_LINK);
2868}
2869
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2871{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 return may_link(dir, dentry, MAY_UNLINK);
2873}
2874
2875static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2876{
2877 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2878}
2879
Al Viro18bb1db2011-07-26 01:41:39 -04002880static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
2882 return may_create(dir, dentry, SECCLASS_DIR);
2883}
2884
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2886{
2887 return may_link(dir, dentry, MAY_RMDIR);
2888}
2889
Al Viro1a67aaf2011-07-26 01:52:52 -04002890static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2893}
2894
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002896 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897{
2898 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2899}
2900
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901static int selinux_inode_readlink(struct dentry *dentry)
2902{
David Howells88e67f32008-11-14 10:39:21 +11002903 const struct cred *cred = current_cred();
2904
Eric Paris2875fa02011-04-28 16:04:24 -04002905 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906}
2907
NeilBrownbda0be72015-03-23 13:37:39 +11002908static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2909 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910{
David Howells88e67f32008-11-14 10:39:21 +11002911 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002912 struct common_audit_data ad;
2913 struct inode_security_struct *isec;
2914 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
NeilBrownbda0be72015-03-23 13:37:39 +11002916 validate_creds(cred);
2917
2918 ad.type = LSM_AUDIT_DATA_DENTRY;
2919 ad.u.dentry = dentry;
2920 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002921 isec = inode_security_rcu(inode, rcu);
2922 if (IS_ERR(isec))
2923 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002924
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002925 return avc_has_perm_flags(&selinux_state,
2926 sid, isec->sid, isec->sclass, FILE__READ, &ad,
NeilBrownbda0be72015-03-23 13:37:39 +11002927 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928}
2929
Eric Parisd4cf970d2012-04-04 15:01:42 -04002930static noinline int audit_inode_permission(struct inode *inode,
2931 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002932 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002933 unsigned flags)
2934{
2935 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002936 struct inode_security_struct *isec = inode->i_security;
2937 int rc;
2938
Eric Paris50c205f2012-04-04 15:01:43 -04002939 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002940 ad.u.inode = inode;
2941
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002942 rc = slow_avc_audit(&selinux_state,
2943 current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002944 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002945 if (rc)
2946 return rc;
2947 return 0;
2948}
2949
Al Viroe74f71e2011-06-20 19:38:15 -04002950static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
David Howells88e67f32008-11-14 10:39:21 +11002952 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002953 u32 perms;
2954 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002955 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002956 struct inode_security_struct *isec;
2957 u32 sid;
2958 struct av_decision avd;
2959 int rc, rc2;
2960 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Eric Parisb782e0a2010-07-23 11:44:03 -04002962 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002963 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2964
Eric Parisb782e0a2010-07-23 11:44:03 -04002965 /* No permission to check. Existence test. */
2966 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Eric Paris2e334052012-04-04 15:01:42 -04002969 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002970
Eric Paris2e334052012-04-04 15:01:42 -04002971 if (unlikely(IS_PRIVATE(inode)))
2972 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002973
2974 perms = file_mask_to_av(inode->i_mode, mask);
2975
Eric Paris2e334052012-04-04 15:01:42 -04002976 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002977 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
2978 if (IS_ERR(isec))
2979 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04002980
Stephen Smalley6b6bc622018-03-05 11:47:56 -05002981 rc = avc_has_perm_noaudit(&selinux_state,
2982 sid, isec->sid, isec->sclass, perms, 0, &avd);
Eric Paris2e334052012-04-04 15:01:42 -04002983 audited = avc_audit_required(perms, &avd, rc,
2984 from_access ? FILE__AUDIT_ACCESS : 0,
2985 &denied);
2986 if (likely(!audited))
2987 return rc;
2988
Stephen Smalley626b9742014-04-29 11:29:04 -07002989 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002990 if (rc2)
2991 return rc2;
2992 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993}
2994
2995static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2996{
David Howells88e67f32008-11-14 10:39:21 +11002997 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04002998 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002999 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003000 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003002 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3003 if (ia_valid & ATTR_FORCE) {
3004 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3005 ATTR_FORCE);
3006 if (!ia_valid)
3007 return 0;
3008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003010 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3011 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003012 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003014 if (selinux_policycap_openperm() &&
Stephen Smalleyccb54472017-05-12 12:41:24 -04003015 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3016 (ia_valid & ATTR_SIZE) &&
3017 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003018 av |= FILE__OPEN;
3019
3020 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021}
3022
Al Viro3f7036a2015-03-08 19:28:30 -04003023static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024{
Al Viro3f7036a2015-03-08 19:28:30 -04003025 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026}
3027
Stephen Smalleydb590002017-04-20 11:31:30 -04003028static bool has_cap_mac_admin(bool audit)
3029{
3030 const struct cred *cred = current_cred();
3031 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3032
3033 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3034 return false;
3035 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3036 return false;
3037 return true;
3038}
3039
David Howells8f0cfa52008-04-29 00:59:41 -07003040static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3041 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042{
David Howellsc6f493d2015-03-17 22:26:22 +00003043 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003044 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003046 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003047 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 int rc = 0;
3049
Eric W. Biederman6b240302017-10-02 09:38:20 -05003050 if (strcmp(name, XATTR_NAME_SELINUX)) {
3051 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3052 if (rc)
3053 return rc;
3054
3055 /* Not an attribute we recognize, so just check the
3056 ordinary setattr permission. */
3057 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003061 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 return -EOPNOTSUPP;
3063
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003064 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 return -EPERM;
3066
Eric Paris50c205f2012-04-04 15:01:43 -04003067 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003068 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Paul Moore20cdef82016-04-04 14:14:42 -04003070 isec = backing_inode_security(dentry);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003071 rc = avc_has_perm(&selinux_state,
3072 sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 FILE__RELABELFROM, &ad);
3074 if (rc)
3075 return rc;
3076
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003077 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3078 GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003079 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003080 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003081 struct audit_buffer *ab;
3082 size_t audit_size;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003083
3084 /* We strip a nul only if it is at the end, otherwise the
3085 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003086 if (value) {
Colin Ian Kingadd24372017-10-14 13:46:55 +01003087 const char *str = value;
3088
Al Viroe3fea3f2012-06-09 08:15:16 +01003089 if (str[size - 1] == '\0')
3090 audit_size = size - 1;
3091 else
3092 audit_size = size;
3093 } else {
Al Viroe3fea3f2012-06-09 08:15:16 +01003094 audit_size = 0;
3095 }
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04003096 ab = audit_log_start(audit_context(),
3097 GFP_ATOMIC, AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04003098 audit_log_format(ab, "op=setxattr invalid_context=");
3099 audit_log_n_untrustedstring(ab, value, audit_size);
3100 audit_log_end(ab);
3101
Stephen Smalley12b29f32008-05-07 13:03:20 -04003102 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003103 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003104 rc = security_context_to_sid_force(&selinux_state, value,
3105 size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 if (rc)
3108 return rc;
3109
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003110 rc = avc_has_perm(&selinux_state,
3111 sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 FILE__RELABELTO, &ad);
3113 if (rc)
3114 return rc;
3115
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003116 rc = security_validate_transition(&selinux_state, isec->sid, newsid,
3117 sid, isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 if (rc)
3119 return rc;
3120
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003121 return avc_has_perm(&selinux_state,
3122 newsid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 sbsec->sid,
3124 SECCLASS_FILESYSTEM,
3125 FILESYSTEM__ASSOCIATE,
3126 &ad);
3127}
3128
David Howells8f0cfa52008-04-29 00:59:41 -07003129static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003130 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003131 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132{
David Howellsc6f493d2015-03-17 22:26:22 +00003133 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003134 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 u32 newsid;
3136 int rc;
3137
3138 if (strcmp(name, XATTR_NAME_SELINUX)) {
3139 /* Not an attribute we recognize, so nothing to do. */
3140 return;
3141 }
3142
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003143 rc = security_context_to_sid_force(&selinux_state, value, size,
3144 &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 if (rc) {
peter enderborgc103a912018-06-12 10:09:03 +02003146 pr_err("SELinux: unable to map context to SID"
Stephen Smalley12b29f32008-05-07 13:03:20 -04003147 "for (%s, %lu), rc=%d\n",
3148 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 return;
3150 }
3151
Paul Moore20cdef82016-04-04 14:14:42 -04003152 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003153 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003154 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003156 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003157 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 return;
3160}
3161
David Howells8f0cfa52008-04-29 00:59:41 -07003162static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163{
David Howells88e67f32008-11-14 10:39:21 +11003164 const struct cred *cred = current_cred();
3165
Eric Paris2875fa02011-04-28 16:04:24 -04003166 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167}
3168
Eric Paris828dfe12008-04-17 13:17:49 -04003169static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170{
David Howells88e67f32008-11-14 10:39:21 +11003171 const struct cred *cred = current_cred();
3172
Eric Paris2875fa02011-04-28 16:04:24 -04003173 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174}
3175
David Howells8f0cfa52008-04-29 00:59:41 -07003176static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177{
Eric W. Biederman6b240302017-10-02 09:38:20 -05003178 if (strcmp(name, XATTR_NAME_SELINUX)) {
3179 int rc = cap_inode_removexattr(dentry, name);
3180 if (rc)
3181 return rc;
3182
3183 /* Not an attribute we recognize, so just check the
3184 ordinary setattr permission. */
3185 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
3188 /* No one is allowed to remove a SELinux security label.
3189 You can change the label, but all data must be labeled. */
3190 return -EACCES;
3191}
3192
James Morrisd381d8a2005-10-30 14:59:22 -08003193/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003194 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003195 *
3196 * Permission check is handled by selinux_inode_getxattr hook.
3197 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003198static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199{
David P. Quigley42492592008-02-04 22:29:39 -08003200 u32 size;
3201 int error;
3202 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003203 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003205 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3206 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003208 /*
3209 * If the caller has CAP_MAC_ADMIN, then get the raw context
3210 * value even if it is not defined by current policy; otherwise,
3211 * use the in-core value under current policy.
3212 * Use the non-auditing forms of the permission checks since
3213 * getxattr may be called by unprivileged processes commonly
3214 * and lack of permission just means that we fall back to the
3215 * in-core context value, not a denial.
3216 */
Paul Moore20cdef82016-04-04 14:14:42 -04003217 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003218 if (has_cap_mac_admin(false))
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003219 error = security_sid_to_context_force(&selinux_state,
3220 isec->sid, &context,
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003221 &size);
3222 else
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003223 error = security_sid_to_context(&selinux_state, isec->sid,
3224 &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003225 if (error)
3226 return error;
3227 error = size;
3228 if (alloc) {
3229 *buffer = context;
3230 goto out_nofree;
3231 }
3232 kfree(context);
3233out_nofree:
3234 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235}
3236
3237static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003238 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239{
Paul Moore2c971652016-04-19 16:36:28 -04003240 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 u32 newsid;
3242 int rc;
3243
3244 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3245 return -EOPNOTSUPP;
3246
3247 if (!value || !size)
3248 return -EACCES;
3249
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003250 rc = security_context_to_sid(&selinux_state, value, size, &newsid,
3251 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 if (rc)
3253 return rc;
3254
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003255 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003256 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003258 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003259 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 return 0;
3261}
3262
3263static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3264{
3265 const int len = sizeof(XATTR_NAME_SELINUX);
3266 if (buffer && len <= buffer_size)
3267 memcpy(buffer, XATTR_NAME_SELINUX, len);
3268 return len;
3269}
3270
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003271static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003272{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003273 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003274 *secid = isec->sid;
3275}
3276
Vivek Goyal56909eb2016-07-13 10:44:48 -04003277static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3278{
3279 u32 sid;
3280 struct task_security_struct *tsec;
3281 struct cred *new_creds = *new;
3282
3283 if (new_creds == NULL) {
3284 new_creds = prepare_creds();
3285 if (!new_creds)
3286 return -ENOMEM;
3287 }
3288
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003289 tsec = selinux_cred(new_creds);
Vivek Goyal56909eb2016-07-13 10:44:48 -04003290 /* Get label from overlay inode and set it in create_sid */
3291 selinux_inode_getsecid(d_inode(src), &sid);
3292 tsec->create_sid = sid;
3293 *new = new_creds;
3294 return 0;
3295}
3296
Vivek Goyal19472b62016-07-13 10:44:50 -04003297static int selinux_inode_copy_up_xattr(const char *name)
3298{
3299 /* The copy_up hook above sets the initial context on an inode, but we
3300 * don't then want to overwrite it by blindly copying all the lower
3301 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3302 */
3303 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3304 return 1; /* Discard */
3305 /*
3306 * Any other attribute apart from SELINUX is not claimed, supported
3307 * by selinux.
3308 */
3309 return -EOPNOTSUPP;
3310}
3311
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312/* file security operations */
3313
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003314static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315{
David Howells88e67f32008-11-14 10:39:21 +11003316 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003317 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3320 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3321 mask |= MAY_APPEND;
3322
Paul Moore389fb8002009-03-27 17:10:34 -04003323 return file_has_perm(cred, file,
3324 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325}
3326
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003327static int selinux_file_permission(struct file *file, int mask)
3328{
Al Viro496ad9a2013-01-23 17:07:38 -05003329 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003330 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003331 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003332 u32 sid = current_sid();
3333
Paul Moore389fb8002009-03-27 17:10:34 -04003334 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003335 /* No permission to check. Existence test. */
3336 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003337
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003338 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003339 if (sid == fsec->sid && fsec->isid == isec->sid &&
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003340 fsec->pseqno == avc_policy_seqno(&selinux_state))
Eric Paris83d49852012-04-04 13:45:40 -04003341 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003342 return 0;
3343
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003344 return selinux_revalidate_file_permission(file, mask);
3345}
3346
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347static int selinux_file_alloc_security(struct file *file)
3348{
3349 return file_alloc_security(file);
3350}
3351
3352static void selinux_file_free_security(struct file *file)
3353{
3354 file_free_security(file);
3355}
3356
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003357/*
3358 * Check whether a task has the ioctl permission and cmd
3359 * operation to an inode.
3360 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003361static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003362 u32 requested, u16 cmd)
3363{
3364 struct common_audit_data ad;
3365 struct file_security_struct *fsec = file->f_security;
3366 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003367 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003368 struct lsm_ioctlop_audit ioctl;
3369 u32 ssid = cred_sid(cred);
3370 int rc;
3371 u8 driver = cmd >> 8;
3372 u8 xperm = cmd & 0xff;
3373
3374 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3375 ad.u.op = &ioctl;
3376 ad.u.op->cmd = cmd;
3377 ad.u.op->path = file->f_path;
3378
3379 if (ssid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003380 rc = avc_has_perm(&selinux_state,
3381 ssid, fsec->sid,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003382 SECCLASS_FD,
3383 FD__USE,
3384 &ad);
3385 if (rc)
3386 goto out;
3387 }
3388
3389 if (unlikely(IS_PRIVATE(inode)))
3390 return 0;
3391
Paul Moore20cdef82016-04-04 14:14:42 -04003392 isec = inode_security(inode);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003393 rc = avc_has_extended_perms(&selinux_state,
3394 ssid, isec->sid, isec->sclass,
3395 requested, driver, xperm, &ad);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003396out:
3397 return rc;
3398}
3399
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3401 unsigned long arg)
3402{
David Howells88e67f32008-11-14 10:39:21 +11003403 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003404 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Eric Paris0b24dcb2011-02-25 15:39:20 -05003406 switch (cmd) {
3407 case FIONREAD:
3408 /* fall through */
3409 case FIBMAP:
3410 /* fall through */
3411 case FIGETBSZ:
3412 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003413 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003414 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003415 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003416 error = file_has_perm(cred, file, FILE__GETATTR);
3417 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418
Al Viro2f99c362012-03-23 16:04:05 -04003419 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003420 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003421 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003422 error = file_has_perm(cred, file, FILE__SETATTR);
3423 break;
3424
3425 /* sys_ioctl() checks */
3426 case FIONBIO:
3427 /* fall through */
3428 case FIOASYNC:
3429 error = file_has_perm(cred, file, 0);
3430 break;
3431
3432 case KDSKBENT:
3433 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003434 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003435 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003436 break;
3437
3438 /* default case assumes that the command will go
3439 * to the file's ioctl() function.
3440 */
3441 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003442 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003443 }
3444 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445}
3446
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003447static int default_noexec;
3448
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3450{
David Howells88e67f32008-11-14 10:39:21 +11003451 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003452 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003453 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003454
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003455 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003456 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3457 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 /*
3459 * We are making executable an anonymous mapping or a
3460 * private file mapping that will also be writable.
3461 * This has an additional check.
3462 */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003463 rc = avc_has_perm(&selinux_state,
3464 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003465 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003467 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
3470 if (file) {
3471 /* read access is always possible with a mapping */
3472 u32 av = FILE__READ;
3473
3474 /* write access only matters if the mapping is shared */
3475 if (shared && (prot & PROT_WRITE))
3476 av |= FILE__WRITE;
3477
3478 if (prot & PROT_EXEC)
3479 av |= FILE__EXECUTE;
3480
David Howells88e67f32008-11-14 10:39:21 +11003481 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 }
David Howellsd84f4f92008-11-14 10:39:23 +11003483
3484error:
3485 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486}
3487
Al Viroe5467852012-05-30 13:30:51 -04003488static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003490 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003491
3492 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3493 u32 sid = current_sid();
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003494 rc = avc_has_perm(&selinux_state,
3495 sid, sid, SECCLASS_MEMPROTECT,
Paul Moore98883bf2014-03-19 16:46:11 -04003496 MEMPROTECT__MMAP_ZERO, NULL);
3497 }
3498
3499 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003500}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501
Al Viroe5467852012-05-30 13:30:51 -04003502static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3503 unsigned long prot, unsigned long flags)
3504{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003505 struct common_audit_data ad;
3506 int rc;
3507
3508 if (file) {
3509 ad.type = LSM_AUDIT_DATA_FILE;
3510 ad.u.file = file;
3511 rc = inode_has_perm(current_cred(), file_inode(file),
3512 FILE__MAP, &ad);
3513 if (rc)
3514 return rc;
3515 }
3516
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003517 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 prot = reqprot;
3519
3520 return file_map_prot_check(file, prot,
3521 (flags & MAP_TYPE) == MAP_SHARED);
3522}
3523
3524static int selinux_file_mprotect(struct vm_area_struct *vma,
3525 unsigned long reqprot,
3526 unsigned long prot)
3527{
David Howells88e67f32008-11-14 10:39:21 +11003528 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003529 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05003531 if (selinux_state.checkreqprot)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 prot = reqprot;
3533
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003534 if (default_noexec &&
3535 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003536 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003537 if (vma->vm_start >= vma->vm_mm->start_brk &&
3538 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003539 rc = avc_has_perm(&selinux_state,
3540 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003541 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003542 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003543 ((vma->vm_start <= vma->vm_mm->start_stack &&
3544 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003545 vma_is_stack_for_current(vma))) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003546 rc = avc_has_perm(&selinux_state,
3547 sid, sid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003548 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003549 } else if (vma->vm_file && vma->anon_vma) {
3550 /*
3551 * We are making executable a file mapping that has
3552 * had some COW done. Since pages might have been
3553 * written, check ability to execute the possibly
3554 * modified content. This typically should only
3555 * occur for text relocations.
3556 */
David Howellsd84f4f92008-11-14 10:39:23 +11003557 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003558 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003559 if (rc)
3560 return rc;
3561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
3563 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3564}
3565
3566static int selinux_file_lock(struct file *file, unsigned int cmd)
3567{
David Howells88e67f32008-11-14 10:39:21 +11003568 const struct cred *cred = current_cred();
3569
3570 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571}
3572
3573static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3574 unsigned long arg)
3575{
David Howells88e67f32008-11-14 10:39:21 +11003576 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 int err = 0;
3578
3579 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003580 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003581 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003582 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003584 }
3585 /* fall through */
3586 case F_SETOWN:
3587 case F_SETSIG:
3588 case F_GETFL:
3589 case F_GETOWN:
3590 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003591 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003592 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003593 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003594 break;
3595 case F_GETLK:
3596 case F_SETLK:
3597 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003598 case F_OFD_GETLK:
3599 case F_OFD_SETLK:
3600 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003602 case F_GETLK64:
3603 case F_SETLK64:
3604 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605#endif
David Howells88e67f32008-11-14 10:39:21 +11003606 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003607 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 }
3609
3610 return err;
3611}
3612
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003613static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 struct file_security_struct *fsec;
3616
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003618 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619}
3620
3621static int selinux_file_send_sigiotask(struct task_struct *tsk,
3622 struct fown_struct *fown, int signum)
3623{
Eric Paris828dfe12008-04-17 13:17:49 -04003624 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003625 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 struct file_security_struct *fsec;
3628
3629 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003630 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 fsec = file->f_security;
3633
3634 if (!signum)
3635 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3636 else
3637 perm = signal_to_av(signum);
3638
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003639 return avc_has_perm(&selinux_state,
3640 fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 SECCLASS_PROCESS, perm, NULL);
3642}
3643
3644static int selinux_file_receive(struct file *file)
3645{
David Howells88e67f32008-11-14 10:39:21 +11003646 const struct cred *cred = current_cred();
3647
3648 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649}
3650
Al Viro94817692018-07-10 14:13:18 -04003651static int selinux_file_open(struct file *file)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003652{
3653 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003654 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003655
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003656 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003657 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003658 /*
3659 * Save inode label and policy sequence number
3660 * at open-time so that selinux_file_permission
3661 * can determine whether revalidation is necessary.
3662 * Task label is already saved in the file security
3663 * struct as its SID.
3664 */
3665 fsec->isid = isec->sid;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003666 fsec->pseqno = avc_policy_seqno(&selinux_state);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003667 /*
3668 * Since the inode label or policy seqno may have changed
3669 * between the selinux_inode_permission check and the saving
3670 * of state above, recheck that access is still permitted.
3671 * Otherwise, access might never be revalidated against the
3672 * new inode label or new policy.
3673 * This check is not redundant - do not remove.
3674 */
Al Viro94817692018-07-10 14:13:18 -04003675 return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003676}
3677
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678/* task security operations */
3679
Tetsuo Handaa79be232017-03-28 23:08:45 +09003680static int selinux_task_alloc(struct task_struct *task,
3681 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003683 u32 sid = current_sid();
3684
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003685 return avc_has_perm(&selinux_state,
3686 sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687}
3688
David Howellsf1752ee2008-11-14 10:39:17 +11003689/*
David Howellsee18d642009-09-02 09:14:21 +01003690 * allocate the SELinux part of blank credentials
3691 */
3692static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3693{
3694 struct task_security_struct *tsec;
3695
3696 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3697 if (!tsec)
3698 return -ENOMEM;
3699
3700 cred->security = tsec;
3701 return 0;
3702}
3703
3704/*
David Howellsf1752ee2008-11-14 10:39:17 +11003705 * detach and free the LSM part of a set of credentials
3706 */
3707static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003709 struct task_security_struct *tsec = selinux_cred(cred);
David Howellse0e81732009-09-02 09:13:40 +01003710
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003711 /*
3712 * cred->security == NULL if security_cred_alloc_blank() or
3713 * security_prepare_creds() returned an error.
3714 */
3715 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003716 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003717 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718}
3719
David Howellsd84f4f92008-11-14 10:39:23 +11003720/*
3721 * prepare a new set of credentials for modification
3722 */
3723static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3724 gfp_t gfp)
3725{
3726 const struct task_security_struct *old_tsec;
3727 struct task_security_struct *tsec;
3728
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003729 old_tsec = selinux_cred(old);
David Howellsd84f4f92008-11-14 10:39:23 +11003730
3731 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3732 if (!tsec)
3733 return -ENOMEM;
3734
3735 new->security = tsec;
3736 return 0;
3737}
3738
3739/*
David Howellsee18d642009-09-02 09:14:21 +01003740 * transfer the SELinux data to a blank set of creds
3741 */
3742static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3743{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003744 const struct task_security_struct *old_tsec = selinux_cred(old);
3745 struct task_security_struct *tsec = selinux_cred(new);
David Howellsee18d642009-09-02 09:14:21 +01003746
3747 *tsec = *old_tsec;
3748}
3749
Matthew Garrett3ec30112018-01-08 13:36:19 -08003750static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
3751{
3752 *secid = cred_sid(c);
3753}
3754
David Howellsee18d642009-09-02 09:14:21 +01003755/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003756 * set the security data for a kernel service
3757 * - all the creation contexts are set to unlabelled
3758 */
3759static int selinux_kernel_act_as(struct cred *new, u32 secid)
3760{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003761 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003762 u32 sid = current_sid();
3763 int ret;
3764
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003765 ret = avc_has_perm(&selinux_state,
3766 sid, secid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003767 SECCLASS_KERNEL_SERVICE,
3768 KERNEL_SERVICE__USE_AS_OVERRIDE,
3769 NULL);
3770 if (ret == 0) {
3771 tsec->sid = secid;
3772 tsec->create_sid = 0;
3773 tsec->keycreate_sid = 0;
3774 tsec->sockcreate_sid = 0;
3775 }
3776 return ret;
3777}
3778
3779/*
3780 * set the file creation context in a security record to the same as the
3781 * objective context of the specified inode
3782 */
3783static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3784{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003785 struct inode_security_struct *isec = inode_security(inode);
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07003786 struct task_security_struct *tsec = selinux_cred(new);
David Howells3a3b7ce2008-11-14 10:39:28 +11003787 u32 sid = current_sid();
3788 int ret;
3789
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003790 ret = avc_has_perm(&selinux_state,
3791 sid, isec->sid,
David Howells3a3b7ce2008-11-14 10:39:28 +11003792 SECCLASS_KERNEL_SERVICE,
3793 KERNEL_SERVICE__CREATE_FILES_AS,
3794 NULL);
3795
3796 if (ret == 0)
3797 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003798 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003799}
3800
Eric Parisdd8dbf22009-11-03 16:35:32 +11003801static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003802{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003803 struct common_audit_data ad;
3804
Eric Paris50c205f2012-04-04 15:01:43 -04003805 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003806 ad.u.kmod_name = kmod_name;
3807
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003808 return avc_has_perm(&selinux_state,
3809 current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11003810 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003811}
3812
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003813static int selinux_kernel_module_from_file(struct file *file)
3814{
3815 struct common_audit_data ad;
3816 struct inode_security_struct *isec;
3817 struct file_security_struct *fsec;
3818 u32 sid = current_sid();
3819 int rc;
3820
3821 /* init_module */
3822 if (file == NULL)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003823 return avc_has_perm(&selinux_state,
3824 sid, sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003825 SYSTEM__MODULE_LOAD, NULL);
3826
3827 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003828
Vivek Goyal43af5de2016-09-09 11:37:49 -04003829 ad.type = LSM_AUDIT_DATA_FILE;
3830 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003831
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003832 fsec = file->f_security;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003833 if (sid != fsec->sid) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003834 rc = avc_has_perm(&selinux_state,
3835 sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003836 if (rc)
3837 return rc;
3838 }
3839
Paul Moore20cdef82016-04-04 14:14:42 -04003840 isec = inode_security(file_inode(file));
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003841 return avc_has_perm(&selinux_state,
3842 sid, isec->sid, SECCLASS_SYSTEM,
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003843 SYSTEM__MODULE_LOAD, &ad);
3844}
3845
3846static int selinux_kernel_read_file(struct file *file,
3847 enum kernel_read_file_id id)
3848{
3849 int rc = 0;
3850
3851 switch (id) {
3852 case READING_MODULE:
3853 rc = selinux_kernel_module_from_file(file);
3854 break;
3855 default:
3856 break;
3857 }
3858
3859 return rc;
3860}
3861
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04003862static int selinux_kernel_load_data(enum kernel_load_data_id id)
3863{
3864 int rc = 0;
3865
3866 switch (id) {
3867 case LOADING_MODULE:
3868 rc = selinux_kernel_module_from_file(NULL);
3869 default:
3870 break;
3871 }
3872
3873 return rc;
3874}
3875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3877{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003878 return avc_has_perm(&selinux_state,
3879 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003880 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881}
3882
3883static int selinux_task_getpgid(struct task_struct *p)
3884{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003885 return avc_has_perm(&selinux_state,
3886 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003887 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
3890static int selinux_task_getsid(struct task_struct *p)
3891{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003892 return avc_has_perm(&selinux_state,
3893 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003894 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895}
3896
David Quigleyf9008e4c2006-06-30 01:55:46 -07003897static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3898{
David Howells275bb412008-11-14 10:39:19 +11003899 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003900}
3901
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902static int selinux_task_setnice(struct task_struct *p, int nice)
3903{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003904 return avc_has_perm(&selinux_state,
3905 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003906 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907}
3908
James Morris03e68062006-06-23 02:03:58 -07003909static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3910{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003911 return avc_has_perm(&selinux_state,
3912 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003913 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07003914}
3915
David Quigleya1836a42006-06-30 01:55:49 -07003916static int selinux_task_getioprio(struct task_struct *p)
3917{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003918 return avc_has_perm(&selinux_state,
3919 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003920 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07003921}
3922
Corentin LABBE42985552017-10-04 20:32:18 +02003923static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
3924 unsigned int flags)
Stephen Smalley791ec492017-02-17 07:57:00 -05003925{
3926 u32 av = 0;
3927
Stephen Smalley84e68852017-02-28 09:35:08 -05003928 if (!flags)
3929 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05003930 if (flags & LSM_PRLIMIT_WRITE)
3931 av |= PROCESS__SETRLIMIT;
3932 if (flags & LSM_PRLIMIT_READ)
3933 av |= PROCESS__GETRLIMIT;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003934 return avc_has_perm(&selinux_state,
3935 cred_sid(cred), cred_sid(tcred),
Stephen Smalley791ec492017-02-17 07:57:00 -05003936 SECCLASS_PROCESS, av, NULL);
3937}
3938
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003939static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3940 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003942 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
3944 /* Control the ability to change the hard limit (whether
3945 lowering or raising it), so that the hard limit can
3946 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003947 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003949 return avc_has_perm(&selinux_state,
3950 current_sid(), task_sid(p),
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003951 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952
3953 return 0;
3954}
3955
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003956static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003958 return avc_has_perm(&selinux_state,
3959 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003960 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961}
3962
3963static int selinux_task_getscheduler(struct task_struct *p)
3964{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003965 return avc_has_perm(&selinux_state,
3966 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003967 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968}
3969
David Quigley35601542006-06-23 02:04:01 -07003970static int selinux_task_movememory(struct task_struct *p)
3971{
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003972 return avc_has_perm(&selinux_state,
3973 current_sid(), task_sid(p), SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003974 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07003975}
3976
Eric W. Biedermanae7795b2018-09-25 11:27:20 +02003977static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04003978 int sig, const struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979{
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04003980 u32 secid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 if (!sig)
3984 perm = PROCESS__SIGNULL; /* null signal; existence test */
3985 else
3986 perm = signal_to_av(sig);
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04003987 if (!cred)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003988 secid = current_sid();
Stephen Smalley6b4f3d02017-09-08 12:40:01 -04003989 else
3990 secid = cred_sid(cred);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05003991 return avc_has_perm(&selinux_state,
3992 secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993}
3994
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995static void selinux_task_to_inode(struct task_struct *p,
3996 struct inode *inode)
3997{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003999 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004001 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004002 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004003 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004004 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004005 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006}
4007
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004009static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004010 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011{
4012 int offset, ihlen, ret = -EINVAL;
4013 struct iphdr _iph, *ih;
4014
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004015 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4017 if (ih == NULL)
4018 goto out;
4019
4020 ihlen = ih->ihl * 4;
4021 if (ihlen < sizeof(_iph))
4022 goto out;
4023
Eric Paris48c62af2012-04-02 13:15:44 -04004024 ad->u.net->v4info.saddr = ih->saddr;
4025 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 ret = 0;
4027
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004028 if (proto)
4029 *proto = ih->protocol;
4030
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004032 case IPPROTO_TCP: {
4033 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
Eric Paris828dfe12008-04-17 13:17:49 -04004035 if (ntohs(ih->frag_off) & IP_OFFSET)
4036 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
4038 offset += ihlen;
4039 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4040 if (th == NULL)
4041 break;
4042
Eric Paris48c62af2012-04-02 13:15:44 -04004043 ad->u.net->sport = th->source;
4044 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
Eric Paris828dfe12008-04-17 13:17:49 -04004048 case IPPROTO_UDP: {
4049 struct udphdr _udph, *uh;
4050
4051 if (ntohs(ih->frag_off) & IP_OFFSET)
4052 break;
4053
4054 offset += ihlen;
4055 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4056 if (uh == NULL)
4057 break;
4058
Eric Paris48c62af2012-04-02 13:15:44 -04004059 ad->u.net->sport = uh->source;
4060 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004061 break;
4062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
James Morris2ee92d42006-11-13 16:09:01 -08004064 case IPPROTO_DCCP: {
4065 struct dccp_hdr _dccph, *dh;
4066
4067 if (ntohs(ih->frag_off) & IP_OFFSET)
4068 break;
4069
4070 offset += ihlen;
4071 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4072 if (dh == NULL)
4073 break;
4074
Eric Paris48c62af2012-04-02 13:15:44 -04004075 ad->u.net->sport = dh->dccph_sport;
4076 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004077 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004078 }
James Morris2ee92d42006-11-13 16:09:01 -08004079
Richard Hainesd4529302018-02-13 20:57:18 +00004080#if IS_ENABLED(CONFIG_IP_SCTP)
4081 case IPPROTO_SCTP: {
4082 struct sctphdr _sctph, *sh;
4083
4084 if (ntohs(ih->frag_off) & IP_OFFSET)
4085 break;
4086
4087 offset += ihlen;
4088 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4089 if (sh == NULL)
4090 break;
4091
4092 ad->u.net->sport = sh->source;
4093 ad->u.net->dport = sh->dest;
4094 break;
4095 }
4096#endif
Eric Paris828dfe12008-04-17 13:17:49 -04004097 default:
4098 break;
4099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100out:
4101 return ret;
4102}
4103
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004104#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
4106/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004107static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004108 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109{
4110 u8 nexthdr;
4111 int ret = -EINVAL, offset;
4112 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004113 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004115 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4117 if (ip6 == NULL)
4118 goto out;
4119
Eric Paris48c62af2012-04-02 13:15:44 -04004120 ad->u.net->v6info.saddr = ip6->saddr;
4121 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 ret = 0;
4123
4124 nexthdr = ip6->nexthdr;
4125 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004126 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 if (offset < 0)
4128 goto out;
4129
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004130 if (proto)
4131 *proto = nexthdr;
4132
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 switch (nexthdr) {
4134 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004135 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
4137 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4138 if (th == NULL)
4139 break;
4140
Eric Paris48c62af2012-04-02 13:15:44 -04004141 ad->u.net->sport = th->source;
4142 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 break;
4144 }
4145
4146 case IPPROTO_UDP: {
4147 struct udphdr _udph, *uh;
4148
4149 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4150 if (uh == NULL)
4151 break;
4152
Eric Paris48c62af2012-04-02 13:15:44 -04004153 ad->u.net->sport = uh->source;
4154 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 break;
4156 }
4157
James Morris2ee92d42006-11-13 16:09:01 -08004158 case IPPROTO_DCCP: {
4159 struct dccp_hdr _dccph, *dh;
4160
4161 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4162 if (dh == NULL)
4163 break;
4164
Eric Paris48c62af2012-04-02 13:15:44 -04004165 ad->u.net->sport = dh->dccph_sport;
4166 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004167 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004168 }
James Morris2ee92d42006-11-13 16:09:01 -08004169
Richard Hainesd4529302018-02-13 20:57:18 +00004170#if IS_ENABLED(CONFIG_IP_SCTP)
4171 case IPPROTO_SCTP: {
4172 struct sctphdr _sctph, *sh;
4173
4174 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4175 if (sh == NULL)
4176 break;
4177
4178 ad->u.net->sport = sh->source;
4179 ad->u.net->dport = sh->dest;
4180 break;
4181 }
4182#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 /* includes fragments */
4184 default:
4185 break;
4186 }
4187out:
4188 return ret;
4189}
4190
4191#endif /* IPV6 */
4192
Thomas Liu2bf49692009-07-14 12:14:09 -04004193static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004194 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195{
David Howellscf9481e2008-07-27 21:31:07 +10004196 char *addrp;
4197 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
Eric Paris48c62af2012-04-02 13:15:44 -04004199 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004201 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004202 if (ret)
4203 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004204 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4205 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004206 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004208#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004210 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004211 if (ret)
4212 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004213 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4214 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004215 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216#endif /* IPV6 */
4217 default:
David Howellscf9481e2008-07-27 21:31:07 +10004218 addrp = NULL;
4219 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 }
4221
David Howellscf9481e2008-07-27 21:31:07 +10004222parse_error:
peter enderborgc103a912018-06-12 10:09:03 +02004223 pr_warn(
David Howellscf9481e2008-07-27 21:31:07 +10004224 "SELinux: failure in selinux_parse_skb(),"
4225 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004227
4228okay:
4229 if (_addrp)
4230 *_addrp = addrp;
4231 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232}
4233
Paul Moore4f6a9932007-03-01 14:35:22 -05004234/**
Paul Moore220deb92008-01-29 08:38:23 -05004235 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004236 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004237 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004238 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004239 *
4240 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004241 * Check the various different forms of network peer labeling and determine
4242 * the peer label/SID for the packet; most of the magic actually occurs in
4243 * the security server function security_net_peersid_cmp(). The function
4244 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4245 * or -EACCES if @sid is invalid due to inconsistencies with the different
4246 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004247 *
4248 */
Paul Moore220deb92008-01-29 08:38:23 -05004249static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004250{
Paul Moore71f1cb02008-01-29 08:51:16 -05004251 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004252 u32 xfrm_sid;
4253 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004254 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004255
Paul Moore817eff72013-12-10 14:57:54 -05004256 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004257 if (unlikely(err))
4258 return -EACCES;
4259 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4260 if (unlikely(err))
4261 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004262
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004263 err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
4264 nlbl_type, xfrm_sid, sid);
Paul Moore71f1cb02008-01-29 08:51:16 -05004265 if (unlikely(err)) {
peter enderborgc103a912018-06-12 10:09:03 +02004266 pr_warn(
Paul Moore71f1cb02008-01-29 08:51:16 -05004267 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4268 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004269 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004270 }
Paul Moore220deb92008-01-29 08:38:23 -05004271
4272 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004273}
4274
Paul Moore446b8022013-12-04 16:10:51 -05004275/**
4276 * selinux_conn_sid - Determine the child socket label for a connection
4277 * @sk_sid: the parent socket's SID
4278 * @skb_sid: the packet's SID
4279 * @conn_sid: the resulting connection SID
4280 *
4281 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4282 * combined with the MLS information from @skb_sid in order to create
4283 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4284 * of @sk_sid. Returns zero on success, negative values on failure.
4285 *
4286 */
4287static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4288{
4289 int err = 0;
4290
4291 if (skb_sid != SECSID_NULL)
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004292 err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
4293 conn_sid);
Paul Moore446b8022013-12-04 16:10:51 -05004294 else
4295 *conn_sid = sk_sid;
4296
4297 return err;
4298}
4299
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004301
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004302static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4303 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004304{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004305 if (tsec->sockcreate_sid > SECSID_NULL) {
4306 *socksid = tsec->sockcreate_sid;
4307 return 0;
4308 }
4309
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004310 return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
4311 secclass, NULL, socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004312}
4313
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004314static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315{
Paul Moore253bfae2010-04-22 14:46:19 -04004316 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004317 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004318 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Paul Moore253bfae2010-04-22 14:46:19 -04004320 if (sksec->sid == SECINITSID_KERNEL)
4321 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Eric Paris50c205f2012-04-04 15:01:43 -04004323 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004324 ad.u.net = &net;
4325 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004327 return avc_has_perm(&selinux_state,
4328 current_sid(), sksec->sid, sksec->sclass, perms,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004329 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330}
4331
4332static int selinux_socket_create(int family, int type,
4333 int protocol, int kern)
4334{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004335 const struct task_security_struct *tsec = selinux_cred(current_cred());
Paul Moored4f2d972010-04-22 14:46:18 -04004336 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004337 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004338 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
4340 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004341 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
David Howells275bb412008-11-14 10:39:19 +11004343 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004344 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4345 if (rc)
4346 return rc;
4347
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004348 return avc_has_perm(&selinux_state,
4349 tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350}
4351
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004352static int selinux_socket_post_create(struct socket *sock, int family,
4353 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07004355 const struct task_security_struct *tsec = selinux_cred(current_cred());
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004356 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004357 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004358 u16 sclass = socket_type_to_security_class(family, type, protocol);
4359 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004360 int err = 0;
4361
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004362 if (!kern) {
4363 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004364 if (err)
4365 return err;
4366 }
David Howells275bb412008-11-14 10:39:19 +11004367
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004368 isec->sclass = sclass;
4369 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004370 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004372 if (sock->sk) {
4373 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004374 sksec->sclass = sclass;
4375 sksec->sid = sid;
Richard Hainesd4529302018-02-13 20:57:18 +00004376 /* Allows detection of the first association on this socket */
4377 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4378 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4379
Paul Moore389fb8002009-03-27 17:10:34 -04004380 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004381 }
4382
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004383 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384}
4385
David Herrmann0b811db2018-05-04 16:28:21 +02004386static int selinux_socket_socketpair(struct socket *socka,
4387 struct socket *sockb)
4388{
4389 struct sk_security_struct *sksec_a = socka->sk->sk_security;
4390 struct sk_security_struct *sksec_b = sockb->sk->sk_security;
4391
4392 sksec_a->peer_sid = sksec_b->sid;
4393 sksec_b->peer_sid = sksec_a->sid;
4394
4395 return 0;
4396}
4397
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398/* Range of port numbers used to automatically bind.
4399 Need to determine whether we should perform a name_bind
4400 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
4402static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4403{
Paul Moore253bfae2010-04-22 14:46:19 -04004404 struct sock *sk = sock->sk;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004405 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 u16 family;
4407 int err;
4408
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004409 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 if (err)
4411 goto out;
4412
Richard Hainesd4529302018-02-13 20:57:18 +00004413 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
Paul Moore253bfae2010-04-22 14:46:19 -04004414 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 if (family == PF_INET || family == PF_INET6) {
4416 char *addrp;
Thomas Liu2bf49692009-07-14 12:14:09 -04004417 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004418 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 struct sockaddr_in *addr4 = NULL;
4420 struct sockaddr_in6 *addr6 = NULL;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004421 u16 family_sa = address->sa_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004423 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Richard Hainesd4529302018-02-13 20:57:18 +00004425 /*
4426 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4427 * that validates multiple binding addresses. Because of this
4428 * need to check address->sa_family as it is possible to have
4429 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4430 */
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004431 switch (family_sa) {
4432 case AF_UNSPEC:
Richard Haines68741a8a2018-03-02 19:54:34 +00004433 case AF_INET:
4434 if (addrlen < sizeof(struct sockaddr_in))
4435 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 addr4 = (struct sockaddr_in *)address;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004437 if (family_sa == AF_UNSPEC) {
4438 /* see __inet_bind(), we only want to allow
4439 * AF_UNSPEC if the address is INADDR_ANY
4440 */
4441 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4442 goto err_af;
4443 family_sa = AF_INET;
4444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 addrp = (char *)&addr4->sin_addr.s_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004447 break;
4448 case AF_INET6:
4449 if (addrlen < SIN6_LEN_RFC2133)
4450 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 addr6 = (struct sockaddr_in6 *)address;
4452 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 addrp = (char *)&addr6->sin6_addr.s6_addr;
Richard Haines68741a8a2018-03-02 19:54:34 +00004454 break;
4455 default:
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004456 goto err_af;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 }
4458
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004459 ad.type = LSM_AUDIT_DATA_NET;
4460 ad.u.net = &net;
4461 ad.u.net->sport = htons(snum);
4462 ad.u.net->family = family_sa;
4463
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004464 if (snum) {
4465 int low, high;
4466
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004467 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004468
Krister Johansen4548b682017-01-20 17:49:11 -08004469 if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
4470 snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004471 err = sel_netport_sid(sk->sk_protocol,
4472 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004473 if (err)
4474 goto out;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004475 err = avc_has_perm(&selinux_state,
4476 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004477 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004478 SOCKET__NAME_BIND, &ad);
4479 if (err)
4480 goto out;
4481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482 }
Eric Paris828dfe12008-04-17 13:17:49 -04004483
Paul Moore253bfae2010-04-22 14:46:19 -04004484 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004485 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 node_perm = TCP_SOCKET__NODE_BIND;
4487 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004488
James Morris13402582005-09-30 14:24:34 -04004489 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 node_perm = UDP_SOCKET__NODE_BIND;
4491 break;
James Morris2ee92d42006-11-13 16:09:01 -08004492
4493 case SECCLASS_DCCP_SOCKET:
4494 node_perm = DCCP_SOCKET__NODE_BIND;
4495 break;
4496
Richard Hainesd4529302018-02-13 20:57:18 +00004497 case SECCLASS_SCTP_SOCKET:
4498 node_perm = SCTP_SOCKET__NODE_BIND;
4499 break;
4500
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 default:
4502 node_perm = RAWIP_SOCKET__NODE_BIND;
4503 break;
4504 }
Eric Paris828dfe12008-04-17 13:17:49 -04004505
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004506 err = sel_netnode_sid(addrp, family_sa, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 if (err)
4508 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004509
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004510 if (family_sa == AF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004511 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 else
Eric Paris48c62af2012-04-02 13:15:44 -04004513 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004515 err = avc_has_perm(&selinux_state,
4516 sksec->sid, sid,
Paul Moore253bfae2010-04-22 14:46:19 -04004517 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 if (err)
4519 goto out;
4520 }
4521out:
4522 return err;
Alexey Kodanev0f8db8c2018-05-11 20:15:11 +03004523err_af:
4524 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4525 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4526 return -EINVAL;
4527 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528}
4529
Richard Hainesd4529302018-02-13 20:57:18 +00004530/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
Mauro Carvalho Chehab5fb94e92018-05-08 15:14:57 -03004531 * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.rst
Richard Hainesd4529302018-02-13 20:57:18 +00004532 */
4533static int selinux_socket_connect_helper(struct socket *sock,
4534 struct sockaddr *address, int addrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535{
Paul Moore014ab192008-10-10 10:16:33 -04004536 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004537 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 int err;
4539
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004540 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 if (err)
4542 return err;
4543
4544 /*
Richard Hainesd4529302018-02-13 20:57:18 +00004545 * If a TCP, DCCP or SCTP socket, check name_connect permission
4546 * for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 */
Paul Moore253bfae2010-04-22 14:46:19 -04004548 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004549 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4550 sksec->sclass == SECCLASS_SCTP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004551 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004552 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553 struct sockaddr_in *addr4 = NULL;
4554 struct sockaddr_in6 *addr6 = NULL;
4555 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004556 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557
Richard Hainesd4529302018-02-13 20:57:18 +00004558 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4559 * that validates multiple connect addresses. Because of this
4560 * need to check address->sa_family as it is possible to have
4561 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4562 */
Richard Haines68741a8a2018-03-02 19:54:34 +00004563 switch (address->sa_family) {
4564 case AF_INET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004566 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 return -EINVAL;
4568 snum = ntohs(addr4->sin_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004569 break;
4570 case AF_INET6:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004572 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 return -EINVAL;
4574 snum = ntohs(addr6->sin6_port);
Richard Haines68741a8a2018-03-02 19:54:34 +00004575 break;
4576 default:
4577 /* Note that SCTP services expect -EINVAL, whereas
4578 * others expect -EAFNOSUPPORT.
4579 */
4580 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4581 return -EINVAL;
4582 else
4583 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 }
4585
Paul Moore3e1121722008-04-10 10:48:14 -04004586 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004588 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
Richard Hainesd4529302018-02-13 20:57:18 +00004590 switch (sksec->sclass) {
4591 case SECCLASS_TCP_SOCKET:
4592 perm = TCP_SOCKET__NAME_CONNECT;
4593 break;
4594 case SECCLASS_DCCP_SOCKET:
4595 perm = DCCP_SOCKET__NAME_CONNECT;
4596 break;
4597 case SECCLASS_SCTP_SOCKET:
4598 perm = SCTP_SOCKET__NAME_CONNECT;
4599 break;
4600 }
James Morris2ee92d42006-11-13 16:09:01 -08004601
Eric Paris50c205f2012-04-04 15:01:43 -04004602 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004603 ad.u.net = &net;
4604 ad.u.net->dport = htons(snum);
Alexey Kodanev88b7d372018-05-11 20:15:12 +03004605 ad.u.net->family = address->sa_family;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004606 err = avc_has_perm(&selinux_state,
4607 sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 if (err)
Richard Hainesd4529302018-02-13 20:57:18 +00004609 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610 }
4611
Richard Hainesd4529302018-02-13 20:57:18 +00004612 return 0;
4613}
Paul Moore014ab192008-10-10 10:16:33 -04004614
Richard Hainesd4529302018-02-13 20:57:18 +00004615/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4616static int selinux_socket_connect(struct socket *sock,
4617 struct sockaddr *address, int addrlen)
4618{
4619 int err;
4620 struct sock *sk = sock->sk;
4621
4622 err = selinux_socket_connect_helper(sock, address, addrlen);
4623 if (err)
4624 return err;
4625
4626 return selinux_netlbl_socket_connect(sk, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627}
4628
4629static int selinux_socket_listen(struct socket *sock, int backlog)
4630{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004631 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632}
4633
4634static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4635{
4636 int err;
4637 struct inode_security_struct *isec;
4638 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004639 u16 sclass;
4640 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004642 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643 if (err)
4644 return err;
4645
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004646 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004647 spin_lock(&isec->lock);
4648 sclass = isec->sclass;
4649 sid = isec->sid;
4650 spin_unlock(&isec->lock);
4651
4652 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4653 newisec->sclass = sclass;
4654 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004655 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
4657 return 0;
4658}
4659
4660static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004661 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004663 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664}
4665
4666static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4667 int size, int flags)
4668{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004669 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670}
4671
4672static int selinux_socket_getsockname(struct socket *sock)
4673{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004674 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675}
4676
4677static int selinux_socket_getpeername(struct socket *sock)
4678{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004679 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680}
4681
Eric Paris828dfe12008-04-17 13:17:49 -04004682static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683{
Paul Mooref8687af2006-10-30 15:22:15 -08004684 int err;
4685
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004686 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004687 if (err)
4688 return err;
4689
4690 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691}
4692
4693static int selinux_socket_getsockopt(struct socket *sock, int level,
4694 int optname)
4695{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004696 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697}
4698
4699static int selinux_socket_shutdown(struct socket *sock, int how)
4700{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004701 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702}
4703
David S. Miller3610cda2011-01-05 15:38:53 -08004704static int selinux_socket_unix_stream_connect(struct sock *sock,
4705 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706 struct sock *newsk)
4707{
David S. Miller3610cda2011-01-05 15:38:53 -08004708 struct sk_security_struct *sksec_sock = sock->sk_security;
4709 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004710 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004711 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004712 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713 int err;
4714
Eric Paris50c205f2012-04-04 15:01:43 -04004715 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004716 ad.u.net = &net;
4717 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004719 err = avc_has_perm(&selinux_state,
4720 sksec_sock->sid, sksec_other->sid,
Paul Moore4d1e2452010-04-22 14:46:18 -04004721 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4723 if (err)
4724 return err;
4725
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004727 sksec_new->peer_sid = sksec_sock->sid;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004728 err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
4729 sksec_sock->sid, &sksec_new->sid);
Paul Moore4d1e2452010-04-22 14:46:18 -04004730 if (err)
4731 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004732
Paul Moore4d1e2452010-04-22 14:46:18 -04004733 /* connecting socket */
4734 sksec_sock->peer_sid = sksec_new->sid;
4735
4736 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737}
4738
4739static int selinux_socket_unix_may_send(struct socket *sock,
4740 struct socket *other)
4741{
Paul Moore253bfae2010-04-22 14:46:19 -04004742 struct sk_security_struct *ssec = sock->sk->sk_security;
4743 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004744 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004745 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746
Eric Paris50c205f2012-04-04 15:01:43 -04004747 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004748 ad.u.net = &net;
4749 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004751 return avc_has_perm(&selinux_state,
4752 ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
Paul Moore253bfae2010-04-22 14:46:19 -04004753 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754}
4755
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004756static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4757 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004758 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004759{
4760 int err;
4761 u32 if_sid;
4762 u32 node_sid;
4763
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004764 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004765 if (err)
4766 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004767 err = avc_has_perm(&selinux_state,
4768 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004769 SECCLASS_NETIF, NETIF__INGRESS, ad);
4770 if (err)
4771 return err;
4772
4773 err = sel_netnode_sid(addrp, family, &node_sid);
4774 if (err)
4775 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004776 return avc_has_perm(&selinux_state,
4777 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778 SECCLASS_NODE, NODE__RECVFROM, ad);
4779}
4780
Paul Moore220deb92008-01-29 08:38:23 -05004781static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004782 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004783{
Paul Moore277d3422008-12-31 12:54:11 -05004784 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004785 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004786 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004787 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004788 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004789 char *addrp;
4790
Eric Paris50c205f2012-04-04 15:01:43 -04004791 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004792 ad.u.net = &net;
4793 ad.u.net->netif = skb->skb_iif;
4794 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004795 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4796 if (err)
4797 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004798
Paul Moore58bfbb52009-03-27 17:10:41 -04004799 if (selinux_secmark_enabled()) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004800 err = avc_has_perm(&selinux_state,
4801 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004802 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004803 if (err)
4804 return err;
4805 }
Paul Moore220deb92008-01-29 08:38:23 -05004806
Steffen Klassertb9679a72011-02-23 12:55:21 +01004807 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4808 if (err)
4809 return err;
4810 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004811
James Morris4e5ab4c2006-06-09 00:33:33 -07004812 return err;
4813}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004814
James Morris4e5ab4c2006-06-09 00:33:33 -07004815static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4816{
Paul Moore220deb92008-01-29 08:38:23 -05004817 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004818 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004819 u16 family = sk->sk_family;
4820 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004821 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004822 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004823 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004824 u8 secmark_active;
4825 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004826
James Morris4e5ab4c2006-06-09 00:33:33 -07004827 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004828 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004829
4830 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004831 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004832 family = PF_INET;
4833
Paul Moored8395c82008-10-10 10:16:30 -04004834 /* If any sort of compatibility mode is enabled then handoff processing
4835 * to the selinux_sock_rcv_skb_compat() function to deal with the
4836 * special handling. We do this in an attempt to keep this function
4837 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004838 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04004839 return selinux_sock_rcv_skb_compat(sk, skb, family);
4840
4841 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004842 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004843 if (!secmark_active && !peerlbl_active)
4844 return 0;
4845
Eric Paris50c205f2012-04-04 15:01:43 -04004846 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004847 ad.u.net = &net;
4848 ad.u.net->netif = skb->skb_iif;
4849 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004850 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004851 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004852 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004853
Paul Moored8395c82008-10-10 10:16:30 -04004854 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004855 u32 peer_sid;
4856
4857 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4858 if (err)
4859 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004860 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4861 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004862 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004863 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004864 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004865 }
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004866 err = avc_has_perm(&selinux_state,
4867 sk_sid, peer_sid, SECCLASS_PEER,
Paul Moored621d352008-01-29 08:43:36 -05004868 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004869 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004870 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004871 return err;
4872 }
Paul Moored621d352008-01-29 08:43:36 -05004873 }
4874
Paul Moored8395c82008-10-10 10:16:30 -04004875 if (secmark_active) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05004876 err = avc_has_perm(&selinux_state,
4877 sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004878 PACKET__RECV, &ad);
4879 if (err)
4880 return err;
4881 }
4882
Paul Moored621d352008-01-29 08:43:36 -05004883 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004884}
4885
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004886static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4887 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888{
4889 int err = 0;
4890 char *scontext;
4891 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004892 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004893 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894
Paul Moore253bfae2010-04-22 14:46:19 -04004895 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
Richard Hainesd4529302018-02-13 20:57:18 +00004896 sksec->sclass == SECCLASS_TCP_SOCKET ||
4897 sksec->sclass == SECCLASS_SCTP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004898 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004899 if (peer_sid == SECSID_NULL)
4900 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05004902 err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
4903 &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004905 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
4907 if (scontext_len > len) {
4908 err = -ERANGE;
4909 goto out_len;
4910 }
4911
4912 if (copy_to_user(optval, scontext, scontext_len))
4913 err = -EFAULT;
4914
4915out_len:
4916 if (put_user(scontext_len, optlen))
4917 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919 return err;
4920}
4921
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004922static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004923{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004924 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004925 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004926 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004927
Paul Mooreaa862902008-10-10 10:16:29 -04004928 if (skb && skb->protocol == htons(ETH_P_IP))
4929 family = PF_INET;
4930 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4931 family = PF_INET6;
4932 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004933 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004934 else
4935 goto out;
4936
Paul Moore899134f2016-03-28 15:19:10 -04004937 if (sock && family == PF_UNIX) {
4938 isec = inode_security_novalidate(SOCK_INODE(sock));
4939 peer_secid = isec->sid;
4940 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004941 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004942
Paul Moore75e22912008-01-29 08:38:04 -05004943out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004944 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004945 if (peer_secid == SECSID_NULL)
4946 return -EINVAL;
4947 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004948}
4949
Al Viro7d877f32005-10-21 03:20:43 -04004950static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951{
Paul Moore84914b72010-04-22 14:46:18 -04004952 struct sk_security_struct *sksec;
4953
4954 sksec = kzalloc(sizeof(*sksec), priority);
4955 if (!sksec)
4956 return -ENOMEM;
4957
4958 sksec->peer_sid = SECINITSID_UNLABELED;
4959 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004960 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004961 selinux_netlbl_sk_security_reset(sksec);
4962 sk->sk_security = sksec;
4963
4964 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965}
4966
4967static void selinux_sk_free_security(struct sock *sk)
4968{
Paul Moore84914b72010-04-22 14:46:18 -04004969 struct sk_security_struct *sksec = sk->sk_security;
4970
4971 sk->sk_security = NULL;
4972 selinux_netlbl_sk_security_free(sksec);
4973 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974}
4975
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004976static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4977{
Eric Parisdd3e7832010-04-07 15:08:46 -04004978 struct sk_security_struct *sksec = sk->sk_security;
4979 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004980
Eric Parisdd3e7832010-04-07 15:08:46 -04004981 newsksec->sid = sksec->sid;
4982 newsksec->peer_sid = sksec->peer_sid;
4983 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004984
Eric Parisdd3e7832010-04-07 15:08:46 -04004985 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004986}
4987
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004988static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004989{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004990 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004991 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004992 else {
4993 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004994
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004995 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004996 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004997}
4998
Eric Paris828dfe12008-04-17 13:17:49 -04004999static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005000{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05005001 struct inode_security_struct *isec =
5002 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005003 struct sk_security_struct *sksec = sk->sk_security;
5004
Paul Moore2873ead2014-07-28 10:42:48 -04005005 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
5006 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07005007 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05005008 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005009}
5010
Richard Hainesd4529302018-02-13 20:57:18 +00005011/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5012 * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5013 * already present).
5014 */
5015static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5016 struct sk_buff *skb)
5017{
5018 struct sk_security_struct *sksec = ep->base.sk->sk_security;
5019 struct common_audit_data ad;
5020 struct lsm_network_audit net = {0,};
5021 u8 peerlbl_active;
5022 u32 peer_sid = SECINITSID_UNLABELED;
5023 u32 conn_sid;
5024 int err = 0;
5025
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005026 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005027 return 0;
5028
5029 peerlbl_active = selinux_peerlbl_enabled();
5030
5031 if (peerlbl_active) {
5032 /* This will return peer_sid = SECSID_NULL if there are
5033 * no peer labels, see security_net_peersid_resolve().
5034 */
5035 err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5036 &peer_sid);
5037 if (err)
5038 return err;
5039
5040 if (peer_sid == SECSID_NULL)
5041 peer_sid = SECINITSID_UNLABELED;
5042 }
5043
5044 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5045 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5046
5047 /* Here as first association on socket. As the peer SID
5048 * was allowed by peer recv (and the netif/node checks),
5049 * then it is approved by policy and used as the primary
5050 * peer SID for getpeercon(3).
5051 */
5052 sksec->peer_sid = peer_sid;
5053 } else if (sksec->peer_sid != peer_sid) {
5054 /* Other association peer SIDs are checked to enforce
5055 * consistency among the peer SIDs.
5056 */
5057 ad.type = LSM_AUDIT_DATA_NET;
5058 ad.u.net = &net;
5059 ad.u.net->sk = ep->base.sk;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005060 err = avc_has_perm(&selinux_state,
5061 sksec->peer_sid, peer_sid, sksec->sclass,
Richard Hainesd4529302018-02-13 20:57:18 +00005062 SCTP_SOCKET__ASSOCIATION, &ad);
5063 if (err)
5064 return err;
5065 }
5066
5067 /* Compute the MLS component for the connection and store
5068 * the information in ep. This will be used by SCTP TCP type
5069 * sockets and peeled off connections as they cause a new
5070 * socket to be generated. selinux_sctp_sk_clone() will then
5071 * plug this into the new socket.
5072 */
5073 err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5074 if (err)
5075 return err;
5076
5077 ep->secid = conn_sid;
5078 ep->peer_secid = peer_sid;
5079
5080 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
5081 return selinux_netlbl_sctp_assoc_request(ep, skb);
5082}
5083
5084/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5085 * based on their @optname.
5086 */
5087static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5088 struct sockaddr *address,
5089 int addrlen)
5090{
5091 int len, err = 0, walk_size = 0;
5092 void *addr_buf;
5093 struct sockaddr *addr;
5094 struct socket *sock;
5095
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005096 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005097 return 0;
5098
5099 /* Process one or more addresses that may be IPv4 or IPv6 */
5100 sock = sk->sk_socket;
5101 addr_buf = address;
5102
5103 while (walk_size < addrlen) {
Ondrej Mosnacekc1383252018-11-13 16:16:08 +01005104 if (walk_size + sizeof(sa_family_t) > addrlen)
5105 return -EINVAL;
5106
Richard Hainesd4529302018-02-13 20:57:18 +00005107 addr = addr_buf;
5108 switch (addr->sa_family) {
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005109 case AF_UNSPEC:
Richard Hainesd4529302018-02-13 20:57:18 +00005110 case AF_INET:
5111 len = sizeof(struct sockaddr_in);
5112 break;
5113 case AF_INET6:
5114 len = sizeof(struct sockaddr_in6);
5115 break;
5116 default:
Alexey Kodanev4152dc92018-05-11 20:15:13 +03005117 return -EINVAL;
Richard Hainesd4529302018-02-13 20:57:18 +00005118 }
5119
5120 err = -EINVAL;
5121 switch (optname) {
5122 /* Bind checks */
5123 case SCTP_PRIMARY_ADDR:
5124 case SCTP_SET_PEER_PRIMARY_ADDR:
5125 case SCTP_SOCKOPT_BINDX_ADD:
5126 err = selinux_socket_bind(sock, addr, len);
5127 break;
5128 /* Connect checks */
5129 case SCTP_SOCKOPT_CONNECTX:
5130 case SCTP_PARAM_SET_PRIMARY:
5131 case SCTP_PARAM_ADD_IP:
5132 case SCTP_SENDMSG_CONNECT:
5133 err = selinux_socket_connect_helper(sock, addr, len);
5134 if (err)
5135 return err;
5136
5137 /* As selinux_sctp_bind_connect() is called by the
5138 * SCTP protocol layer, the socket is already locked,
5139 * therefore selinux_netlbl_socket_connect_locked() is
5140 * is called here. The situations handled are:
5141 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5142 * whenever a new IP address is added or when a new
5143 * primary address is selected.
5144 * Note that an SCTP connect(2) call happens before
5145 * the SCTP protocol layer and is handled via
5146 * selinux_socket_connect().
5147 */
5148 err = selinux_netlbl_socket_connect_locked(sk, addr);
5149 break;
5150 }
5151
5152 if (err)
5153 return err;
5154
5155 addr_buf += len;
5156 walk_size += len;
5157 }
5158
5159 return 0;
5160}
5161
5162/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
5163static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5164 struct sock *newsk)
5165{
5166 struct sk_security_struct *sksec = sk->sk_security;
5167 struct sk_security_struct *newsksec = newsk->sk_security;
5168
5169 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5170 * the non-sctp clone version.
5171 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005172 if (!selinux_policycap_extsockclass())
Richard Hainesd4529302018-02-13 20:57:18 +00005173 return selinux_sk_clone_security(sk, newsk);
5174
5175 newsksec->sid = ep->secid;
5176 newsksec->peer_sid = ep->peer_secid;
5177 newsksec->sclass = sksec->sclass;
5178 selinux_netlbl_sctp_sk_clone(sk, newsk);
5179}
5180
Adrian Bunk9a673e52006-08-15 00:03:53 -07005181static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
5182 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005183{
5184 struct sk_security_struct *sksec = sk->sk_security;
5185 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05005186 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05005187 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005188 u32 peersid;
5189
Paul Mooreaa862902008-10-10 10:16:29 -04005190 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05005191 if (err)
5192 return err;
Paul Moore446b8022013-12-04 16:10:51 -05005193 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
5194 if (err)
5195 return err;
5196 req->secid = connsid;
5197 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07005198
Paul Moore389fb8002009-03-27 17:10:34 -04005199 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005200}
5201
Adrian Bunk9a673e52006-08-15 00:03:53 -07005202static void selinux_inet_csk_clone(struct sock *newsk,
5203 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005204{
5205 struct sk_security_struct *newsksec = newsk->sk_security;
5206
5207 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005208 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005209 /* NOTE: Ideally, we should also get the isec->sid for the
5210 new socket in sync, but we don't have the isec available yet.
5211 So we will wait until sock_graft to do it, by which
5212 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07005213
Paul Moore9f2ad662006-11-17 17:38:53 -05005214 /* We don't need to take any sort of lock here as we are the only
5215 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04005216 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005217}
5218
Paul Moore014ab192008-10-10 10:16:33 -04005219static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005220{
Paul Mooreaa862902008-10-10 10:16:29 -04005221 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005222 struct sk_security_struct *sksec = sk->sk_security;
5223
Paul Mooreaa862902008-10-10 10:16:29 -04005224 /* handle mapped IPv4 packets arriving via IPv6 sockets */
5225 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
5226 family = PF_INET;
5227
5228 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005229}
5230
Eric Paris2606fd12010-10-13 16:24:41 -04005231static int selinux_secmark_relabel_packet(u32 sid)
5232{
5233 const struct task_security_struct *__tsec;
5234 u32 tsid;
5235
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07005236 __tsec = selinux_cred(current_cred());
Eric Paris2606fd12010-10-13 16:24:41 -04005237 tsid = __tsec->sid;
5238
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005239 return avc_has_perm(&selinux_state,
5240 tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
5241 NULL);
Eric Paris2606fd12010-10-13 16:24:41 -04005242}
5243
5244static void selinux_secmark_refcount_inc(void)
5245{
5246 atomic_inc(&selinux_secmark_refcount);
5247}
5248
5249static void selinux_secmark_refcount_dec(void)
5250{
5251 atomic_dec(&selinux_secmark_refcount);
5252}
5253
Adrian Bunk9a673e52006-08-15 00:03:53 -07005254static void selinux_req_classify_flow(const struct request_sock *req,
5255 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005256{
David S. Miller1d28f422011-03-12 00:29:39 -05005257 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005258}
5259
Paul Moore5dbbaf22013-01-14 07:12:19 +00005260static int selinux_tun_dev_alloc_security(void **security)
5261{
5262 struct tun_security_struct *tunsec;
5263
5264 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5265 if (!tunsec)
5266 return -ENOMEM;
5267 tunsec->sid = current_sid();
5268
5269 *security = tunsec;
5270 return 0;
5271}
5272
5273static void selinux_tun_dev_free_security(void *security)
5274{
5275 kfree(security);
5276}
5277
Paul Mooreed6d76e2009-08-28 18:12:49 -04005278static int selinux_tun_dev_create(void)
5279{
5280 u32 sid = current_sid();
5281
5282 /* we aren't taking into account the "sockcreate" SID since the socket
5283 * that is being created here is not a socket in the traditional sense,
5284 * instead it is a private sock, accessible only to the kernel, and
5285 * representing a wide range of network traffic spanning multiple
5286 * connections unlike traditional sockets - check the TUN driver to
5287 * get a better understanding of why this socket is special */
5288
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005289 return avc_has_perm(&selinux_state,
5290 sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005291 NULL);
5292}
5293
Paul Moore5dbbaf22013-01-14 07:12:19 +00005294static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005295{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005296 struct tun_security_struct *tunsec = security;
5297
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005298 return avc_has_perm(&selinux_state,
5299 current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005300 TUN_SOCKET__ATTACH_QUEUE, NULL);
5301}
5302
5303static int selinux_tun_dev_attach(struct sock *sk, void *security)
5304{
5305 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005306 struct sk_security_struct *sksec = sk->sk_security;
5307
5308 /* we don't currently perform any NetLabel based labeling here and it
5309 * isn't clear that we would want to do so anyway; while we could apply
5310 * labeling without the support of the TUN user the resulting labeled
5311 * traffic from the other end of the connection would almost certainly
5312 * cause confusion to the TUN user that had no idea network labeling
5313 * protocols were being used */
5314
Paul Moore5dbbaf22013-01-14 07:12:19 +00005315 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005316 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005317
5318 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005319}
5320
Paul Moore5dbbaf22013-01-14 07:12:19 +00005321static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005322{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005323 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005324 u32 sid = current_sid();
5325 int err;
5326
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005327 err = avc_has_perm(&selinux_state,
5328 sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005329 TUN_SOCKET__RELABELFROM, NULL);
5330 if (err)
5331 return err;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005332 err = avc_has_perm(&selinux_state,
5333 sid, sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005334 TUN_SOCKET__RELABELTO, NULL);
5335 if (err)
5336 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005337 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005338
5339 return 0;
5340}
5341
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
5343{
5344 int err = 0;
5345 u32 perm;
5346 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005347 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005348
Hong zhi guo77954982013-03-27 06:49:35 +00005349 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350 err = -EINVAL;
5351 goto out;
5352 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005353 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005354
Paul Moore253bfae2010-04-22 14:46:19 -04005355 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005356 if (err) {
5357 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005358 pr_warn_ratelimited("SELinux: unrecognized netlink"
5359 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5360 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005361 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005362 secclass_map[sksec->sclass - 1].name,
5363 task_pid_nr(current), current->comm);
Paul Mooree5a5ca92018-03-01 17:38:30 -05005364 if (!enforcing_enabled(&selinux_state) ||
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005365 security_get_allow_unknown(&selinux_state))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366 err = 0;
5367 }
5368
5369 /* Ignore */
5370 if (err == -ENOENT)
5371 err = 0;
5372 goto out;
5373 }
5374
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005375 err = sock_has_perm(sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376out:
5377 return err;
5378}
5379
5380#ifdef CONFIG_NETFILTER
5381
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005382static unsigned int selinux_ip_forward(struct sk_buff *skb,
5383 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005384 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385{
Paul Mooredfaebe92008-10-10 10:16:31 -04005386 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005387 char *addrp;
5388 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005389 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005390 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005391 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005392 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005393 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005394
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005395 if (!selinux_policycap_netpeer())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005396 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005397
Paul Mooreeffad8d2008-01-29 08:49:27 -05005398 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005399 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005400 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005401 if (!secmark_active && !peerlbl_active)
5402 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005403
Paul Moored8395c82008-10-10 10:16:30 -04005404 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5405 return NF_DROP;
5406
Eric Paris50c205f2012-04-04 15:01:43 -04005407 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005408 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005409 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005410 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005411 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5412 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
Paul Mooredfaebe92008-10-10 10:16:31 -04005414 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005415 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5416 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005417 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005418 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005419 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005420 }
5421 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005422
5423 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005424 if (avc_has_perm(&selinux_state,
5425 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005426 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5427 return NF_DROP;
5428
Paul Moore948bf852008-10-10 10:16:32 -04005429 if (netlbl_active)
5430 /* we do this in the FORWARD path and not the POST_ROUTING
5431 * path because we want to make sure we apply the necessary
5432 * labeling before IPsec is applied so we can leverage AH
5433 * protection */
5434 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5435 return NF_DROP;
5436
Paul Mooreeffad8d2008-01-29 08:49:27 -05005437 return NF_ACCEPT;
5438}
5439
Eric W. Biederman06198b32015-09-18 14:33:06 -05005440static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005441 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005442 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005443{
David S. Miller238e54c2015-04-03 20:32:56 -04005444 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005445}
5446
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005447#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005448static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005449 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005450 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005451{
David S. Miller238e54c2015-04-03 20:32:56 -04005452 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005453}
5454#endif /* IPV6 */
5455
Paul Moore948bf852008-10-10 10:16:32 -04005456static unsigned int selinux_ip_output(struct sk_buff *skb,
5457 u16 family)
5458{
Paul Moore47180062013-12-04 16:10:45 -05005459 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005460 u32 sid;
5461
5462 if (!netlbl_enabled())
5463 return NF_ACCEPT;
5464
5465 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5466 * because we want to make sure we apply the necessary labeling
5467 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005468 sk = skb->sk;
5469 if (sk) {
5470 struct sk_security_struct *sksec;
5471
Eric Dumazete446f9d2015-10-08 05:01:55 -07005472 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005473 /* if the socket is the listening state then this
5474 * packet is a SYN-ACK packet which means it needs to
5475 * be labeled based on the connection/request_sock and
5476 * not the parent socket. unfortunately, we can't
5477 * lookup the request_sock yet as it isn't queued on
5478 * the parent socket until after the SYN-ACK is sent.
5479 * the "solution" is to simply pass the packet as-is
5480 * as any IP option based labeling should be copied
5481 * from the initial connection request (in the IP
5482 * layer). it is far from ideal, but until we get a
5483 * security label in the packet itself this is the
5484 * best we can do. */
5485 return NF_ACCEPT;
5486
5487 /* standard practice, label using the parent socket */
5488 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005489 sid = sksec->sid;
5490 } else
5491 sid = SECINITSID_KERNEL;
5492 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5493 return NF_DROP;
5494
5495 return NF_ACCEPT;
5496}
5497
Eric W. Biederman06198b32015-09-18 14:33:06 -05005498static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005499 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005500 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005501{
5502 return selinux_ip_output(skb, PF_INET);
5503}
5504
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005505#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005506static unsigned int selinux_ipv6_output(void *priv,
5507 struct sk_buff *skb,
5508 const struct nf_hook_state *state)
5509{
5510 return selinux_ip_output(skb, PF_INET6);
5511}
5512#endif /* IPV6 */
5513
Paul Mooreeffad8d2008-01-29 08:49:27 -05005514static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5515 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005516 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005517{
Eric Dumazet54abc682015-11-08 10:54:07 -08005518 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005519 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005520 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005521 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005522 char *addrp;
5523 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005524
Paul Mooreeffad8d2008-01-29 08:49:27 -05005525 if (sk == NULL)
5526 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005527 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005528
Eric Paris50c205f2012-04-04 15:01:43 -04005529 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005530 ad.u.net = &net;
5531 ad.u.net->netif = ifindex;
5532 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005533 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5534 return NF_DROP;
5535
Paul Moore58bfbb52009-03-27 17:10:41 -04005536 if (selinux_secmark_enabled())
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005537 if (avc_has_perm(&selinux_state,
5538 sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005539 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005540 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005541
Steffen Klassertb9679a72011-02-23 12:55:21 +01005542 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5543 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005544
Paul Mooreeffad8d2008-01-29 08:49:27 -05005545 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546}
5547
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005548static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5549 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005550 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005551{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005552 u32 secmark_perm;
5553 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005554 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005555 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005556 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005557 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005558 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005559 u8 secmark_active;
5560 u8 peerlbl_active;
5561
Paul Mooreeffad8d2008-01-29 08:49:27 -05005562 /* If any sort of compatibility mode is enabled then handoff processing
5563 * to the selinux_ip_postroute_compat() function to deal with the
5564 * special handling. We do this in an attempt to keep this function
5565 * as fast and as clean as possible. */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005566 if (!selinux_policycap_netpeer())
Paul Moored8395c82008-10-10 10:16:30 -04005567 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005568
Paul Mooreeffad8d2008-01-29 08:49:27 -05005569 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005570 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005571 if (!secmark_active && !peerlbl_active)
5572 return NF_ACCEPT;
5573
Eric Dumazet54abc682015-11-08 10:54:07 -08005574 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005575
Paul Mooreeffad8d2008-01-29 08:49:27 -05005576#ifdef CONFIG_XFRM
5577 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5578 * packet transformation so allow the packet to pass without any checks
5579 * since we'll have another chance to perform access control checks
5580 * when the packet is on it's final way out.
5581 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005582 * is NULL, in this case go ahead and apply access control.
5583 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5584 * TCP listening state we cannot wait until the XFRM processing
5585 * is done as we will miss out on the SA label if we do;
5586 * unfortunately, this means more work, but it is only once per
5587 * connection. */
5588 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005589 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005590 return NF_ACCEPT;
5591#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005592
Paul Moored8395c82008-10-10 10:16:30 -04005593 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005594 /* Without an associated socket the packet is either coming
5595 * from the kernel or it is being forwarded; check the packet
5596 * to determine which and if the packet is being forwarded
5597 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005598 if (skb->skb_iif) {
5599 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005600 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005601 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005602 } else {
5603 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005604 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005605 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005606 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005607 /* Locally generated packet but the associated socket is in the
5608 * listening state which means this is a SYN-ACK packet. In
5609 * this particular case the correct security label is assigned
5610 * to the connection/request_sock but unfortunately we can't
5611 * query the request_sock as it isn't queued on the parent
5612 * socket until after the SYN-ACK packet is sent; the only
5613 * viable choice is to regenerate the label like we do in
5614 * selinux_inet_conn_request(). See also selinux_ip_output()
5615 * for similar problems. */
5616 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005617 struct sk_security_struct *sksec;
5618
Eric Dumazete446f9d2015-10-08 05:01:55 -07005619 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005620 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5621 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005622 /* At this point, if the returned skb peerlbl is SECSID_NULL
5623 * and the packet has been through at least one XFRM
5624 * transformation then we must be dealing with the "final"
5625 * form of labeled IPsec packet; since we've already applied
5626 * all of our access controls on this packet we can safely
5627 * pass the packet. */
5628 if (skb_sid == SECSID_NULL) {
5629 switch (family) {
5630 case PF_INET:
5631 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5632 return NF_ACCEPT;
5633 break;
5634 case PF_INET6:
5635 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5636 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005637 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005638 default:
5639 return NF_DROP_ERR(-ECONNREFUSED);
5640 }
5641 }
Paul Moore446b8022013-12-04 16:10:51 -05005642 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5643 return NF_DROP;
5644 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005645 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005646 /* Locally generated packet, fetch the security label from the
5647 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005648 struct sk_security_struct *sksec = sk->sk_security;
5649 peer_sid = sksec->sid;
5650 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005651 }
5652
Eric Paris50c205f2012-04-04 15:01:43 -04005653 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005654 ad.u.net = &net;
5655 ad.u.net->netif = ifindex;
5656 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005657 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005658 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005659
Paul Mooreeffad8d2008-01-29 08:49:27 -05005660 if (secmark_active)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005661 if (avc_has_perm(&selinux_state,
5662 peer_sid, skb->secmark,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005663 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005664 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005665
5666 if (peerlbl_active) {
5667 u32 if_sid;
5668 u32 node_sid;
5669
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005670 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005671 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005672 if (avc_has_perm(&selinux_state,
5673 peer_sid, if_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005674 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005675 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005676
5677 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005678 return NF_DROP;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005679 if (avc_has_perm(&selinux_state,
5680 peer_sid, node_sid,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005681 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005682 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005683 }
5684
5685 return NF_ACCEPT;
5686}
5687
Eric W. Biederman06198b32015-09-18 14:33:06 -05005688static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005689 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005690 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005691{
David S. Miller238e54c2015-04-03 20:32:56 -04005692 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693}
5694
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005695#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005696static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005697 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005698 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005699{
David S. Miller238e54c2015-04-03 20:32:56 -04005700 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005702#endif /* IPV6 */
5703
5704#endif /* CONFIG_NETFILTER */
5705
Linus Torvalds1da177e2005-04-16 15:20:36 -07005706static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5707{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005708 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709}
5710
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005711static int ipc_alloc_security(struct kern_ipc_perm *perm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712 u16 sclass)
5713{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714 struct ipc_security_struct *isec;
5715
James Morris89d155e2005-10-30 14:59:21 -08005716 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717 if (!isec)
5718 return -ENOMEM;
5719
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005721 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005722 perm->security = isec;
5723
5724 return 0;
5725}
5726
5727static void ipc_free_security(struct kern_ipc_perm *perm)
5728{
5729 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730 perm->security = NULL;
5731 kfree(isec);
5732}
5733
5734static int msg_msg_alloc_security(struct msg_msg *msg)
5735{
5736 struct msg_security_struct *msec;
5737
James Morris89d155e2005-10-30 14:59:21 -08005738 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739 if (!msec)
5740 return -ENOMEM;
5741
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742 msec->sid = SECINITSID_UNLABELED;
5743 msg->security = msec;
5744
5745 return 0;
5746}
5747
5748static void msg_msg_free_security(struct msg_msg *msg)
5749{
5750 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751
5752 msg->security = NULL;
5753 kfree(msec);
5754}
5755
5756static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005757 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005758{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005760 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005761 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763 isec = ipc_perms->security;
5764
Eric Paris50c205f2012-04-04 15:01:43 -04005765 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766 ad.u.ipc_id = ipc_perms->key;
5767
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005768 return avc_has_perm(&selinux_state,
5769 sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770}
5771
5772static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5773{
5774 return msg_msg_alloc_security(msg);
5775}
5776
5777static void selinux_msg_msg_free_security(struct msg_msg *msg)
5778{
5779 msg_msg_free_security(msg);
5780}
5781
5782/* message queue security operations */
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005783static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005786 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005787 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788 int rc;
5789
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005790 rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791 if (rc)
5792 return rc;
5793
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005794 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795
Eric Paris50c205f2012-04-04 15:01:43 -04005796 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005797 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005799 rc = avc_has_perm(&selinux_state,
5800 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801 MSGQ__CREATE, &ad);
5802 if (rc) {
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005803 ipc_free_security(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804 return rc;
5805 }
5806 return 0;
5807}
5808
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005809static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810{
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005811 ipc_free_security(msq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812}
5813
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005814static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005817 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005818 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005820 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
Eric Paris50c205f2012-04-04 15:01:43 -04005822 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005823 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005825 return avc_has_perm(&selinux_state,
5826 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827 MSGQ__ASSOCIATE, &ad);
5828}
5829
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005830static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005831{
5832 int err;
5833 int perms;
5834
Eric Paris828dfe12008-04-17 13:17:49 -04005835 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836 case IPC_INFO:
5837 case MSG_INFO:
5838 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005839 return avc_has_perm(&selinux_state,
5840 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005841 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 case IPC_STAT:
5843 case MSG_STAT:
Davidlohr Bueso23c8cec2018-04-10 16:35:30 -07005844 case MSG_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5846 break;
5847 case IPC_SET:
5848 perms = MSGQ__SETATTR;
5849 break;
5850 case IPC_RMID:
5851 perms = MSGQ__DESTROY;
5852 break;
5853 default:
5854 return 0;
5855 }
5856
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005857 err = ipc_has_perm(msq, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858 return err;
5859}
5860
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005861static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863 struct ipc_security_struct *isec;
5864 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005865 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005866 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 int rc;
5868
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005869 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870 msec = msg->security;
5871
5872 /*
5873 * First time through, need to assign label to the message
5874 */
5875 if (msec->sid == SECINITSID_UNLABELED) {
5876 /*
5877 * Compute new sid based on current process and
5878 * message queue this message will be stored in
5879 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05005880 rc = security_transition_sid(&selinux_state, sid, isec->sid,
5881 SECCLASS_MSG, NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882 if (rc)
5883 return rc;
5884 }
5885
Eric Paris50c205f2012-04-04 15:01:43 -04005886 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005887 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
5889 /* Can this process write to the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005890 rc = avc_has_perm(&selinux_state,
5891 sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892 MSGQ__WRITE, &ad);
5893 if (!rc)
5894 /* Can this process send the message */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005895 rc = avc_has_perm(&selinux_state,
5896 sid, msec->sid, SECCLASS_MSG,
David Howells275bb412008-11-14 10:39:19 +11005897 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005898 if (!rc)
5899 /* Can the message be put in the queue? */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005900 rc = avc_has_perm(&selinux_state,
5901 msec->sid, isec->sid, SECCLASS_MSGQ,
David Howells275bb412008-11-14 10:39:19 +11005902 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903
5904 return rc;
5905}
5906
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005907static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908 struct task_struct *target,
5909 long type, int mode)
5910{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911 struct ipc_security_struct *isec;
5912 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005913 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005914 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 int rc;
5916
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005917 isec = msq->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918 msec = msg->security;
5919
Eric Paris50c205f2012-04-04 15:01:43 -04005920 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermand8c6e852018-03-22 21:22:26 -05005921 ad.u.ipc_id = msq->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005923 rc = avc_has_perm(&selinux_state,
5924 sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 SECCLASS_MSGQ, MSGQ__READ, &ad);
5926 if (!rc)
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005927 rc = avc_has_perm(&selinux_state,
5928 sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929 SECCLASS_MSG, MSG__RECEIVE, &ad);
5930 return rc;
5931}
5932
5933/* Shared Memory security operations */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005934static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005937 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005938 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939 int rc;
5940
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005941 rc = ipc_alloc_security(shp, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 if (rc)
5943 return rc;
5944
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005945 isec = shp->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946
Eric Paris50c205f2012-04-04 15:01:43 -04005947 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005948 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005950 rc = avc_has_perm(&selinux_state,
5951 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 SHM__CREATE, &ad);
5953 if (rc) {
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005954 ipc_free_security(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955 return rc;
5956 }
5957 return 0;
5958}
5959
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005960static void selinux_shm_free_security(struct kern_ipc_perm *shp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961{
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005962 ipc_free_security(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963}
5964
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005965static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005968 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005969 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005971 isec = shp->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
Eric Paris50c205f2012-04-04 15:01:43 -04005973 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005974 ad.u.ipc_id = shp->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005976 return avc_has_perm(&selinux_state,
5977 sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978 SHM__ASSOCIATE, &ad);
5979}
5980
5981/* Note, at this point, shp is locked down */
Eric W. Biederman7191adf2018-03-22 21:08:27 -05005982static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983{
5984 int perms;
5985 int err;
5986
Eric Paris828dfe12008-04-17 13:17:49 -04005987 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988 case IPC_INFO:
5989 case SHM_INFO:
5990 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05005991 return avc_has_perm(&selinux_state,
5992 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005993 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994 case IPC_STAT:
5995 case SHM_STAT:
Davidlohr Buesoc21a6972018-04-10 16:35:23 -07005996 case SHM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997 perms = SHM__GETATTR | SHM__ASSOCIATE;
5998 break;
5999 case IPC_SET:
6000 perms = SHM__SETATTR;
6001 break;
6002 case SHM_LOCK:
6003 case SHM_UNLOCK:
6004 perms = SHM__LOCK;
6005 break;
6006 case IPC_RMID:
6007 perms = SHM__DESTROY;
6008 break;
6009 default:
6010 return 0;
6011 }
6012
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006013 err = ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014 return err;
6015}
6016
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006017static int selinux_shm_shmat(struct kern_ipc_perm *shp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 char __user *shmaddr, int shmflg)
6019{
6020 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021
6022 if (shmflg & SHM_RDONLY)
6023 perms = SHM__READ;
6024 else
6025 perms = SHM__READ | SHM__WRITE;
6026
Eric W. Biederman7191adf2018-03-22 21:08:27 -05006027 return ipc_has_perm(shp, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028}
6029
6030/* Semaphore security operations */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006031static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006034 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006035 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036 int rc;
6037
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006038 rc = ipc_alloc_security(sma, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 if (rc)
6040 return rc;
6041
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006042 isec = sma->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043
Eric Paris50c205f2012-04-04 15:01:43 -04006044 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006045 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006047 rc = avc_has_perm(&selinux_state,
6048 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049 SEM__CREATE, &ad);
6050 if (rc) {
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006051 ipc_free_security(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052 return rc;
6053 }
6054 return 0;
6055}
6056
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006057static void selinux_sem_free_security(struct kern_ipc_perm *sma)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058{
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006059 ipc_free_security(sma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060}
6061
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006062static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04006065 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11006066 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006068 isec = sma->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
Eric Paris50c205f2012-04-04 15:01:43 -04006070 ad.type = LSM_AUDIT_DATA_IPC;
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006071 ad.u.ipc_id = sma->key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006073 return avc_has_perm(&selinux_state,
6074 sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075 SEM__ASSOCIATE, &ad);
6076}
6077
6078/* Note, at this point, sma is locked down */
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006079static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006080{
6081 int err;
6082 u32 perms;
6083
Eric Paris828dfe12008-04-17 13:17:49 -04006084 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085 case IPC_INFO:
6086 case SEM_INFO:
6087 /* No specific object, just general system-wide information. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006088 return avc_has_perm(&selinux_state,
6089 current_sid(), SECINITSID_KERNEL,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006090 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091 case GETPID:
6092 case GETNCNT:
6093 case GETZCNT:
6094 perms = SEM__GETATTR;
6095 break;
6096 case GETVAL:
6097 case GETALL:
6098 perms = SEM__READ;
6099 break;
6100 case SETVAL:
6101 case SETALL:
6102 perms = SEM__WRITE;
6103 break;
6104 case IPC_RMID:
6105 perms = SEM__DESTROY;
6106 break;
6107 case IPC_SET:
6108 perms = SEM__SETATTR;
6109 break;
6110 case IPC_STAT:
6111 case SEM_STAT:
Davidlohr Buesoa280d6d2018-04-10 16:35:26 -07006112 case SEM_STAT_ANY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113 perms = SEM__GETATTR | SEM__ASSOCIATE;
6114 break;
6115 default:
6116 return 0;
6117 }
6118
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006119 err = ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120 return err;
6121}
6122
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006123static int selinux_sem_semop(struct kern_ipc_perm *sma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124 struct sembuf *sops, unsigned nsops, int alter)
6125{
6126 u32 perms;
6127
6128 if (alter)
6129 perms = SEM__READ | SEM__WRITE;
6130 else
6131 perms = SEM__READ;
6132
Eric W. Biedermanaefad952018-03-22 20:52:43 -05006133 return ipc_has_perm(sma, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134}
6135
6136static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
6137{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138 u32 av = 0;
6139
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 av = 0;
6141 if (flag & S_IRUGO)
6142 av |= IPC__UNIX_READ;
6143 if (flag & S_IWUGO)
6144 av |= IPC__UNIX_WRITE;
6145
6146 if (av == 0)
6147 return 0;
6148
Stephen Smalley6af963f2005-05-01 08:58:39 -07006149 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150}
6151
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02006152static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
6153{
6154 struct ipc_security_struct *isec = ipcp->security;
6155 *secid = isec->sid;
6156}
6157
Eric Paris828dfe12008-04-17 13:17:49 -04006158static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159{
6160 if (inode)
6161 inode_doinit_with_dentry(inode, dentry);
6162}
6163
6164static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00006165 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166{
David Howells275bb412008-11-14 10:39:19 +11006167 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00006168 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169 int error;
Al Viro04ff9702007-03-12 16:17:58 +00006170 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171
David Howells275bb412008-11-14 10:39:19 +11006172 rcu_read_lock();
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006173 __tsec = selinux_cred(__task_cred(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006175 if (current != p) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006176 error = avc_has_perm(&selinux_state,
6177 current_sid(), __tsec->sid,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006178 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
6179 if (error)
6180 goto bad;
6181 }
6182
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11006184 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006185 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11006186 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11006188 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11006190 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006191 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11006192 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07006193 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11006194 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006195 else {
6196 error = -EINVAL;
6197 goto bad;
6198 }
David Howells275bb412008-11-14 10:39:19 +11006199 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
6201 if (!sid)
6202 return 0;
6203
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006204 error = security_sid_to_context(&selinux_state, sid, value, &len);
Al Viro04ff9702007-03-12 16:17:58 +00006205 if (error)
6206 return error;
6207 return len;
David Howells275bb412008-11-14 10:39:19 +11006208
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006209bad:
David Howells275bb412008-11-14 10:39:19 +11006210 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006211 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212}
6213
Stephen Smalleyb21507e2017-01-09 10:07:31 -05006214static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215{
6216 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11006217 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006218 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219 int error;
6220 char *str = value;
6221
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222 /*
6223 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224 */
6225 if (!strcmp(name, "exec"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006226 error = avc_has_perm(&selinux_state,
6227 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006228 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229 else if (!strcmp(name, "fscreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006230 error = avc_has_perm(&selinux_state,
6231 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006232 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006233 else if (!strcmp(name, "keycreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006234 error = avc_has_perm(&selinux_state,
6235 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006236 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07006237 else if (!strcmp(name, "sockcreate"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006238 error = avc_has_perm(&selinux_state,
6239 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006240 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006241 else if (!strcmp(name, "current"))
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006242 error = avc_has_perm(&selinux_state,
6243 mysid, mysid, SECCLASS_PROCESS,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006244 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245 else
6246 error = -EINVAL;
6247 if (error)
6248 return error;
6249
6250 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05006251 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252 if (str[size-1] == '\n') {
6253 str[size-1] = 0;
6254 size--;
6255 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006256 error = security_context_to_sid(&selinux_state, value, size,
6257 &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006258 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04006259 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04006260 struct audit_buffer *ab;
6261 size_t audit_size;
6262
6263 /* We strip a nul only if it is at the end, otherwise the
6264 * context contains a nul and we should audit that */
6265 if (str[size - 1] == '\0')
6266 audit_size = size - 1;
6267 else
6268 audit_size = size;
Richard Guy Briggscdfb6b32018-05-12 21:58:20 -04006269 ab = audit_log_start(audit_context(),
6270 GFP_ATOMIC,
6271 AUDIT_SELINUX_ERR);
Eric Parisd6ea83e2012-04-04 13:45:49 -04006272 audit_log_format(ab, "op=fscreate invalid_context=");
6273 audit_log_n_untrustedstring(ab, value, audit_size);
6274 audit_log_end(ab);
6275
Stephen Smalley12b29f32008-05-07 13:03:20 -04006276 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006277 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006278 error = security_context_to_sid_force(
6279 &selinux_state,
6280 value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04006281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282 if (error)
6283 return error;
6284 }
6285
David Howellsd84f4f92008-11-14 10:39:23 +11006286 new = prepare_creds();
6287 if (!new)
6288 return -ENOMEM;
6289
Linus Torvalds1da177e2005-04-16 15:20:36 -07006290 /* Permission checking based on the specified context is
6291 performed during the actual operation (execve,
6292 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11006293 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294 checks and may_create for the file creation checks. The
6295 operation will then fail if the context is not permitted. */
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006296 tsec = selinux_cred(new);
David Howellsd84f4f92008-11-14 10:39:23 +11006297 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006299 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006300 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006301 } else if (!strcmp(name, "keycreate")) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006302 error = avc_has_perm(&selinux_state,
6303 mysid, sid, SECCLASS_KEY, KEY__CREATE,
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006304 NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006305 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006306 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006307 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006308 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006309 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006310 } else if (!strcmp(name, "current")) {
6311 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006312 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006313 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006314
David Howellsd84f4f92008-11-14 10:39:23 +11006315 /* Only allow single threaded processes to change context */
6316 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006317 if (!current_is_single_threaded()) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006318 error = security_bounded_transition(&selinux_state,
6319 tsec->sid, sid);
David Howellsd84f4f92008-11-14 10:39:23 +11006320 if (error)
6321 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006323
6324 /* Check permissions for the transition. */
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006325 error = avc_has_perm(&selinux_state,
6326 tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006327 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006329 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006330
6331 /* Check for ptracing, and update the task SID if ok.
6332 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006333 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006334 if (ptsid != 0) {
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006335 error = avc_has_perm(&selinux_state,
6336 ptsid, sid, SECCLASS_PROCESS,
David Howellsd84f4f92008-11-14 10:39:23 +11006337 PROCESS__PTRACE, NULL);
6338 if (error)
6339 goto abort_change;
6340 }
6341
6342 tsec->sid = sid;
6343 } else {
6344 error = -EINVAL;
6345 goto abort_change;
6346 }
6347
6348 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006350
6351abort_change:
6352 abort_creds(new);
6353 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354}
6355
David Quigley746df9b2013-05-22 12:50:35 -04006356static int selinux_ismaclabel(const char *name)
6357{
6358 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6359}
6360
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006361static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6362{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006363 return security_sid_to_context(&selinux_state, secid,
6364 secdata, seclen);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006365}
6366
David Howells7bf570d2008-04-29 20:52:51 +01006367static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006368{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006369 return security_context_to_sid(&selinux_state, secdata, seclen,
6370 secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006371}
6372
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006373static void selinux_release_secctx(char *secdata, u32 seclen)
6374{
Paul Moore088999e2007-08-01 11:12:58 -04006375 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006376}
6377
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006378static void selinux_inode_invalidate_secctx(struct inode *inode)
6379{
6380 struct inode_security_struct *isec = inode->i_security;
6381
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006382 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006383 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006384 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006385}
6386
David P. Quigley1ee65e32009-09-03 14:25:57 -04006387/*
6388 * called with inode->i_mutex locked
6389 */
6390static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6391{
6392 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6393}
6394
6395/*
6396 * called with inode->i_mutex locked
6397 */
6398static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6399{
6400 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6401}
6402
6403static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6404{
6405 int len = 0;
6406 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6407 ctx, true);
6408 if (len < 0)
6409 return len;
6410 *ctxlen = len;
6411 return 0;
6412}
Michael LeMayd7200242006-06-22 14:47:17 -07006413#ifdef CONFIG_KEYS
6414
David Howellsd84f4f92008-11-14 10:39:23 +11006415static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006416 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006417{
David Howellsd84f4f92008-11-14 10:39:23 +11006418 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006419 struct key_security_struct *ksec;
6420
6421 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6422 if (!ksec)
6423 return -ENOMEM;
6424
Casey Schaufler0c6cfa62018-09-21 17:17:16 -07006425 tsec = selinux_cred(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11006426 if (tsec->keycreate_sid)
6427 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006428 else
David Howellsd84f4f92008-11-14 10:39:23 +11006429 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006430
David Howells275bb412008-11-14 10:39:19 +11006431 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006432 return 0;
6433}
6434
6435static void selinux_key_free(struct key *k)
6436{
6437 struct key_security_struct *ksec = k->security;
6438
6439 k->security = NULL;
6440 kfree(ksec);
6441}
6442
6443static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006444 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006445 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006446{
6447 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006448 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006449 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006450
6451 /* if no specific permissions are requested, we skip the
6452 permission check. No serious, additional covert channels
6453 appear to be created. */
6454 if (perm == 0)
6455 return 0;
6456
David Howellsd84f4f92008-11-14 10:39:23 +11006457 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006458
6459 key = key_ref_to_ptr(key_ref);
6460 ksec = key->security;
6461
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006462 return avc_has_perm(&selinux_state,
6463 sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006464}
6465
David Howells70a5bb72008-04-29 01:01:26 -07006466static int selinux_key_getsecurity(struct key *key, char **_buffer)
6467{
6468 struct key_security_struct *ksec = key->security;
6469 char *context = NULL;
6470 unsigned len;
6471 int rc;
6472
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006473 rc = security_sid_to_context(&selinux_state, ksec->sid,
6474 &context, &len);
David Howells70a5bb72008-04-29 01:01:26 -07006475 if (!rc)
6476 rc = len;
6477 *_buffer = context;
6478 return rc;
6479}
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006480#endif
David Howells70a5bb72008-04-29 01:01:26 -07006481
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006482#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006483static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6484{
6485 struct common_audit_data ad;
6486 int err;
6487 u32 sid = 0;
6488 struct ib_security_struct *sec = ib_sec;
6489 struct lsm_ibpkey_audit ibpkey;
6490
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006491 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006492 if (err)
6493 return err;
6494
6495 ad.type = LSM_AUDIT_DATA_IBPKEY;
6496 ibpkey.subnet_prefix = subnet_prefix;
6497 ibpkey.pkey = pkey_val;
6498 ad.u.ibpkey = &ibpkey;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006499 return avc_has_perm(&selinux_state,
6500 sec->sid, sid,
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006501 SECCLASS_INFINIBAND_PKEY,
6502 INFINIBAND_PKEY__ACCESS, &ad);
6503}
6504
Daniel Jurgensab861df2017-05-19 15:48:58 +03006505static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6506 u8 port_num)
6507{
6508 struct common_audit_data ad;
6509 int err;
6510 u32 sid = 0;
6511 struct ib_security_struct *sec = ib_sec;
6512 struct lsm_ibendport_audit ibendport;
6513
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006514 err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
6515 &sid);
Daniel Jurgensab861df2017-05-19 15:48:58 +03006516
6517 if (err)
6518 return err;
6519
6520 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6521 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6522 ibendport.port = port_num;
6523 ad.u.ibendport = &ibendport;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006524 return avc_has_perm(&selinux_state,
6525 sec->sid, sid,
Daniel Jurgensab861df2017-05-19 15:48:58 +03006526 SECCLASS_INFINIBAND_ENDPORT,
6527 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6528}
6529
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006530static int selinux_ib_alloc_security(void **ib_sec)
6531{
6532 struct ib_security_struct *sec;
6533
6534 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6535 if (!sec)
6536 return -ENOMEM;
6537 sec->sid = current_sid();
6538
6539 *ib_sec = sec;
6540 return 0;
6541}
6542
6543static void selinux_ib_free_security(void *ib_sec)
6544{
6545 kfree(ib_sec);
6546}
Michael LeMayd7200242006-06-22 14:47:17 -07006547#endif
6548
Chenbo Fengec27c352017-10-18 13:00:25 -07006549#ifdef CONFIG_BPF_SYSCALL
6550static int selinux_bpf(int cmd, union bpf_attr *attr,
6551 unsigned int size)
6552{
6553 u32 sid = current_sid();
6554 int ret;
6555
6556 switch (cmd) {
6557 case BPF_MAP_CREATE:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006558 ret = avc_has_perm(&selinux_state,
6559 sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
Chenbo Fengec27c352017-10-18 13:00:25 -07006560 NULL);
6561 break;
6562 case BPF_PROG_LOAD:
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006563 ret = avc_has_perm(&selinux_state,
6564 sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
Chenbo Fengec27c352017-10-18 13:00:25 -07006565 NULL);
6566 break;
6567 default:
6568 ret = 0;
6569 break;
6570 }
6571
6572 return ret;
6573}
6574
6575static u32 bpf_map_fmode_to_av(fmode_t fmode)
6576{
6577 u32 av = 0;
6578
6579 if (fmode & FMODE_READ)
6580 av |= BPF__MAP_READ;
6581 if (fmode & FMODE_WRITE)
6582 av |= BPF__MAP_WRITE;
6583 return av;
6584}
6585
Chenbo Fengf66e4482017-10-18 13:00:26 -07006586/* This function will check the file pass through unix socket or binder to see
6587 * if it is a bpf related object. And apply correspinding checks on the bpf
6588 * object based on the type. The bpf maps and programs, not like other files and
6589 * socket, are using a shared anonymous inode inside the kernel as their inode.
6590 * So checking that inode cannot identify if the process have privilege to
6591 * access the bpf object and that's why we have to add this additional check in
6592 * selinux_file_receive and selinux_binder_transfer_files.
6593 */
6594static int bpf_fd_pass(struct file *file, u32 sid)
6595{
6596 struct bpf_security_struct *bpfsec;
6597 struct bpf_prog *prog;
6598 struct bpf_map *map;
6599 int ret;
6600
6601 if (file->f_op == &bpf_map_fops) {
6602 map = file->private_data;
6603 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006604 ret = avc_has_perm(&selinux_state,
6605 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006606 bpf_map_fmode_to_av(file->f_mode), NULL);
6607 if (ret)
6608 return ret;
6609 } else if (file->f_op == &bpf_prog_fops) {
6610 prog = file->private_data;
6611 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006612 ret = avc_has_perm(&selinux_state,
6613 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengf66e4482017-10-18 13:00:26 -07006614 BPF__PROG_RUN, NULL);
6615 if (ret)
6616 return ret;
6617 }
6618 return 0;
6619}
6620
Chenbo Fengec27c352017-10-18 13:00:25 -07006621static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6622{
6623 u32 sid = current_sid();
6624 struct bpf_security_struct *bpfsec;
6625
6626 bpfsec = map->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006627 return avc_has_perm(&selinux_state,
6628 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006629 bpf_map_fmode_to_av(fmode), NULL);
6630}
6631
6632static int selinux_bpf_prog(struct bpf_prog *prog)
6633{
6634 u32 sid = current_sid();
6635 struct bpf_security_struct *bpfsec;
6636
6637 bpfsec = prog->aux->security;
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006638 return avc_has_perm(&selinux_state,
6639 sid, bpfsec->sid, SECCLASS_BPF,
Chenbo Fengec27c352017-10-18 13:00:25 -07006640 BPF__PROG_RUN, NULL);
6641}
6642
6643static int selinux_bpf_map_alloc(struct bpf_map *map)
6644{
6645 struct bpf_security_struct *bpfsec;
6646
6647 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6648 if (!bpfsec)
6649 return -ENOMEM;
6650
6651 bpfsec->sid = current_sid();
6652 map->security = bpfsec;
6653
6654 return 0;
6655}
6656
6657static void selinux_bpf_map_free(struct bpf_map *map)
6658{
6659 struct bpf_security_struct *bpfsec = map->security;
6660
6661 map->security = NULL;
6662 kfree(bpfsec);
6663}
6664
6665static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6666{
6667 struct bpf_security_struct *bpfsec;
6668
6669 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6670 if (!bpfsec)
6671 return -ENOMEM;
6672
6673 bpfsec->sid = current_sid();
6674 aux->security = bpfsec;
6675
6676 return 0;
6677}
6678
6679static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6680{
6681 struct bpf_security_struct *bpfsec = aux->security;
6682
6683 aux->security = NULL;
6684 kfree(bpfsec);
6685}
6686#endif
6687
James Morrisca97d932017-02-15 00:18:51 +11006688static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006689 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6690 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6691 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6692 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006693
Casey Schauflere20b0432015-05-02 15:11:36 -07006694 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6695 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6696 LSM_HOOK_INIT(capget, selinux_capget),
6697 LSM_HOOK_INIT(capset, selinux_capset),
6698 LSM_HOOK_INIT(capable, selinux_capable),
6699 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6700 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6701 LSM_HOOK_INIT(syslog, selinux_syslog),
6702 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006703
Casey Schauflere20b0432015-05-02 15:11:36 -07006704 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006705
Casey Schauflere20b0432015-05-02 15:11:36 -07006706 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6707 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6708 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709
Casey Schauflere20b0432015-05-02 15:11:36 -07006710 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6711 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
Al Viro5b400232018-12-12 20:13:29 -05006712 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
Al Viro204cc0c2018-12-13 13:41:47 -05006713 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
Casey Schauflere20b0432015-05-02 15:11:36 -07006714 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6715 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6716 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6717 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6718 LSM_HOOK_INIT(sb_mount, selinux_mount),
6719 LSM_HOOK_INIT(sb_umount, selinux_umount),
6720 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6721 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
Al Viro757cbe52018-12-14 23:42:21 -05006722 LSM_HOOK_INIT(sb_add_mnt_opt, selinux_add_mnt_opt),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006723
Casey Schauflere20b0432015-05-02 15:11:36 -07006724 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006725 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006726
Casey Schauflere20b0432015-05-02 15:11:36 -07006727 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6728 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6729 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6730 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6731 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6732 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6733 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6734 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6735 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6736 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6737 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6738 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6739 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6740 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6741 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6742 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6743 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6744 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6745 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6746 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6747 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6748 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6749 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6750 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6751 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006752 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006753 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754
Casey Schauflere20b0432015-05-02 15:11:36 -07006755 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6756 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6757 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6758 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6759 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6760 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6761 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6762 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6763 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6764 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6765 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6766 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006767
Casey Schauflere20b0432015-05-02 15:11:36 -07006768 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006769
Tetsuo Handaa79be232017-03-28 23:08:45 +09006770 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07006771 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6772 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6773 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6774 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
Matthew Garrett3ec30112018-01-08 13:36:19 -08006775 LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
Casey Schauflere20b0432015-05-02 15:11:36 -07006776 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6777 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6778 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Mimi Zoharc77b8cd2018-07-13 14:06:02 -04006779 LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006780 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006781 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6782 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6783 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6784 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6785 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6786 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6787 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05006788 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07006789 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6790 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6791 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6792 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6793 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07006794 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006795
Casey Schauflere20b0432015-05-02 15:11:36 -07006796 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6797 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006798
Casey Schauflere20b0432015-05-02 15:11:36 -07006799 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6800 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006801
Casey Schauflere20b0432015-05-02 15:11:36 -07006802 LSM_HOOK_INIT(msg_queue_alloc_security,
6803 selinux_msg_queue_alloc_security),
6804 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6805 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6806 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6807 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6808 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809
Casey Schauflere20b0432015-05-02 15:11:36 -07006810 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6811 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6812 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6813 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6814 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815
Casey Schauflere20b0432015-05-02 15:11:36 -07006816 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6817 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6818 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6819 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6820 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006821
Casey Schauflere20b0432015-05-02 15:11:36 -07006822 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006823
Casey Schauflere20b0432015-05-02 15:11:36 -07006824 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6825 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826
Casey Schauflere20b0432015-05-02 15:11:36 -07006827 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6828 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6829 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6830 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006831 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006832 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6833 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6834 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835
Casey Schauflere20b0432015-05-02 15:11:36 -07006836 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6837 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006838
Casey Schauflere20b0432015-05-02 15:11:36 -07006839 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6840 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
David Herrmann0b811db2018-05-04 16:28:21 +02006841 LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
Casey Schauflere20b0432015-05-02 15:11:36 -07006842 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6843 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6844 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6845 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6846 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6847 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6848 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6849 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6850 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6851 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6852 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6853 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6854 LSM_HOOK_INIT(socket_getpeersec_stream,
6855 selinux_socket_getpeersec_stream),
6856 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6857 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6858 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6859 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6860 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6861 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
Richard Hainesd4529302018-02-13 20:57:18 +00006862 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
6863 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
6864 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
Casey Schauflere20b0432015-05-02 15:11:36 -07006865 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6866 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6867 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6868 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6869 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6870 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6871 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6872 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6873 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6874 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6875 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6876 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6877 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006878#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006879 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03006880 LSM_HOOK_INIT(ib_endport_manage_subnet,
6881 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006882 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6883 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6884#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006885#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006886 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6887 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6888 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6889 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6890 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6891 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6892 selinux_xfrm_state_alloc_acquire),
6893 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6894 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6895 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6896 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6897 selinux_xfrm_state_pol_flow_match),
6898 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006899#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006900
6901#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006902 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6903 LSM_HOOK_INIT(key_free, selinux_key_free),
6904 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6905 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006906#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006907
6908#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006909 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6910 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6911 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6912 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006913#endif
Chenbo Fengec27c352017-10-18 13:00:25 -07006914
6915#ifdef CONFIG_BPF_SYSCALL
6916 LSM_HOOK_INIT(bpf, selinux_bpf),
6917 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
6918 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
6919 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
6920 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
6921 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
6922 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
6923#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924};
6925
6926static __init int selinux_init(void)
6927{
peter enderborgc103a912018-06-12 10:09:03 +02006928 pr_info("SELinux: Initializing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006929
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006930 memset(&selinux_state, 0, sizeof(selinux_state));
Paul Mooree5a5ca92018-03-01 17:38:30 -05006931 enforcing_set(&selinux_state, selinux_enforcing_boot);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006932 selinux_state.checkreqprot = selinux_checkreqprot_boot;
6933 selinux_ss_init(&selinux_state.ss);
Stephen Smalley6b6bc622018-03-05 11:47:56 -05006934 selinux_avc_init(&selinux_state.avc);
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006935
Linus Torvalds1da177e2005-04-16 15:20:36 -07006936 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006937 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006938
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006939 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6940
James Morris7cae7e22006-03-22 00:09:22 -08006941 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6942 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006943 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006944 file_security_cache = kmem_cache_create("selinux_file_security",
6945 sizeof(struct file_security_struct),
6946 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006947 avc_init();
6948
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006949 avtab_cache_init();
6950
6951 ebitmap_cache_init();
6952
6953 hashtab_cache_init();
6954
Casey Schauflerd69dece52017-01-18 17:09:05 -08006955 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006956
Paul Moore615e51f2014-06-26 14:33:56 -04006957 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6958 panic("SELinux: Unable to register AVC netcache callback\n");
6959
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03006960 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6961 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6962
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05006963 if (selinux_enforcing_boot)
peter enderborgc103a912018-06-12 10:09:03 +02006964 pr_debug("SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006965 else
peter enderborgc103a912018-06-12 10:09:03 +02006966 pr_debug("SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006967
Linus Torvalds1da177e2005-04-16 15:20:36 -07006968 return 0;
6969}
6970
Al Viroe8c26252010-03-23 06:36:54 -04006971static void delayed_superblock_init(struct super_block *sb, void *unused)
6972{
Al Viro204cc0c2018-12-13 13:41:47 -05006973 selinux_set_mnt_opts(sb, NULL, 0, NULL);
Al Viroe8c26252010-03-23 06:36:54 -04006974}
6975
Linus Torvalds1da177e2005-04-16 15:20:36 -07006976void selinux_complete_init(void)
6977{
peter enderborgc103a912018-06-12 10:09:03 +02006978 pr_debug("SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979
6980 /* Set up any superblocks initialized prior to the policy load. */
peter enderborgc103a912018-06-12 10:09:03 +02006981 pr_debug("SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006982 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006983}
6984
6985/* SELinux requires early initialization in order to label
6986 all processes and objects when they are created. */
Kees Cook3d6e5f62018-10-10 17:18:23 -07006987DEFINE_LSM(selinux) = {
Kees Cook07aed2f2018-10-10 17:18:24 -07006988 .name = "selinux",
Kees Cook14bd99c2018-09-19 19:57:06 -07006989 .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
Kees Cookc5459b82018-09-13 22:28:48 -07006990 .enabled = &selinux_enabled,
Kees Cook3d6e5f62018-10-10 17:18:23 -07006991 .init = selinux_init,
6992};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006994#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006995
Florian Westphal591bb272017-07-26 11:40:52 +02006996static const struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006997 {
6998 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006999 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007000 .hooknum = NF_INET_POST_ROUTING,
7001 .priority = NF_IP_PRI_SELINUX_LAST,
7002 },
7003 {
7004 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007005 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007006 .hooknum = NF_INET_FORWARD,
7007 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04007008 },
7009 {
7010 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00007011 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04007012 .hooknum = NF_INET_LOCAL_OUT,
7013 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007014 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04007015#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05007016 {
7017 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00007018 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007019 .hooknum = NF_INET_POST_ROUTING,
7020 .priority = NF_IP6_PRI_SELINUX_LAST,
7021 },
7022 {
7023 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00007024 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05007025 .hooknum = NF_INET_FORWARD,
7026 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02007027 },
Huw Davies2917f572016-06-27 15:06:15 -04007028 {
7029 .hook = selinux_ipv6_output,
7030 .pf = NFPROTO_IPV6,
7031 .hooknum = NF_INET_LOCAL_OUT,
7032 .priority = NF_IP6_PRI_SELINUX_FIRST,
7033 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02007035};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007036
Florian Westphal8e71bf72017-04-21 11:49:09 +02007037static int __net_init selinux_nf_register(struct net *net)
7038{
7039 return nf_register_net_hooks(net, selinux_nf_ops,
7040 ARRAY_SIZE(selinux_nf_ops));
7041}
7042
7043static void __net_exit selinux_nf_unregister(struct net *net)
7044{
7045 nf_unregister_net_hooks(net, selinux_nf_ops,
7046 ARRAY_SIZE(selinux_nf_ops));
7047}
7048
7049static struct pernet_operations selinux_net_ops = {
7050 .init = selinux_nf_register,
7051 .exit = selinux_nf_unregister,
7052};
7053
Linus Torvalds1da177e2005-04-16 15:20:36 -07007054static int __init selinux_nf_ip_init(void)
7055{
Jiri Pirko25db6be2014-09-03 17:42:13 +02007056 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057
7058 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02007059 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05007060
peter enderborgc103a912018-06-12 10:09:03 +02007061 pr_debug("SELinux: Registering netfilter hooks\n");
Eric Parisfadcdb42007-02-22 18:11:31 -05007062
Florian Westphal8e71bf72017-04-21 11:49:09 +02007063 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07007064 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02007065 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007066
Jiri Pirko25db6be2014-09-03 17:42:13 +02007067 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007069__initcall(selinux_nf_ip_init);
7070
7071#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7072static void selinux_nf_ip_exit(void)
7073{
peter enderborgc103a912018-06-12 10:09:03 +02007074 pr_debug("SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Florian Westphal8e71bf72017-04-21 11:49:09 +02007076 unregister_pernet_subsys(&selinux_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007077}
7078#endif
7079
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007080#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007081
7082#ifdef CONFIG_SECURITY_SELINUX_DISABLE
7083#define selinux_nf_ip_exit()
7084#endif
7085
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08007086#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007087
7088#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007089int selinux_disable(struct selinux_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007090{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007091 if (state->initialized) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007092 /* Not permitted after initial policy load. */
7093 return -EINVAL;
7094 }
7095
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007096 if (state->disabled) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007097 /* Only do this once. */
7098 return -EINVAL;
7099 }
7100
Stephen Smalleyaa8e7122018-03-01 18:48:02 -05007101 state->disabled = 1;
7102
peter enderborgc103a912018-06-12 10:09:03 +02007103 pr_info("SELinux: Disabled at runtime.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Stephen Smalley30d55282006-05-03 10:52:36 -04007105 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07007107 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Eric Parisaf8ff042009-09-20 21:23:01 -04007109 /* Try to destroy the avc node cache */
7110 avc_disable();
7111
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112 /* Unregister netfilter hooks. */
7113 selinux_nf_ip_exit();
7114
7115 /* Unregister selinuxfs. */
7116 exit_sel_fs();
7117
7118 return 0;
7119}
7120#endif