blob: 04b8e1082c9a959039a84f10a29b2901f368ca65 [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 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#include <linux/quota.h>
71#include <linux/un.h> /* for Unix socket types */
72#include <net/af_unix.h> /* for Unix socket types */
73#include <linux/parser.h>
74#include <linux/nfs_mount.h>
75#include <net/ipv6.h>
76#include <linux/hugetlb.h>
77#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070078#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070079#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070080#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070081#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070082#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080083#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070084#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040085#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000086#include <linux/msg.h>
87#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89#include "avc.h"
90#include "objsec.h"
91#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050092#include "netnode.h"
Paul Moore3e1121722008-04-10 10:48:14 -040093#include "netport.h"
Daniel Jurgens409dcf32017-05-19 15:48:59 +030094#include "ibpkey.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080095#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050096#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020097#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100098#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Paul Moored621d352008-01-29 08:43:36 -0500100/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000101static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500102
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400104int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106static int __init enforcing_setup(char *str)
107{
Eric Parisf5269712008-05-14 11:27:45 -0400108 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900109 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400110 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 return 1;
112}
113__setup("enforcing=", enforcing_setup);
114#endif
115
116#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
117int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
118
119static int __init selinux_enabled_setup(char *str)
120{
Eric Parisf5269712008-05-14 11:27:45 -0400121 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900122 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400123 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 return 1;
125}
126__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400127#else
128int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129#endif
130
Christoph Lametere18b8902006-12-06 20:33:20 -0800131static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400132static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800133
Paul Moored621d352008-01-29 08:43:36 -0500134/**
135 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
136 *
137 * Description:
138 * This function checks the SECMARK reference counter to see if any SECMARK
139 * targets are currently configured, if the reference counter is greater than
140 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400141 * enabled, false (0) if SECMARK is disabled. If the always_check_network
142 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500143 *
144 */
145static int selinux_secmark_enabled(void)
146{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400147 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
148}
149
150/**
151 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
152 *
153 * Description:
154 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
155 * (1) if any are enabled or false (0) if neither are enabled. If the
156 * always_check_network policy capability is enabled, peer labeling
157 * is always considered enabled.
158 *
159 */
160static int selinux_peerlbl_enabled(void)
161{
162 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500163}
164
Paul Moore615e51f2014-06-26 14:33:56 -0400165static int selinux_netcache_avc_callback(u32 event)
166{
167 if (event == AVC_CALLBACK_RESET) {
168 sel_netif_flush();
169 sel_netnode_flush();
170 sel_netport_flush();
171 synchronize_net();
172 }
173 return 0;
174}
175
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300176static int selinux_lsm_notifier_avc_callback(u32 event)
177{
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300178 if (event == AVC_CALLBACK_RESET) {
179 sel_ib_pkey_flush();
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300180 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
Daniel Jurgens409dcf32017-05-19 15:48:59 +0300181 }
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300182
183 return 0;
184}
185
David Howellsd84f4f92008-11-14 10:39:23 +1100186/*
187 * initialise the security for the init task
188 */
189static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190{
David Howells3b11a1d2008-11-14 10:39:26 +1100191 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 struct task_security_struct *tsec;
193
James Morris89d155e2005-10-30 14:59:21 -0800194 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100196 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
David Howellsd84f4f92008-11-14 10:39:23 +1100198 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100199 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200}
201
David Howells275bb412008-11-14 10:39:19 +1100202/*
David Howells88e67f32008-11-14 10:39:21 +1100203 * get the security ID of a set of credentials
204 */
205static inline u32 cred_sid(const struct cred *cred)
206{
207 const struct task_security_struct *tsec;
208
209 tsec = cred->security;
210 return tsec->sid;
211}
212
213/*
David Howells3b11a1d2008-11-14 10:39:26 +1100214 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100215 */
216static inline u32 task_sid(const struct task_struct *task)
217{
David Howells275bb412008-11-14 10:39:19 +1100218 u32 sid;
219
220 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100221 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100222 rcu_read_unlock();
223 return sid;
224}
225
David Howells88e67f32008-11-14 10:39:21 +1100226/* Allocate and free functions for each kind of security blob. */
227
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228static int inode_alloc_security(struct inode *inode)
229{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100231 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Josef Bacika02fe132008-04-04 09:35:05 +1100233 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 if (!isec)
235 return -ENOMEM;
236
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +0100237 spin_lock_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 isec->inode = inode;
240 isec->sid = SECINITSID_UNLABELED;
241 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100242 isec->task_sid = sid;
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100243 isec->initialized = LABEL_INVALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 inode->i_security = isec;
245
246 return 0;
247}
248
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500249static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
250
251/*
252 * Try reloading inode security labels that have been marked as invalid. The
253 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100254 * allowed; when set to false, returns -ECHILD when the label is
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500255 * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
256 * when no dentry is available, set it to NULL instead.
257 */
258static int __inode_security_revalidate(struct inode *inode,
259 struct dentry *opt_dentry,
260 bool may_sleep)
261{
262 struct inode_security_struct *isec = inode->i_security;
263
264 might_sleep_if(may_sleep);
265
Paul Moore1ac424762016-04-18 16:41:38 -0400266 if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500267 if (!may_sleep)
268 return -ECHILD;
269
270 /*
271 * Try reloading the inode security label. This will fail if
272 * @opt_dentry is NULL and no dentry for this inode can be
273 * found; in that case, continue using the old label.
274 */
275 inode_doinit_with_dentry(inode, opt_dentry);
276 }
277 return 0;
278}
279
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500280static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
281{
282 return inode->i_security;
283}
284
285static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
286{
287 int error;
288
289 error = __inode_security_revalidate(inode, NULL, !rcu);
290 if (error)
291 return ERR_PTR(error);
292 return inode->i_security;
293}
294
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500295/*
296 * Get the security label of an inode.
297 */
298static struct inode_security_struct *inode_security(struct inode *inode)
299{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500300 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500301 return inode->i_security;
302}
303
Paul Moore2c971652016-04-19 16:36:28 -0400304static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
305{
306 struct inode *inode = d_backing_inode(dentry);
307
308 return inode->i_security;
309}
310
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500311/*
312 * Get the security label of a dentry's backing inode.
313 */
314static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
315{
316 struct inode *inode = d_backing_inode(dentry);
317
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500318 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500319 return inode->i_security;
320}
321
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500322static void inode_free_rcu(struct rcu_head *head)
323{
324 struct inode_security_struct *isec;
325
326 isec = container_of(head, struct inode_security_struct, rcu);
327 kmem_cache_free(sel_inode_cache, isec);
328}
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330static void inode_free_security(struct inode *inode)
331{
332 struct inode_security_struct *isec = inode->i_security;
333 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
334
Waiman Long9629d042015-07-10 17:19:56 -0400335 /*
336 * As not all inode security structures are in a list, we check for
337 * empty list outside of the lock to make sure that we won't waste
338 * time taking a lock doing nothing.
339 *
340 * The list_del_init() function can be safely called more than once.
341 * It should not be possible for this function to be called with
342 * concurrent list_add(), but for better safety against future changes
343 * in the code, we use list_empty_careful() here.
344 */
345 if (!list_empty_careful(&isec->list)) {
346 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400348 spin_unlock(&sbsec->isec_lock);
349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500351 /*
352 * The inode may still be referenced in a path walk and
353 * a call to selinux_inode_permission() can be made
354 * after inode_free_security() is called. Ideally, the VFS
355 * wouldn't do this, but fixing that is a much harder
356 * job. For now, simply free the i_security via RCU, and
357 * leave the current inode->i_security pointer intact.
358 * The inode will be freed after the RCU grace period too.
359 */
360 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361}
362
363static int file_alloc_security(struct file *file)
364{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100366 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Sangwoo63205652015-10-21 17:44:30 -0400368 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 if (!fsec)
370 return -ENOMEM;
371
David Howells275bb412008-11-14 10:39:19 +1100372 fsec->sid = sid;
373 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 file->f_security = fsec;
375
376 return 0;
377}
378
379static void file_free_security(struct file *file)
380{
381 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400383 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
386static int superblock_alloc_security(struct super_block *sb)
387{
388 struct superblock_security_struct *sbsec;
389
James Morris89d155e2005-10-30 14:59:21 -0800390 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (!sbsec)
392 return -ENOMEM;
393
Eric Parisbc7e9822006-09-25 23:32:02 -0700394 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 INIT_LIST_HEAD(&sbsec->isec_head);
396 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 sbsec->sb = sb;
398 sbsec->sid = SECINITSID_UNLABELED;
399 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700400 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 sb->s_security = sbsec;
402
403 return 0;
404}
405
406static void superblock_free_security(struct super_block *sb)
407{
408 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 sb->s_security = NULL;
410 kfree(sbsec);
411}
412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413static inline int inode_doinit(struct inode *inode)
414{
415 return inode_doinit_with_dentry(inode, NULL);
416}
417
418enum {
Eric Paris31e87932007-09-19 17:19:12 -0400419 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 Opt_context = 1,
421 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500422 Opt_defcontext = 3,
423 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500424 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400425 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426};
427
Eric Parisd355987f2012-08-24 15:58:53 -0400428#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
429
Steven Whitehousea447c092008-10-13 10:46:57 +0100430static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400431 {Opt_context, CONTEXT_STR "%s"},
432 {Opt_fscontext, FSCONTEXT_STR "%s"},
433 {Opt_defcontext, DEFCONTEXT_STR "%s"},
434 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500435 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400436 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437};
438
439#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
440
Eric Parisc312feb2006-07-10 04:43:53 -0700441static int may_context_mount_sb_relabel(u32 sid,
442 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100443 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700444{
David Howells275bb412008-11-14 10:39:19 +1100445 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700446 int rc;
447
448 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
449 FILESYSTEM__RELABELFROM, NULL);
450 if (rc)
451 return rc;
452
453 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
454 FILESYSTEM__RELABELTO, NULL);
455 return rc;
456}
457
Eric Paris08089252006-07-10 04:43:55 -0700458static int may_context_mount_inode_relabel(u32 sid,
459 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100460 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700461{
David Howells275bb412008-11-14 10:39:19 +1100462 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700463 int rc;
464 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
465 FILESYSTEM__RELABELFROM, NULL);
466 if (rc)
467 return rc;
468
469 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
470 FILESYSTEM__ASSOCIATE, NULL);
471 return rc;
472}
473
Eric Parisb43e7252012-10-10 14:27:35 -0400474static int selinux_is_sblabel_mnt(struct super_block *sb)
475{
476 struct superblock_security_struct *sbsec = sb->s_security;
477
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500478 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
479 sbsec->behavior == SECURITY_FS_USE_TRANS ||
480 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400481 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500482 /* Special handling. Genfs but also in-core setxattr handler */
483 !strcmp(sb->s_type->name, "sysfs") ||
484 !strcmp(sb->s_type->name, "pstore") ||
485 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500486 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500487 !strcmp(sb->s_type->name, "rootfs") ||
488 (selinux_policycap_cgroupseclabel &&
489 (!strcmp(sb->s_type->name, "cgroup") ||
490 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400491}
492
Eric Parisc9180a52007-11-30 13:00:35 -0500493static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
495 struct superblock_security_struct *sbsec = sb->s_security;
496 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000497 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 int rc = 0;
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
501 /* Make sure that the xattr handler exists and that no
502 error other than -ENODATA is returned by getxattr on
503 the root directory. -ENODATA is ok, as this may be
504 the first boot of the SELinux kernel before we have
505 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200506 if (!(root_inode->i_opflags & IOP_XATTR)) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800507 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
508 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 rc = -EOPNOTSUPP;
510 goto out;
511 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200512
513 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if (rc < 0 && rc != -ENODATA) {
515 if (rc == -EOPNOTSUPP)
516 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800517 "%s) has no security xattr handler\n",
518 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 else
520 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800521 "%s) getxattr errno %d\n", sb->s_id,
522 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 goto out;
524 }
525 }
526
Eric Pariseadcabc2012-08-24 15:59:14 -0400527 sbsec->flags |= SE_SBINITIALIZED;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400528
529 /*
530 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
531 * leave the flag untouched because sb_clone_mnt_opts might be handing
532 * us a superblock that needs the flag to be cleared.
533 */
Eric Parisb43e7252012-10-10 14:27:35 -0400534 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400535 sbsec->flags |= SBLABEL_MNT;
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400536 else
537 sbsec->flags &= ~SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500540 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 /* Initialize any other inodes associated with the superblock, e.g.
543 inodes created prior to initial policy load or inodes created
544 during get_sb by a pseudo filesystem that directly
545 populates itself. */
546 spin_lock(&sbsec->isec_lock);
547next_inode:
548 if (!list_empty(&sbsec->isec_head)) {
549 struct inode_security_struct *isec =
550 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500551 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400553 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 spin_unlock(&sbsec->isec_lock);
555 inode = igrab(inode);
556 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500557 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 inode_doinit(inode);
559 iput(inode);
560 }
561 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 goto next_inode;
563 }
564 spin_unlock(&sbsec->isec_lock);
565out:
Eric Parisc9180a52007-11-30 13:00:35 -0500566 return rc;
567}
568
569/*
570 * This function should allow an FS to ask what it's mount security
571 * options were so it can use those later for submounts, displaying
572 * mount options, or whatever.
573 */
574static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500575 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500576{
577 int rc = 0, i;
578 struct superblock_security_struct *sbsec = sb->s_security;
579 char *context = NULL;
580 u32 len;
581 char tmp;
582
Eric Parise0007522008-03-05 10:31:54 -0500583 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500584
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500585 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500586 return -EINVAL;
587
588 if (!ss_initialized)
589 return -EINVAL;
590
Eric Parisaf8e50c2012-08-24 15:59:00 -0400591 /* make sure we always check enough bits to cover the mask */
592 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
593
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500594 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500595 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400596 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500597 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500598 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500599 tmp >>= 1;
600 }
David P. Quigley11689d42009-01-16 09:22:03 -0500601 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400602 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500603 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500604
Eric Parise0007522008-03-05 10:31:54 -0500605 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
606 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500607 rc = -ENOMEM;
608 goto out_free;
609 }
610
Eric Parise0007522008-03-05 10:31:54 -0500611 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
612 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500613 rc = -ENOMEM;
614 goto out_free;
615 }
616
617 i = 0;
618 if (sbsec->flags & FSCONTEXT_MNT) {
619 rc = security_sid_to_context(sbsec->sid, &context, &len);
620 if (rc)
621 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500622 opts->mnt_opts[i] = context;
623 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500624 }
625 if (sbsec->flags & CONTEXT_MNT) {
626 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
627 if (rc)
628 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500629 opts->mnt_opts[i] = context;
630 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500631 }
632 if (sbsec->flags & DEFCONTEXT_MNT) {
633 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
634 if (rc)
635 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500636 opts->mnt_opts[i] = context;
637 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500638 }
639 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500640 struct dentry *root = sbsec->sb->s_root;
641 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500642
643 rc = security_sid_to_context(isec->sid, &context, &len);
644 if (rc)
645 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500646 opts->mnt_opts[i] = context;
647 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500648 }
Eric Paris12f348b2012-10-09 10:56:25 -0400649 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500650 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400651 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500652 }
Eric Parisc9180a52007-11-30 13:00:35 -0500653
Eric Parise0007522008-03-05 10:31:54 -0500654 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500655
656 return 0;
657
658out_free:
Eric Parise0007522008-03-05 10:31:54 -0500659 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500660 return rc;
661}
662
663static int bad_option(struct superblock_security_struct *sbsec, char flag,
664 u32 old_sid, u32 new_sid)
665{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500666 char mnt_flags = sbsec->flags & SE_MNTMASK;
667
Eric Parisc9180a52007-11-30 13:00:35 -0500668 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500669 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500670 if (!(sbsec->flags & flag) ||
671 (old_sid != new_sid))
672 return 1;
673
674 /* check if we were passed the same options twice,
675 * aka someone passed context=a,context=b
676 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500677 if (!(sbsec->flags & SE_SBINITIALIZED))
678 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500679 return 1;
680 return 0;
681}
Eric Parise0007522008-03-05 10:31:54 -0500682
Eric Parisc9180a52007-11-30 13:00:35 -0500683/*
684 * Allow filesystems with binary mount data to explicitly set mount point
685 * labeling information.
686 */
Eric Parise0007522008-03-05 10:31:54 -0500687static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400688 struct security_mnt_opts *opts,
689 unsigned long kern_flags,
690 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500691{
David Howells275bb412008-11-14 10:39:19 +1100692 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500693 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500694 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800695 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500696 struct dentry *root = sbsec->sb->s_root;
Paul Moore2c971652016-04-19 16:36:28 -0400697 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500698 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
699 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500700 char **mount_options = opts->mnt_opts;
701 int *flags = opts->mnt_opts_flags;
702 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500703
704 mutex_lock(&sbsec->lock);
705
706 if (!ss_initialized) {
707 if (!num_opts) {
708 /* Defer initialization until selinux_complete_init,
709 after the initial policy is loaded and the security
710 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500711 goto out;
712 }
713 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400714 printk(KERN_WARNING "SELinux: Unable to set superblock options "
715 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500716 goto out;
717 }
David Quigley649f6e72013-05-22 12:50:36 -0400718 if (kern_flags && !set_kern_flags) {
719 /* Specifying internal flags without providing a place to
720 * place the results is not allowed */
721 rc = -EINVAL;
722 goto out;
723 }
Eric Parisc9180a52007-11-30 13:00:35 -0500724
725 /*
Eric Parise0007522008-03-05 10:31:54 -0500726 * Binary mount data FS will come through this function twice. Once
727 * from an explicit call and once from the generic calls from the vfs.
728 * Since the generic VFS calls will not contain any security mount data
729 * we need to skip the double mount verification.
730 *
731 * This does open a hole in which we will not notice if the first
732 * mount using this sb set explict options and a second mount using
733 * this sb does not set any security options. (The first options
734 * will be used for both mounts)
735 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500736 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500737 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400738 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500739
Paul Moore2c971652016-04-19 16:36:28 -0400740 root_isec = backing_inode_security_novalidate(root);
741
Eric Parise0007522008-03-05 10:31:54 -0500742 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500743 * parse the mount options, check if they are valid sids.
744 * also check if someone is trying to mount the same sb more
745 * than once with different security options.
746 */
747 for (i = 0; i < num_opts; i++) {
748 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500749
Eric Paris12f348b2012-10-09 10:56:25 -0400750 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500751 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400752 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500753 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400754 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800755 "(%s) failed for (dev %s, type %s) errno=%d\n",
756 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500757 goto out;
758 }
759 switch (flags[i]) {
760 case FSCONTEXT_MNT:
761 fscontext_sid = sid;
762
763 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
764 fscontext_sid))
765 goto out_double_mount;
766
767 sbsec->flags |= FSCONTEXT_MNT;
768 break;
769 case CONTEXT_MNT:
770 context_sid = sid;
771
772 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
773 context_sid))
774 goto out_double_mount;
775
776 sbsec->flags |= CONTEXT_MNT;
777 break;
778 case ROOTCONTEXT_MNT:
779 rootcontext_sid = sid;
780
781 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
782 rootcontext_sid))
783 goto out_double_mount;
784
785 sbsec->flags |= ROOTCONTEXT_MNT;
786
787 break;
788 case DEFCONTEXT_MNT:
789 defcontext_sid = sid;
790
791 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
792 defcontext_sid))
793 goto out_double_mount;
794
795 sbsec->flags |= DEFCONTEXT_MNT;
796
797 break;
798 default:
799 rc = -EINVAL;
800 goto out;
801 }
802 }
803
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500804 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500805 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500806 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500807 goto out_double_mount;
808 rc = 0;
809 goto out;
810 }
811
James Morris089be432008-07-15 18:32:49 +1000812 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400813 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
814
Stephen Smalley8e014722015-06-04 16:22:17 -0400815 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep6a391182017-06-20 09:35:33 -0700816 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley8e014722015-06-04 16:22:17 -0400817 !strcmp(sb->s_type->name, "sysfs") ||
818 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400819 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500820
David Quigleyeb9ae682013-05-22 12:50:37 -0400821 if (!sbsec->behavior) {
822 /*
823 * Determine the labeling behavior to use for this
824 * filesystem type.
825 */
Paul Moore98f700f2013-09-18 13:52:20 -0400826 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400827 if (rc) {
828 printk(KERN_WARNING
829 "%s: security_fs_use(%s) returned %d\n",
830 __func__, sb->s_type->name, rc);
831 goto out;
832 }
Eric Parisc9180a52007-11-30 13:00:35 -0500833 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500834
835 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500836 * If this is a user namespace mount and the filesystem type is not
837 * explicitly whitelisted, then no contexts are allowed on the command
838 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500839 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500840 if (sb->s_user_ns != &init_user_ns &&
841 strcmp(sb->s_type->name, "tmpfs") &&
842 strcmp(sb->s_type->name, "ramfs") &&
843 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500844 if (context_sid || fscontext_sid || rootcontext_sid ||
845 defcontext_sid) {
846 rc = -EACCES;
847 goto out;
848 }
849 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
850 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
851 rc = security_transition_sid(current_sid(), current_sid(),
852 SECCLASS_FILE, NULL,
853 &sbsec->mntpoint_sid);
854 if (rc)
855 goto out;
856 }
857 goto out_set_opts;
858 }
859
Eric Parisc9180a52007-11-30 13:00:35 -0500860 /* sets the context of the superblock for the fs being mounted. */
861 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100862 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500863 if (rc)
864 goto out;
865
866 sbsec->sid = fscontext_sid;
867 }
868
869 /*
870 * Switch to using mount point labeling behavior.
871 * sets the label used on all file below the mountpoint, and will set
872 * the superblock context if not already set.
873 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400874 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
875 sbsec->behavior = SECURITY_FS_USE_NATIVE;
876 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
877 }
878
Eric Parisc9180a52007-11-30 13:00:35 -0500879 if (context_sid) {
880 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100881 rc = may_context_mount_sb_relabel(context_sid, sbsec,
882 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500883 if (rc)
884 goto out;
885 sbsec->sid = context_sid;
886 } else {
David Howells275bb412008-11-14 10:39:19 +1100887 rc = may_context_mount_inode_relabel(context_sid, sbsec,
888 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500889 if (rc)
890 goto out;
891 }
892 if (!rootcontext_sid)
893 rootcontext_sid = context_sid;
894
895 sbsec->mntpoint_sid = context_sid;
896 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
897 }
898
899 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100900 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
901 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500902 if (rc)
903 goto out;
904
905 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500906 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500907 }
908
909 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400910 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
911 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500912 rc = -EINVAL;
913 printk(KERN_WARNING "SELinux: defcontext option is "
914 "invalid for this filesystem type\n");
915 goto out;
916 }
917
918 if (defcontext_sid != sbsec->def_sid) {
919 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100920 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500921 if (rc)
922 goto out;
923 }
924
925 sbsec->def_sid = defcontext_sid;
926 }
927
Seth Forsheeaad82892016-04-26 14:36:20 -0500928out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500929 rc = sb_finish_set_opts(sb);
930out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700931 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500933out_double_mount:
934 rc = -EINVAL;
935 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800936 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500937 goto out;
938}
939
Jeff Layton094f7b62013-04-01 08:14:24 -0400940static int selinux_cmp_sb_context(const struct super_block *oldsb,
941 const struct super_block *newsb)
942{
943 struct superblock_security_struct *old = oldsb->s_security;
944 struct superblock_security_struct *new = newsb->s_security;
945 char oldflags = old->flags & SE_MNTMASK;
946 char newflags = new->flags & SE_MNTMASK;
947
948 if (oldflags != newflags)
949 goto mismatch;
950 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
951 goto mismatch;
952 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
953 goto mismatch;
954 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
955 goto mismatch;
956 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500957 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
958 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400959 if (oldroot->sid != newroot->sid)
960 goto mismatch;
961 }
962 return 0;
963mismatch:
964 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
965 "different security settings for (dev %s, "
966 "type %s)\n", newsb->s_id, newsb->s_type->name);
967 return -EBUSY;
968}
969
970static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400971 struct super_block *newsb,
972 unsigned long kern_flags,
973 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500974{
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400975 int rc = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500976 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
977 struct superblock_security_struct *newsbsec = newsb->s_security;
978
979 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
980 int set_context = (oldsbsec->flags & CONTEXT_MNT);
981 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
982
Eric Paris0f5e6422008-04-21 16:24:11 -0400983 /*
984 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400985 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400986 */
Al Viroe8c26252010-03-23 06:36:54 -0400987 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400988 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500989
Scott Mayhew0b4d3452017-06-05 11:45:04 -0400990 /*
991 * Specifying internal flags without providing a place to
992 * place the results is not allowed.
993 */
994 if (kern_flags && !set_kern_flags)
995 return -EINVAL;
996
Eric Parisc9180a52007-11-30 13:00:35 -0500997 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500998 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500999
Jeff Layton094f7b62013-04-01 08:14:24 -04001000 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001001 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -04001002 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -04001003
Eric Parisc9180a52007-11-30 13:00:35 -05001004 mutex_lock(&newsbsec->lock);
1005
1006 newsbsec->flags = oldsbsec->flags;
1007
1008 newsbsec->sid = oldsbsec->sid;
1009 newsbsec->def_sid = oldsbsec->def_sid;
1010 newsbsec->behavior = oldsbsec->behavior;
1011
Scott Mayhew0b4d3452017-06-05 11:45:04 -04001012 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
1013 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
1014 rc = security_fs_use(newsb);
1015 if (rc)
1016 goto out;
1017 }
1018
1019 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
1020 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
1021 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
1022 }
1023
Eric Parisc9180a52007-11-30 13:00:35 -05001024 if (set_context) {
1025 u32 sid = oldsbsec->mntpoint_sid;
1026
1027 if (!set_fscontext)
1028 newsbsec->sid = sid;
1029 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001030 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -05001031 newisec->sid = sid;
1032 }
1033 newsbsec->mntpoint_sid = sid;
1034 }
1035 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001036 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
1037 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -05001038
1039 newisec->sid = oldisec->sid;
1040 }
1041
1042 sb_finish_set_opts(newsb);
Scott Mayhew0b4d3452017-06-05 11:45:04 -04001043out:
Eric Parisc9180a52007-11-30 13:00:35 -05001044 mutex_unlock(&newsbsec->lock);
Scott Mayhew0b4d3452017-06-05 11:45:04 -04001045 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -05001046}
1047
Adrian Bunk2e1479d2008-03-17 22:29:23 +02001048static int selinux_parse_opts_str(char *options,
1049 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001050{
Eric Parise0007522008-03-05 10:31:54 -05001051 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -05001052 char *context = NULL, *defcontext = NULL;
1053 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -05001054 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001055
Eric Parise0007522008-03-05 10:31:54 -05001056 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001057
1058 /* Standard string-based options. */
1059 while ((p = strsep(&options, "|")) != NULL) {
1060 int token;
1061 substring_t args[MAX_OPT_ARGS];
1062
1063 if (!*p)
1064 continue;
1065
1066 token = match_token(p, tokens, args);
1067
1068 switch (token) {
1069 case Opt_context:
1070 if (context || defcontext) {
1071 rc = -EINVAL;
1072 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1073 goto out_err;
1074 }
1075 context = match_strdup(&args[0]);
1076 if (!context) {
1077 rc = -ENOMEM;
1078 goto out_err;
1079 }
1080 break;
1081
1082 case Opt_fscontext:
1083 if (fscontext) {
1084 rc = -EINVAL;
1085 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1086 goto out_err;
1087 }
1088 fscontext = match_strdup(&args[0]);
1089 if (!fscontext) {
1090 rc = -ENOMEM;
1091 goto out_err;
1092 }
1093 break;
1094
1095 case Opt_rootcontext:
1096 if (rootcontext) {
1097 rc = -EINVAL;
1098 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1099 goto out_err;
1100 }
1101 rootcontext = match_strdup(&args[0]);
1102 if (!rootcontext) {
1103 rc = -ENOMEM;
1104 goto out_err;
1105 }
1106 break;
1107
1108 case Opt_defcontext:
1109 if (context || defcontext) {
1110 rc = -EINVAL;
1111 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1112 goto out_err;
1113 }
1114 defcontext = match_strdup(&args[0]);
1115 if (!defcontext) {
1116 rc = -ENOMEM;
1117 goto out_err;
1118 }
1119 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001120 case Opt_labelsupport:
1121 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001122 default:
1123 rc = -EINVAL;
1124 printk(KERN_WARNING "SELinux: unknown mount option\n");
1125 goto out_err;
1126
1127 }
1128 }
1129
Eric Parise0007522008-03-05 10:31:54 -05001130 rc = -ENOMEM;
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001131 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_KERNEL);
Eric Parise0007522008-03-05 10:31:54 -05001132 if (!opts->mnt_opts)
1133 goto out_err;
1134
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001135 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int),
1136 GFP_KERNEL);
Paul Moore023f1082017-06-07 16:48:19 -04001137 if (!opts->mnt_opts_flags)
Eric Parise0007522008-03-05 10:31:54 -05001138 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001139
Eric Parise0007522008-03-05 10:31:54 -05001140 if (fscontext) {
1141 opts->mnt_opts[num_mnt_opts] = fscontext;
1142 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1143 }
1144 if (context) {
1145 opts->mnt_opts[num_mnt_opts] = context;
1146 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1147 }
1148 if (rootcontext) {
1149 opts->mnt_opts[num_mnt_opts] = rootcontext;
1150 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1151 }
1152 if (defcontext) {
1153 opts->mnt_opts[num_mnt_opts] = defcontext;
1154 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1155 }
1156
1157 opts->num_mnt_opts = num_mnt_opts;
1158 return 0;
1159
Eric Parisc9180a52007-11-30 13:00:35 -05001160out_err:
Paul Moore023f1082017-06-07 16:48:19 -04001161 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -05001162 kfree(context);
1163 kfree(defcontext);
1164 kfree(fscontext);
1165 kfree(rootcontext);
1166 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167}
Eric Parise0007522008-03-05 10:31:54 -05001168/*
1169 * string mount options parsing and call set the sbsec
1170 */
1171static int superblock_doinit(struct super_block *sb, void *data)
1172{
1173 int rc = 0;
1174 char *options = data;
1175 struct security_mnt_opts opts;
1176
1177 security_init_mnt_opts(&opts);
1178
1179 if (!data)
1180 goto out;
1181
1182 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1183
1184 rc = selinux_parse_opts_str(options, &opts);
1185 if (rc)
1186 goto out_err;
1187
1188out:
David Quigley649f6e72013-05-22 12:50:36 -04001189 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001190
1191out_err:
1192 security_free_mnt_opts(&opts);
1193 return rc;
1194}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Adrian Bunk3583a712008-07-22 20:21:23 +03001196static void selinux_write_opts(struct seq_file *m,
1197 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001198{
1199 int i;
1200 char *prefix;
1201
1202 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001203 char *has_comma;
1204
1205 if (opts->mnt_opts[i])
1206 has_comma = strchr(opts->mnt_opts[i], ',');
1207 else
1208 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001209
1210 switch (opts->mnt_opts_flags[i]) {
1211 case CONTEXT_MNT:
1212 prefix = CONTEXT_STR;
1213 break;
1214 case FSCONTEXT_MNT:
1215 prefix = FSCONTEXT_STR;
1216 break;
1217 case ROOTCONTEXT_MNT:
1218 prefix = ROOTCONTEXT_STR;
1219 break;
1220 case DEFCONTEXT_MNT:
1221 prefix = DEFCONTEXT_STR;
1222 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001223 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001224 seq_putc(m, ',');
1225 seq_puts(m, LABELSUPP_STR);
1226 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001227 default:
1228 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001229 return;
Eric Paris2069f452008-07-04 09:47:13 +10001230 };
1231 /* we need a comma before each option */
1232 seq_putc(m, ',');
1233 seq_puts(m, prefix);
1234 if (has_comma)
1235 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001236 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001237 if (has_comma)
1238 seq_putc(m, '\"');
1239 }
1240}
1241
1242static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1243{
1244 struct security_mnt_opts opts;
1245 int rc;
1246
1247 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001248 if (rc) {
1249 /* before policy load we may get EINVAL, don't show anything */
1250 if (rc == -EINVAL)
1251 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001252 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001253 }
Eric Paris2069f452008-07-04 09:47:13 +10001254
1255 selinux_write_opts(m, &opts);
1256
1257 security_free_mnt_opts(&opts);
1258
1259 return rc;
1260}
1261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262static inline u16 inode_mode_to_security_class(umode_t mode)
1263{
1264 switch (mode & S_IFMT) {
1265 case S_IFSOCK:
1266 return SECCLASS_SOCK_FILE;
1267 case S_IFLNK:
1268 return SECCLASS_LNK_FILE;
1269 case S_IFREG:
1270 return SECCLASS_FILE;
1271 case S_IFBLK:
1272 return SECCLASS_BLK_FILE;
1273 case S_IFDIR:
1274 return SECCLASS_DIR;
1275 case S_IFCHR:
1276 return SECCLASS_CHR_FILE;
1277 case S_IFIFO:
1278 return SECCLASS_FIFO_FILE;
1279
1280 }
1281
1282 return SECCLASS_FILE;
1283}
1284
James Morris13402582005-09-30 14:24:34 -04001285static inline int default_protocol_stream(int protocol)
1286{
1287 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1288}
1289
1290static inline int default_protocol_dgram(int protocol)
1291{
1292 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1293}
1294
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1296{
Stephen Smalleyda69a532017-01-09 10:07:30 -05001297 int extsockclass = selinux_policycap_extsockclass;
1298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 switch (family) {
1300 case PF_UNIX:
1301 switch (type) {
1302 case SOCK_STREAM:
1303 case SOCK_SEQPACKET:
1304 return SECCLASS_UNIX_STREAM_SOCKET;
1305 case SOCK_DGRAM:
Luis Ressel2a764b52017-07-25 15:13:41 -04001306 case SOCK_RAW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 return SECCLASS_UNIX_DGRAM_SOCKET;
1308 }
1309 break;
1310 case PF_INET:
1311 case PF_INET6:
1312 switch (type) {
1313 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001314 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001315 if (default_protocol_stream(protocol))
1316 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001317 else if (extsockclass && protocol == IPPROTO_SCTP)
1318 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001319 else
1320 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001322 if (default_protocol_dgram(protocol))
1323 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001324 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1325 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001326 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001327 else
1328 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001329 case SOCK_DCCP:
1330 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001331 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 return SECCLASS_RAWIP_SOCKET;
1333 }
1334 break;
1335 case PF_NETLINK:
1336 switch (protocol) {
1337 case NETLINK_ROUTE:
1338 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001339 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1341 case NETLINK_NFLOG:
1342 return SECCLASS_NETLINK_NFLOG_SOCKET;
1343 case NETLINK_XFRM:
1344 return SECCLASS_NETLINK_XFRM_SOCKET;
1345 case NETLINK_SELINUX:
1346 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001347 case NETLINK_ISCSI:
1348 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 case NETLINK_AUDIT:
1350 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001351 case NETLINK_FIB_LOOKUP:
1352 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1353 case NETLINK_CONNECTOR:
1354 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1355 case NETLINK_NETFILTER:
1356 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 case NETLINK_DNRTMSG:
1358 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001359 case NETLINK_KOBJECT_UEVENT:
1360 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001361 case NETLINK_GENERIC:
1362 return SECCLASS_NETLINK_GENERIC_SOCKET;
1363 case NETLINK_SCSITRANSPORT:
1364 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1365 case NETLINK_RDMA:
1366 return SECCLASS_NETLINK_RDMA_SOCKET;
1367 case NETLINK_CRYPTO:
1368 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 default:
1370 return SECCLASS_NETLINK_SOCKET;
1371 }
1372 case PF_PACKET:
1373 return SECCLASS_PACKET_SOCKET;
1374 case PF_KEY:
1375 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001376 case PF_APPLETALK:
1377 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 }
1379
Stephen Smalleyda69a532017-01-09 10:07:30 -05001380 if (extsockclass) {
1381 switch (family) {
1382 case PF_AX25:
1383 return SECCLASS_AX25_SOCKET;
1384 case PF_IPX:
1385 return SECCLASS_IPX_SOCKET;
1386 case PF_NETROM:
1387 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001388 case PF_ATMPVC:
1389 return SECCLASS_ATMPVC_SOCKET;
1390 case PF_X25:
1391 return SECCLASS_X25_SOCKET;
1392 case PF_ROSE:
1393 return SECCLASS_ROSE_SOCKET;
1394 case PF_DECnet:
1395 return SECCLASS_DECNET_SOCKET;
1396 case PF_ATMSVC:
1397 return SECCLASS_ATMSVC_SOCKET;
1398 case PF_RDS:
1399 return SECCLASS_RDS_SOCKET;
1400 case PF_IRDA:
1401 return SECCLASS_IRDA_SOCKET;
1402 case PF_PPPOX:
1403 return SECCLASS_PPPOX_SOCKET;
1404 case PF_LLC:
1405 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001406 case PF_CAN:
1407 return SECCLASS_CAN_SOCKET;
1408 case PF_TIPC:
1409 return SECCLASS_TIPC_SOCKET;
1410 case PF_BLUETOOTH:
1411 return SECCLASS_BLUETOOTH_SOCKET;
1412 case PF_IUCV:
1413 return SECCLASS_IUCV_SOCKET;
1414 case PF_RXRPC:
1415 return SECCLASS_RXRPC_SOCKET;
1416 case PF_ISDN:
1417 return SECCLASS_ISDN_SOCKET;
1418 case PF_PHONET:
1419 return SECCLASS_PHONET_SOCKET;
1420 case PF_IEEE802154:
1421 return SECCLASS_IEEE802154_SOCKET;
1422 case PF_CAIF:
1423 return SECCLASS_CAIF_SOCKET;
1424 case PF_ALG:
1425 return SECCLASS_ALG_SOCKET;
1426 case PF_NFC:
1427 return SECCLASS_NFC_SOCKET;
1428 case PF_VSOCK:
1429 return SECCLASS_VSOCK_SOCKET;
1430 case PF_KCM:
1431 return SECCLASS_KCM_SOCKET;
1432 case PF_QIPCRTR:
1433 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001434 case PF_SMC:
1435 return SECCLASS_SMC_SOCKET;
1436#if PF_MAX > 44
Stephen Smalleyda69a532017-01-09 10:07:30 -05001437#error New address family defined, please update this function.
1438#endif
1439 }
1440 }
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 return SECCLASS_SOCKET;
1443}
1444
Stephen Smalley134509d2015-06-04 16:22:17 -04001445static int selinux_genfs_get_sid(struct dentry *dentry,
1446 u16 tclass,
1447 u16 flags,
1448 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001450 int rc;
Al Virofc640052016-04-10 01:33:30 -04001451 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001452 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Eric Paris828dfe12008-04-17 13:17:49 -04001454 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 if (!buffer)
1456 return -ENOMEM;
1457
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001458 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1459 if (IS_ERR(path))
1460 rc = PTR_ERR(path);
1461 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001462 if (flags & SE_SBPROC) {
1463 /* each process gets a /proc/PID/ entry. Strip off the
1464 * PID part to get a valid selinux labeling.
1465 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1466 while (path[1] >= '0' && path[1] <= '9') {
1467 path[1] = '/';
1468 path++;
1469 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001470 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001471 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 free_page((unsigned long)buffer);
1474 return rc;
1475}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
1477/* The inode's security attributes must be initialized before first use. */
1478static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1479{
1480 struct superblock_security_struct *sbsec = NULL;
1481 struct inode_security_struct *isec = inode->i_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001482 u32 task_sid, sid = 0;
1483 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 struct dentry *dentry;
1485#define INITCONTEXTLEN 255
1486 char *context = NULL;
1487 unsigned len = 0;
1488 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001490 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001491 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001493 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001494 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001495 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001497 if (isec->sclass == SECCLASS_FILE)
1498 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1499
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001501 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 /* Defer initialization until selinux_complete_init,
1503 after the initial policy is loaded and the security
1504 server is ready to handle calls. */
1505 spin_lock(&sbsec->isec_lock);
1506 if (list_empty(&isec->list))
1507 list_add(&isec->list, &sbsec->isec_head);
1508 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001509 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 }
1511
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001512 sclass = isec->sclass;
1513 task_sid = isec->task_sid;
1514 sid = isec->sid;
1515 isec->initialized = LABEL_PENDING;
1516 spin_unlock(&isec->lock);
1517
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001519 case SECURITY_FS_USE_NATIVE:
1520 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001522 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001523 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 break;
1525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 /* Need a dentry, since the xattr API requires one.
1527 Life would be simpler if we could just pass the inode. */
1528 if (opt_dentry) {
1529 /* Called from d_instantiate or d_splice_alias. */
1530 dentry = dget(opt_dentry);
1531 } else {
1532 /* Called from selinux_complete_init, try to find a dentry. */
1533 dentry = d_find_alias(inode);
1534 }
1535 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001536 /*
1537 * this is can be hit on boot when a file is accessed
1538 * before the policy is loaded. When we load policy we
1539 * may find inodes that have no dentry on the
1540 * sbsec->isec_head list. No reason to complain as these
1541 * will get fixed up the next time we go through
1542 * inode_doinit with a dentry, before these inodes could
1543 * be used again by userspace.
1544 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001545 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 }
1547
1548 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001549 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 if (!context) {
1551 rc = -ENOMEM;
1552 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001553 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001555 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001556 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001558 kfree(context);
1559
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001561 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 if (rc < 0) {
1563 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001564 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001567 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 if (!context) {
1569 rc = -ENOMEM;
1570 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001571 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001573 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001574 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 }
1576 dput(dentry);
1577 if (rc < 0) {
1578 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001579 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001580 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 -rc, inode->i_sb->s_id, inode->i_ino);
1582 kfree(context);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001583 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 }
1585 /* Map ENODATA to the default file SID */
1586 sid = sbsec->def_sid;
1587 rc = 0;
1588 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001589 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001590 sbsec->def_sid,
1591 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001593 char *dev = inode->i_sb->s_id;
1594 unsigned long ino = inode->i_ino;
1595
1596 if (rc == -EINVAL) {
1597 if (printk_ratelimit())
1598 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1599 "context=%s. This indicates you may need to relabel the inode or the "
1600 "filesystem in question.\n", ino, dev, context);
1601 } else {
1602 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1603 "returned %d for dev=%s ino=%ld\n",
1604 __func__, context, -rc, dev, ino);
1605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 kfree(context);
1607 /* Leave with the unlabeled SID */
1608 rc = 0;
1609 break;
1610 }
1611 }
1612 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 break;
1614 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001615 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 break;
1617 case SECURITY_FS_USE_TRANS:
1618 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001619 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
1621 /* Try to obtain a transition SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001622 rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001624 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001626 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001627 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001628 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001630 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001631 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632
Stephen Smalley134509d2015-06-04 16:22:17 -04001633 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001634 /* We must have a dentry to determine the label on
1635 * procfs inodes */
1636 if (opt_dentry)
1637 /* Called from d_instantiate or
1638 * d_splice_alias. */
1639 dentry = dget(opt_dentry);
1640 else
1641 /* Called from selinux_complete_init, try to
1642 * find a dentry. */
1643 dentry = d_find_alias(inode);
1644 /*
1645 * This can be hit on boot when a file is accessed
1646 * before the policy is loaded. When we load policy we
1647 * may find inodes that have no dentry on the
1648 * sbsec->isec_head list. No reason to complain as
1649 * these will get fixed up the next time we go through
1650 * inode_doinit() with a dentry, before these inodes
1651 * could be used again by userspace.
1652 */
1653 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001654 goto out;
1655 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001656 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001657 dput(dentry);
1658 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001659 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 }
1661 break;
1662 }
1663
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001664out:
1665 spin_lock(&isec->lock);
1666 if (isec->initialized == LABEL_PENDING) {
1667 if (!sid || rc) {
1668 isec->initialized = LABEL_INVALID;
1669 goto out_unlock;
1670 }
1671
1672 isec->initialized = LABEL_INITIALIZED;
1673 isec->sid = sid;
1674 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Eric Paris23970742006-09-25 23:32:01 -07001676out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001677 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 return rc;
1679}
1680
1681/* Convert a Linux signal to an access vector. */
1682static inline u32 signal_to_av(int sig)
1683{
1684 u32 perm = 0;
1685
1686 switch (sig) {
1687 case SIGCHLD:
1688 /* Commonly granted from child to parent. */
1689 perm = PROCESS__SIGCHLD;
1690 break;
1691 case SIGKILL:
1692 /* Cannot be caught or ignored */
1693 perm = PROCESS__SIGKILL;
1694 break;
1695 case SIGSTOP:
1696 /* Cannot be caught or ignored */
1697 perm = PROCESS__SIGSTOP;
1698 break;
1699 default:
1700 /* All other signals. */
1701 perm = PROCESS__SIGNAL;
1702 break;
1703 }
1704
1705 return perm;
1706}
1707
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001708#if CAP_LAST_CAP > 63
1709#error Fix SELinux to handle capabilities > 63.
1710#endif
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001713static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001714 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715{
Thomas Liu2bf49692009-07-14 12:14:09 -04001716 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001717 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001718 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001719 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001720 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001721 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
Eric Paris50c205f2012-04-04 15:01:43 -04001723 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 ad.u.cap = cap;
1725
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001726 switch (CAP_TO_INDEX(cap)) {
1727 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001728 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001729 break;
1730 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001731 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001732 break;
1733 default:
1734 printk(KERN_ERR
1735 "SELinux: out of range capability %d\n", cap);
1736 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001737 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001738 }
Eric Paris06112162008-11-11 22:02:50 +11001739
David Howells275bb412008-11-14 10:39:19 +11001740 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001741 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001742 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001743 if (rc2)
1744 return rc2;
1745 }
Eric Paris06112162008-11-11 22:02:50 +11001746 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747}
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749/* Check whether a task has a particular permission to an inode.
1750 The 'adp' parameter is optional and allows other audit
1751 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001752static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 struct inode *inode,
1754 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001755 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001758 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
David Howellse0e81732009-09-02 09:13:40 +01001760 validate_creds(cred);
1761
Eric Paris828dfe12008-04-17 13:17:49 -04001762 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001763 return 0;
1764
David Howells88e67f32008-11-14 10:39:21 +11001765 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 isec = inode->i_security;
1767
Linus Torvalds19e49832013-10-04 12:54:11 -07001768 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769}
1770
1771/* Same as inode_has_perm, but pass explicit audit data containing
1772 the dentry to help the auditing code to more easily generate the
1773 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001774static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 struct dentry *dentry,
1776 u32 av)
1777{
David Howellsc6f493d2015-03-17 22:26:22 +00001778 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001779 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001780
Eric Paris50c205f2012-04-04 15:01:43 -04001781 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001782 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001783 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001784 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001785}
1786
1787/* Same as inode_has_perm, but pass explicit audit data containing
1788 the path to help the auditing code to more easily generate the
1789 pathname if needed. */
1790static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001791 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001792 u32 av)
1793{
David Howellsc6f493d2015-03-17 22:26:22 +00001794 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001795 struct common_audit_data ad;
1796
Eric Paris50c205f2012-04-04 15:01:43 -04001797 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001798 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001799 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001800 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801}
1802
David Howells13f8e982013-06-13 23:37:55 +01001803/* Same as path_has_perm, but uses the inode from the file struct. */
1804static inline int file_path_has_perm(const struct cred *cred,
1805 struct file *file,
1806 u32 av)
1807{
1808 struct common_audit_data ad;
1809
Vivek Goyal43af5de2016-09-09 11:37:49 -04001810 ad.type = LSM_AUDIT_DATA_FILE;
1811 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001812 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001813}
1814
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815/* Check whether a task can use an open file descriptor to
1816 access an inode in a given way. Check access to the
1817 descriptor itself, and then use dentry_has_perm to
1818 check a particular permission to the file.
1819 Access to the descriptor is implicitly granted if it
1820 has the same SID as the process. If av is zero, then
1821 access to the file is not checked, e.g. for cases
1822 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001823static int file_has_perm(const struct cred *cred,
1824 struct file *file,
1825 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001828 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001829 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001830 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 int rc;
1832
Vivek Goyal43af5de2016-09-09 11:37:49 -04001833 ad.type = LSM_AUDIT_DATA_FILE;
1834 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
David Howells275bb412008-11-14 10:39:19 +11001836 if (sid != fsec->sid) {
1837 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 SECCLASS_FD,
1839 FD__USE,
1840 &ad);
1841 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001842 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 }
1844
1845 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001846 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001848 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
David Howells88e67f32008-11-14 10:39:21 +11001850out:
1851 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
David Howellsc3c188b2015-07-10 17:19:58 -04001854/*
1855 * Determine the label for an inode that might be unioned.
1856 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001857static int
1858selinux_determine_inode_label(const struct task_security_struct *tsec,
1859 struct inode *dir,
1860 const struct qstr *name, u16 tclass,
1861 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001862{
1863 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001864
1865 if ((sbsec->flags & SE_SBINITIALIZED) &&
1866 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1867 *_new_isid = sbsec->mntpoint_sid;
1868 } else if ((sbsec->flags & SBLABEL_MNT) &&
1869 tsec->create_sid) {
1870 *_new_isid = tsec->create_sid;
1871 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001872 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001873 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1874 name, _new_isid);
1875 }
1876
1877 return 0;
1878}
1879
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880/* Check whether a task can create a file. */
1881static int may_create(struct inode *dir,
1882 struct dentry *dentry,
1883 u16 tclass)
1884{
Paul Moore5fb49872010-04-22 14:46:19 -04001885 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 struct inode_security_struct *dsec;
1887 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001888 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001889 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 int rc;
1891
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001892 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 sbsec = dir->i_sb->s_security;
1894
David Howells275bb412008-11-14 10:39:19 +11001895 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001896
Eric Paris50c205f2012-04-04 15:01:43 -04001897 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001898 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
David Howells275bb412008-11-14 10:39:19 +11001900 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 DIR__ADD_NAME | DIR__SEARCH,
1902 &ad);
1903 if (rc)
1904 return rc;
1905
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001906 rc = selinux_determine_inode_label(current_security(), dir,
1907 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001908 if (rc)
1909 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
David Howells275bb412008-11-14 10:39:19 +11001911 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 if (rc)
1913 return rc;
1914
1915 return avc_has_perm(newsid, sbsec->sid,
1916 SECCLASS_FILESYSTEM,
1917 FILESYSTEM__ASSOCIATE, &ad);
1918}
1919
Eric Paris828dfe12008-04-17 13:17:49 -04001920#define MAY_LINK 0
1921#define MAY_UNLINK 1
1922#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923
1924/* Check whether a task can link, unlink, or rmdir a file/directory. */
1925static int may_link(struct inode *dir,
1926 struct dentry *dentry,
1927 int kind)
1928
1929{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001931 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001932 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 u32 av;
1934 int rc;
1935
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001936 dsec = inode_security(dir);
1937 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Eric Paris50c205f2012-04-04 15:01:43 -04001939 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001940 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
1942 av = DIR__SEARCH;
1943 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001944 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 if (rc)
1946 return rc;
1947
1948 switch (kind) {
1949 case MAY_LINK:
1950 av = FILE__LINK;
1951 break;
1952 case MAY_UNLINK:
1953 av = FILE__UNLINK;
1954 break;
1955 case MAY_RMDIR:
1956 av = DIR__RMDIR;
1957 break;
1958 default:
Eric Paris744ba352008-04-17 11:52:44 -04001959 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1960 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 return 0;
1962 }
1963
David Howells275bb412008-11-14 10:39:19 +11001964 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 return rc;
1966}
1967
1968static inline int may_rename(struct inode *old_dir,
1969 struct dentry *old_dentry,
1970 struct inode *new_dir,
1971 struct dentry *new_dentry)
1972{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001974 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001975 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 u32 av;
1977 int old_is_dir, new_is_dir;
1978 int rc;
1979
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001980 old_dsec = inode_security(old_dir);
1981 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001982 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001983 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
Eric Paris50c205f2012-04-04 15:01:43 -04001985 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Eric Parisa2694342011-04-25 13:10:27 -04001987 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001988 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1990 if (rc)
1991 return rc;
David Howells275bb412008-11-14 10:39:19 +11001992 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 old_isec->sclass, FILE__RENAME, &ad);
1994 if (rc)
1995 return rc;
1996 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001997 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 old_isec->sclass, DIR__REPARENT, &ad);
1999 if (rc)
2000 return rc;
2001 }
2002
Eric Parisa2694342011-04-25 13:10:27 -04002003 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00002005 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11002007 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 if (rc)
2009 return rc;
David Howells2c616d42015-01-29 12:02:33 +00002010 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002011 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00002012 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11002013 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 new_isec->sclass,
2015 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
2016 if (rc)
2017 return rc;
2018 }
2019
2020 return 0;
2021}
2022
2023/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11002024static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 struct super_block *sb,
2026 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04002027 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11002030 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11002033 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034}
2035
2036/* Convert a Linux mode and permission mask to an access vector. */
2037static inline u32 file_mask_to_av(int mode, int mask)
2038{
2039 u32 av = 0;
2040
Al Virodba19c62011-07-25 20:49:29 -04002041 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 if (mask & MAY_EXEC)
2043 av |= FILE__EXECUTE;
2044 if (mask & MAY_READ)
2045 av |= FILE__READ;
2046
2047 if (mask & MAY_APPEND)
2048 av |= FILE__APPEND;
2049 else if (mask & MAY_WRITE)
2050 av |= FILE__WRITE;
2051
2052 } else {
2053 if (mask & MAY_EXEC)
2054 av |= DIR__SEARCH;
2055 if (mask & MAY_WRITE)
2056 av |= DIR__WRITE;
2057 if (mask & MAY_READ)
2058 av |= DIR__READ;
2059 }
2060
2061 return av;
2062}
2063
2064/* Convert a Linux file to an access vector. */
2065static inline u32 file_to_av(struct file *file)
2066{
2067 u32 av = 0;
2068
2069 if (file->f_mode & FMODE_READ)
2070 av |= FILE__READ;
2071 if (file->f_mode & FMODE_WRITE) {
2072 if (file->f_flags & O_APPEND)
2073 av |= FILE__APPEND;
2074 else
2075 av |= FILE__WRITE;
2076 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002077 if (!av) {
2078 /*
2079 * Special file opened with flags 3 for ioctl-only use.
2080 */
2081 av = FILE__IOCTL;
2082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
2084 return av;
2085}
2086
Eric Paris8b6a5a32008-10-29 17:06:46 -04002087/*
2088 * Convert a file to an access vector and include the correct open
2089 * open permission.
2090 */
2091static inline u32 open_file_to_av(struct file *file)
2092{
2093 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04002094 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002095
Stephen Smalleyccb54472017-05-12 12:41:24 -04002096 if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002097 av |= FILE__OPEN;
2098
Eric Paris8b6a5a32008-10-29 17:06:46 -04002099 return av;
2100}
2101
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102/* Hook functions begin here. */
2103
Stephen Smalley79af7302015-01-21 10:54:10 -05002104static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2105{
2106 u32 mysid = current_sid();
2107 u32 mgrsid = task_sid(mgr);
2108
2109 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
2110 BINDER__SET_CONTEXT_MGR, NULL);
2111}
2112
2113static int selinux_binder_transaction(struct task_struct *from,
2114 struct task_struct *to)
2115{
2116 u32 mysid = current_sid();
2117 u32 fromsid = task_sid(from);
2118 u32 tosid = task_sid(to);
2119 int rc;
2120
2121 if (mysid != fromsid) {
2122 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2123 BINDER__IMPERSONATE, NULL);
2124 if (rc)
2125 return rc;
2126 }
2127
2128 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2129 NULL);
2130}
2131
2132static int selinux_binder_transfer_binder(struct task_struct *from,
2133 struct task_struct *to)
2134{
2135 u32 fromsid = task_sid(from);
2136 u32 tosid = task_sid(to);
2137
2138 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2139 NULL);
2140}
2141
2142static int selinux_binder_transfer_file(struct task_struct *from,
2143 struct task_struct *to,
2144 struct file *file)
2145{
2146 u32 sid = task_sid(to);
2147 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002148 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002149 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002150 struct common_audit_data ad;
2151 int rc;
2152
2153 ad.type = LSM_AUDIT_DATA_PATH;
2154 ad.u.path = file->f_path;
2155
2156 if (sid != fsec->sid) {
2157 rc = avc_has_perm(sid, fsec->sid,
2158 SECCLASS_FD,
2159 FD__USE,
2160 &ad);
2161 if (rc)
2162 return rc;
2163 }
2164
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002165 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002166 return 0;
2167
Paul Moore20cdef82016-04-04 14:14:42 -04002168 isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002169 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2170 &ad);
2171}
2172
Ingo Molnar9e488582009-05-07 19:26:19 +10002173static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002174 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002176 u32 sid = current_sid();
2177 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002178
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002179 if (mode & PTRACE_MODE_READ)
2180 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
2181
2182 return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002183}
2184
2185static int selinux_ptrace_traceme(struct task_struct *parent)
2186{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002187 return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS,
2188 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189}
2190
2191static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002192 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002194 return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS,
2195 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196}
2197
David Howellsd84f4f92008-11-14 10:39:23 +11002198static int selinux_capset(struct cred *new, const struct cred *old,
2199 const kernel_cap_t *effective,
2200 const kernel_cap_t *inheritable,
2201 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002203 return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
2204 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205}
2206
James Morris5626d3e2009-01-30 10:05:06 +11002207/*
2208 * (This comment used to live with the selinux_task_setuid hook,
2209 * which was removed).
2210 *
2211 * Since setuid only affects the current process, and since the SELinux
2212 * controls are not based on the Linux identity attributes, SELinux does not
2213 * need to control this operation. However, SELinux does control the use of
2214 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2215 */
2216
Eric Paris6a9de492012-01-03 12:25:14 -05002217static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2218 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002220 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221}
2222
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2224{
David Howells88e67f32008-11-14 10:39:21 +11002225 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 int rc = 0;
2227
2228 if (!sb)
2229 return 0;
2230
2231 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002232 case Q_SYNC:
2233 case Q_QUOTAON:
2234 case Q_QUOTAOFF:
2235 case Q_SETINFO:
2236 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002237 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002238 break;
2239 case Q_GETFMT:
2240 case Q_GETINFO:
2241 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002242 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002243 break;
2244 default:
2245 rc = 0; /* let the kernel handle invalid cmds */
2246 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 }
2248 return rc;
2249}
2250
2251static int selinux_quota_on(struct dentry *dentry)
2252{
David Howells88e67f32008-11-14 10:39:21 +11002253 const struct cred *cred = current_cred();
2254
Eric Paris2875fa02011-04-28 16:04:24 -04002255 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256}
2257
Eric Paris12b30522010-11-15 18:36:29 -05002258static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002261 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2262 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002263 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2264 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002265 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2266 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2267 /* Set level of messages printed to console */
2268 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002269 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2270 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2271 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002273 /* All other syslog types */
2274 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2275 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276}
2277
2278/*
2279 * Check that a process has enough memory to allocate a new virtual
2280 * mapping. 0 means there is enough memory for the allocation to
2281 * succeed and -ENOMEM implies there is not.
2282 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 * Do not audit the selinux permission check, as this is applied to all
2284 * processes that allocate mappings.
2285 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002286static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287{
2288 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002290 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002291 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 if (rc == 0)
2293 cap_sys_admin = 1;
2294
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002295 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296}
2297
2298/* binprm security operations */
2299
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002300static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002301{
2302 u32 sid = 0;
2303 struct task_struct *tracer;
2304
2305 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002306 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002307 if (tracer)
2308 sid = task_sid(tracer);
2309 rcu_read_unlock();
2310
2311 return sid;
2312}
2313
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002314static int check_nnp_nosuid(const struct linux_binprm *bprm,
2315 const struct task_security_struct *old_tsec,
2316 const struct task_security_struct *new_tsec)
2317{
2318 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002319 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002320 int rc;
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002321 u32 av;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002322
2323 if (!nnp && !nosuid)
2324 return 0; /* neither NNP nor nosuid */
2325
2326 if (new_tsec->sid == old_tsec->sid)
2327 return 0; /* No change in credentials */
2328
2329 /*
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002330 * If the policy enables the nnp_nosuid_transition policy capability,
2331 * then we permit transitions under NNP or nosuid if the
2332 * policy allows the corresponding permission between
2333 * the old and new contexts.
2334 */
2335 if (selinux_policycap_nnp_nosuid_transition) {
2336 av = 0;
2337 if (nnp)
2338 av |= PROCESS2__NNP_TRANSITION;
2339 if (nosuid)
2340 av |= PROCESS2__NOSUID_TRANSITION;
2341 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2342 SECCLASS_PROCESS2, av, NULL);
2343 if (!rc)
2344 return 0;
2345 }
2346
2347 /*
2348 * We also permit NNP or nosuid transitions to bounded SIDs,
2349 * i.e. SIDs that are guaranteed to only be allowed a subset
2350 * of the permissions of the current SID.
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002351 */
2352 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
Stephen Smalleyaf63f412017-07-31 10:12:46 -04002353 if (!rc)
2354 return 0;
2355
2356 /*
2357 * On failure, preserve the errno values for NNP vs nosuid.
2358 * NNP: Operation not permitted for caller.
2359 * nosuid: Permission denied to file.
2360 */
2361 if (nnp)
2362 return -EPERM;
2363 return -EACCES;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002364}
2365
David Howellsa6f76f22008-11-14 10:39:24 +11002366static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367{
David Howellsa6f76f22008-11-14 10:39:24 +11002368 const struct task_security_struct *old_tsec;
2369 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002371 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002372 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 int rc;
2374
David Howellsa6f76f22008-11-14 10:39:24 +11002375 /* SELinux context only depends on initial program or script and not
2376 * the script interpreter */
2377 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 return 0;
2379
David Howellsa6f76f22008-11-14 10:39:24 +11002380 old_tsec = current_security();
2381 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002382 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383
2384 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002385 new_tsec->sid = old_tsec->sid;
2386 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387
Michael LeMay28eba5b2006-06-27 02:53:42 -07002388 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002389 new_tsec->create_sid = 0;
2390 new_tsec->keycreate_sid = 0;
2391 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
David Howellsa6f76f22008-11-14 10:39:24 +11002393 if (old_tsec->exec_sid) {
2394 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002396 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002397
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002398 /* Fail on NNP or nosuid if not an allowed transition. */
2399 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2400 if (rc)
2401 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 } else {
2403 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002404 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002405 SECCLASS_PROCESS, NULL,
2406 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 if (rc)
2408 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002409
2410 /*
2411 * Fallback to old SID on NNP or nosuid if not an allowed
2412 * transition.
2413 */
2414 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2415 if (rc)
2416 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 }
2418
Vivek Goyal43af5de2016-09-09 11:37:49 -04002419 ad.type = LSM_AUDIT_DATA_FILE;
2420 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
David Howellsa6f76f22008-11-14 10:39:24 +11002422 if (new_tsec->sid == old_tsec->sid) {
2423 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2425 if (rc)
2426 return rc;
2427 } else {
2428 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002429 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2431 if (rc)
2432 return rc;
2433
David Howellsa6f76f22008-11-14 10:39:24 +11002434 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2436 if (rc)
2437 return rc;
2438
David Howellsa6f76f22008-11-14 10:39:24 +11002439 /* Check for shared state */
2440 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2441 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2442 SECCLASS_PROCESS, PROCESS__SHARE,
2443 NULL);
2444 if (rc)
2445 return -EPERM;
2446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
David Howellsa6f76f22008-11-14 10:39:24 +11002448 /* Make sure that anyone attempting to ptrace over a task that
2449 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002450 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002451 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002452 if (ptsid != 0) {
2453 rc = avc_has_perm(ptsid, new_tsec->sid,
2454 SECCLASS_PROCESS,
2455 PROCESS__PTRACE, NULL);
2456 if (rc)
2457 return -EPERM;
2458 }
2459 }
2460
2461 /* Clear any possibly unsafe personality bits on exec: */
2462 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
2464
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 return 0;
2466}
2467
Eric Paris828dfe12008-04-17 13:17:49 -04002468static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469{
Paul Moore5fb49872010-04-22 14:46:19 -04002470 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002471 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 int atsecure = 0;
2473
David Howells275bb412008-11-14 10:39:19 +11002474 sid = tsec->sid;
2475 osid = tsec->osid;
2476
2477 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 /* Enable secure mode for SIDs transitions unless
2479 the noatsecure permission is granted between
2480 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002481 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002482 SECCLASS_PROCESS,
2483 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 }
2485
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002486 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487}
2488
Al Viroc3c073f2012-08-21 22:32:06 -04002489static int match_file(const void *p, struct file *file, unsigned fd)
2490{
2491 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2492}
2493
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002495static inline void flush_unauthorized_files(const struct cred *cred,
2496 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002499 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002500 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002501 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002503 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002505 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002506 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002507 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002510 Use file_path_has_perm on the tty path directly
2511 rather than using file_has_perm, as this particular
2512 open file may belong to another process and we are
2513 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002514 file_priv = list_first_entry(&tty->tty_files,
2515 struct tty_file_private, list);
2516 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002517 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002518 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 }
Peter Hurley4a510962016-01-09 21:35:23 -08002520 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002521 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002523 /* Reset controlling tty. */
2524 if (drop_tty)
2525 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
2527 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002528 n = iterate_fd(files, 0, match_file, cred);
2529 if (!n) /* none found? */
2530 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531
Al Viroc3c073f2012-08-21 22:32:06 -04002532 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002533 if (IS_ERR(devnull))
2534 devnull = NULL;
2535 /* replace all the matching ones with this */
2536 do {
2537 replace_fd(n - 1, devnull, 0);
2538 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2539 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002540 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541}
2542
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543/*
David Howellsa6f76f22008-11-14 10:39:24 +11002544 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 */
David Howellsa6f76f22008-11-14 10:39:24 +11002546static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547{
David Howellsa6f76f22008-11-14 10:39:24 +11002548 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 int rc, i;
2551
David Howellsa6f76f22008-11-14 10:39:24 +11002552 new_tsec = bprm->cred->security;
2553 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 return;
2555
2556 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002557 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
David Howellsa6f76f22008-11-14 10:39:24 +11002559 /* Always clear parent death signal on SID transitions. */
2560 current->pdeath_signal = 0;
2561
2562 /* Check whether the new SID can inherit resource limits from the old
2563 * SID. If not, reset all soft limits to the lower of the current
2564 * task's hard limit and the init task's soft limit.
2565 *
2566 * Note that the setting of hard limits (even to lower them) can be
2567 * controlled by the setrlimit check. The inclusion of the init task's
2568 * soft limit into the computation is to avoid resetting soft limits
2569 * higher than the default soft limit for cases where the default is
2570 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2571 */
2572 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2573 PROCESS__RLIMITINH, NULL);
2574 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002575 /* protect against do_prlimit() */
2576 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002577 for (i = 0; i < RLIM_NLIMITS; i++) {
2578 rlim = current->signal->rlim + i;
2579 initrlim = init_task.signal->rlim + i;
2580 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2581 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002582 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002583 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2584 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002585 }
2586}
2587
2588/*
2589 * Clean up the process immediately after the installation of new credentials
2590 * due to exec
2591 */
2592static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2593{
2594 const struct task_security_struct *tsec = current_security();
2595 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002596 u32 osid, sid;
2597 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002598
David Howellsa6f76f22008-11-14 10:39:24 +11002599 osid = tsec->osid;
2600 sid = tsec->sid;
2601
2602 if (sid == osid)
2603 return;
2604
2605 /* Check whether the new SID can inherit signal state from the old SID.
2606 * If not, clear itimers to avoid subsequent signal generation and
2607 * flush and unblock signals.
2608 *
2609 * This must occur _after_ the task SID has been updated so that any
2610 * kill done after the flush will be checked against the new SID.
2611 */
2612 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 if (rc) {
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002614 if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
2615 memset(&itimer, 0, sizeof itimer);
2616 for (i = 0; i < 3; i++)
2617 do_setitimer(i, &itimer, NULL);
2618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002620 if (!fatal_signal_pending(current)) {
2621 flush_sigqueue(&current->pending);
2622 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002623 flush_signal_handlers(current, 1);
2624 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002625 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 spin_unlock_irq(&current->sighand->siglock);
2628 }
2629
David Howellsa6f76f22008-11-14 10:39:24 +11002630 /* Wake up the parent if it is waiting so that it can recheck
2631 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002632 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002633 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002634 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635}
2636
2637/* superblock security operations */
2638
2639static int selinux_sb_alloc_security(struct super_block *sb)
2640{
2641 return superblock_alloc_security(sb);
2642}
2643
2644static void selinux_sb_free_security(struct super_block *sb)
2645{
2646 superblock_free_security(sb);
2647}
2648
2649static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2650{
2651 if (plen > olen)
2652 return 0;
2653
2654 return !memcmp(prefix, option, plen);
2655}
2656
2657static inline int selinux_option(char *option, int len)
2658{
Eric Paris832cbd92008-04-01 13:24:09 -04002659 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2660 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2661 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002662 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2663 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664}
2665
2666static inline void take_option(char **to, char *from, int *first, int len)
2667{
2668 if (!*first) {
2669 **to = ',';
2670 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002671 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 *first = 0;
2673 memcpy(*to, from, len);
2674 *to += len;
2675}
2676
Eric Paris828dfe12008-04-17 13:17:49 -04002677static inline void take_selinux_option(char **to, char *from, int *first,
2678 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002679{
2680 int current_size = 0;
2681
2682 if (!*first) {
2683 **to = '|';
2684 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002685 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002686 *first = 0;
2687
2688 while (current_size < len) {
2689 if (*from != '"') {
2690 **to = *from;
2691 *to += 1;
2692 }
2693 from += 1;
2694 current_size += 1;
2695 }
2696}
2697
Eric Parise0007522008-03-05 10:31:54 -05002698static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699{
2700 int fnosec, fsec, rc = 0;
2701 char *in_save, *in_curr, *in_end;
2702 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002703 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704
2705 in_curr = orig;
2706 sec_curr = copy;
2707
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2709 if (!nosec) {
2710 rc = -ENOMEM;
2711 goto out;
2712 }
2713
2714 nosec_save = nosec;
2715 fnosec = fsec = 1;
2716 in_save = in_end = orig;
2717
2718 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002719 if (*in_end == '"')
2720 open_quote = !open_quote;
2721 if ((*in_end == ',' && open_quote == 0) ||
2722 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 int len = in_end - in_curr;
2724
2725 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002726 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 else
2728 take_option(&nosec, in_curr, &fnosec, len);
2729
2730 in_curr = in_end + 1;
2731 }
2732 } while (*in_end++);
2733
Eric Paris6931dfc2005-06-30 02:58:51 -07002734 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002735 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736out:
2737 return rc;
2738}
2739
Eric Paris026eb162011-03-03 16:09:14 -05002740static int selinux_sb_remount(struct super_block *sb, void *data)
2741{
2742 int rc, i, *flags;
2743 struct security_mnt_opts opts;
2744 char *secdata, **mount_options;
2745 struct superblock_security_struct *sbsec = sb->s_security;
2746
2747 if (!(sbsec->flags & SE_SBINITIALIZED))
2748 return 0;
2749
2750 if (!data)
2751 return 0;
2752
2753 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2754 return 0;
2755
2756 security_init_mnt_opts(&opts);
2757 secdata = alloc_secdata();
2758 if (!secdata)
2759 return -ENOMEM;
2760 rc = selinux_sb_copy_data(data, secdata);
2761 if (rc)
2762 goto out_free_secdata;
2763
2764 rc = selinux_parse_opts_str(secdata, &opts);
2765 if (rc)
2766 goto out_free_secdata;
2767
2768 mount_options = opts.mnt_opts;
2769 flags = opts.mnt_opts_flags;
2770
2771 for (i = 0; i < opts.num_mnt_opts; i++) {
2772 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002773
Eric Paris12f348b2012-10-09 10:56:25 -04002774 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002775 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002776 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002777 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002778 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002779 "(%s) failed for (dev %s, type %s) errno=%d\n",
2780 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002781 goto out_free_opts;
2782 }
2783 rc = -EINVAL;
2784 switch (flags[i]) {
2785 case FSCONTEXT_MNT:
2786 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2787 goto out_bad_option;
2788 break;
2789 case CONTEXT_MNT:
2790 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2791 goto out_bad_option;
2792 break;
2793 case ROOTCONTEXT_MNT: {
2794 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002795 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002796
2797 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2798 goto out_bad_option;
2799 break;
2800 }
2801 case DEFCONTEXT_MNT:
2802 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2803 goto out_bad_option;
2804 break;
2805 default:
2806 goto out_free_opts;
2807 }
2808 }
2809
2810 rc = 0;
2811out_free_opts:
2812 security_free_mnt_opts(&opts);
2813out_free_secdata:
2814 free_secdata(secdata);
2815 return rc;
2816out_bad_option:
2817 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002818 "during remount (dev %s, type=%s)\n", sb->s_id,
2819 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002820 goto out_free_opts;
2821}
2822
James Morris12204e22008-12-19 10:44:42 +11002823static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824{
David Howells88e67f32008-11-14 10:39:21 +11002825 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002826 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 int rc;
2828
2829 rc = superblock_doinit(sb, data);
2830 if (rc)
2831 return rc;
2832
James Morris74192242008-12-19 11:41:10 +11002833 /* Allow all mounts performed by the kernel */
2834 if (flags & MS_KERNMOUNT)
2835 return 0;
2836
Eric Paris50c205f2012-04-04 15:01:43 -04002837 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002838 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002839 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840}
2841
David Howells726c3342006-06-23 02:02:58 -07002842static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
David Howells88e67f32008-11-14 10:39:21 +11002844 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002845 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
Eric Paris50c205f2012-04-04 15:01:43 -04002847 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002848 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002849 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850}
2851
Al Viro808d4e32012-10-11 11:42:01 -04002852static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002853 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002854 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002855 unsigned long flags,
2856 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857{
David Howells88e67f32008-11-14 10:39:21 +11002858 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859
2860 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002861 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002862 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 else
Eric Paris2875fa02011-04-28 16:04:24 -04002864 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865}
2866
2867static int selinux_umount(struct vfsmount *mnt, int flags)
2868{
David Howells88e67f32008-11-14 10:39:21 +11002869 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
David Howells88e67f32008-11-14 10:39:21 +11002871 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002872 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873}
2874
2875/* inode security operations */
2876
2877static int selinux_inode_alloc_security(struct inode *inode)
2878{
2879 return inode_alloc_security(inode);
2880}
2881
2882static void selinux_inode_free_security(struct inode *inode)
2883{
2884 inode_free_security(inode);
2885}
2886
David Quigleyd47be3d2013-05-22 12:50:34 -04002887static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002888 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002889 u32 *ctxlen)
2890{
David Quigleyd47be3d2013-05-22 12:50:34 -04002891 u32 newsid;
2892 int rc;
2893
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002894 rc = selinux_determine_inode_label(current_security(),
2895 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002896 inode_mode_to_security_class(mode),
2897 &newsid);
2898 if (rc)
2899 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002900
2901 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2902}
2903
Vivek Goyala518b0a2016-07-13 10:44:53 -04002904static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2905 struct qstr *name,
2906 const struct cred *old,
2907 struct cred *new)
2908{
2909 u32 newsid;
2910 int rc;
2911 struct task_security_struct *tsec;
2912
2913 rc = selinux_determine_inode_label(old->security,
2914 d_inode(dentry->d_parent), name,
2915 inode_mode_to_security_class(mode),
2916 &newsid);
2917 if (rc)
2918 return rc;
2919
2920 tsec = new->security;
2921 tsec->create_sid = newsid;
2922 return 0;
2923}
2924
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002925static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002926 const struct qstr *qstr,
2927 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002928 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002929{
Paul Moore5fb49872010-04-22 14:46:19 -04002930 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002931 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002932 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002933 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002934 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002935
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002936 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002937
David Howells275bb412008-11-14 10:39:19 +11002938 sid = tsec->sid;
2939 newsid = tsec->create_sid;
2940
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002941 rc = selinux_determine_inode_label(current_security(),
David Howellsc3c188b2015-07-10 17:19:58 -04002942 dir, qstr,
2943 inode_mode_to_security_class(inode->i_mode),
2944 &newsid);
2945 if (rc)
2946 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002947
Eric Paris296fddf2006-09-25 23:32:00 -07002948 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002949 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002950 struct inode_security_struct *isec = inode->i_security;
2951 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2952 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002953 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002954 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002955
Eric Paris12f348b2012-10-09 10:56:25 -04002956 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002957 return -EOPNOTSUPP;
2958
Tetsuo Handa95489062013-07-25 05:44:02 +09002959 if (name)
2960 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002961
2962 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002963 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002964 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002965 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002966 *value = context;
2967 *len = clen;
2968 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002969
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002970 return 0;
2971}
2972
Al Viro4acdaf22011-07-26 01:42:34 -04002973static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974{
2975 return may_create(dir, dentry, SECCLASS_FILE);
2976}
2977
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2979{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 return may_link(dir, old_dentry, MAY_LINK);
2981}
2982
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2984{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 return may_link(dir, dentry, MAY_UNLINK);
2986}
2987
2988static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2989{
2990 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2991}
2992
Al Viro18bb1db2011-07-26 01:41:39 -04002993static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994{
2995 return may_create(dir, dentry, SECCLASS_DIR);
2996}
2997
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2999{
3000 return may_link(dir, dentry, MAY_RMDIR);
3001}
3002
Al Viro1a67aaf2011-07-26 01:52:52 -04003003static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return may_create(dir, dentry, inode_mode_to_security_class(mode));
3006}
3007
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04003009 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010{
3011 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
3012}
3013
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014static int selinux_inode_readlink(struct dentry *dentry)
3015{
David Howells88e67f32008-11-14 10:39:21 +11003016 const struct cred *cred = current_cred();
3017
Eric Paris2875fa02011-04-28 16:04:24 -04003018 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019}
3020
NeilBrownbda0be72015-03-23 13:37:39 +11003021static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
3022 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023{
David Howells88e67f32008-11-14 10:39:21 +11003024 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11003025 struct common_audit_data ad;
3026 struct inode_security_struct *isec;
3027 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
NeilBrownbda0be72015-03-23 13:37:39 +11003029 validate_creds(cred);
3030
3031 ad.type = LSM_AUDIT_DATA_DENTRY;
3032 ad.u.dentry = dentry;
3033 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003034 isec = inode_security_rcu(inode, rcu);
3035 if (IS_ERR(isec))
3036 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11003037
3038 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
3039 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040}
3041
Eric Parisd4cf970d2012-04-04 15:01:42 -04003042static noinline int audit_inode_permission(struct inode *inode,
3043 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07003044 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04003045 unsigned flags)
3046{
3047 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003048 struct inode_security_struct *isec = inode->i_security;
3049 int rc;
3050
Eric Paris50c205f2012-04-04 15:01:43 -04003051 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003052 ad.u.inode = inode;
3053
3054 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07003055 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003056 if (rc)
3057 return rc;
3058 return 0;
3059}
3060
Al Viroe74f71e2011-06-20 19:38:15 -04003061static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062{
David Howells88e67f32008-11-14 10:39:21 +11003063 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003064 u32 perms;
3065 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04003066 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003067 struct inode_security_struct *isec;
3068 u32 sid;
3069 struct av_decision avd;
3070 int rc, rc2;
3071 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Eric Parisb782e0a2010-07-23 11:44:03 -04003073 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003074 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3075
Eric Parisb782e0a2010-07-23 11:44:03 -04003076 /* No permission to check. Existence test. */
3077 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
Eric Paris2e334052012-04-04 15:01:42 -04003080 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003081
Eric Paris2e334052012-04-04 15:01:42 -04003082 if (unlikely(IS_PRIVATE(inode)))
3083 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003084
3085 perms = file_mask_to_av(inode->i_mode, mask);
3086
Eric Paris2e334052012-04-04 15:01:42 -04003087 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003088 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
3089 if (IS_ERR(isec))
3090 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003091
3092 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
3093 audited = avc_audit_required(perms, &avd, rc,
3094 from_access ? FILE__AUDIT_ACCESS : 0,
3095 &denied);
3096 if (likely(!audited))
3097 return rc;
3098
Stephen Smalley626b9742014-04-29 11:29:04 -07003099 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04003100 if (rc2)
3101 return rc2;
3102 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103}
3104
3105static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3106{
David Howells88e67f32008-11-14 10:39:21 +11003107 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003108 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003109 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003110 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003112 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3113 if (ia_valid & ATTR_FORCE) {
3114 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3115 ATTR_FORCE);
3116 if (!ia_valid)
3117 return 0;
3118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003120 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3121 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003122 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
Stephen Smalleyccb54472017-05-12 12:41:24 -04003124 if (selinux_policycap_openperm &&
3125 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3126 (ia_valid & ATTR_SIZE) &&
3127 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003128 av |= FILE__OPEN;
3129
3130 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131}
3132
Al Viro3f7036a2015-03-08 19:28:30 -04003133static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134{
Al Viro3f7036a2015-03-08 19:28:30 -04003135 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136}
3137
David Howells8f0cfa52008-04-29 00:59:41 -07003138static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07003139{
David Howells88e67f32008-11-14 10:39:21 +11003140 const struct cred *cred = current_cred();
3141
Serge E. Hallynb5376772007-10-16 23:31:36 -07003142 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3143 sizeof XATTR_SECURITY_PREFIX - 1)) {
3144 if (!strcmp(name, XATTR_NAME_CAPS)) {
3145 if (!capable(CAP_SETFCAP))
3146 return -EPERM;
3147 } else if (!capable(CAP_SYS_ADMIN)) {
3148 /* A different attribute in the security namespace.
3149 Restrict to administrator. */
3150 return -EPERM;
3151 }
3152 }
3153
3154 /* Not an attribute we recognize, so just check the
3155 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04003156 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003157}
3158
Stephen Smalleydb590002017-04-20 11:31:30 -04003159static bool has_cap_mac_admin(bool audit)
3160{
3161 const struct cred *cred = current_cred();
3162 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3163
3164 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3165 return false;
3166 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3167 return false;
3168 return true;
3169}
3170
David Howells8f0cfa52008-04-29 00:59:41 -07003171static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3172 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173{
David Howellsc6f493d2015-03-17 22:26:22 +00003174 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003175 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003177 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003178 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 int rc = 0;
3180
Serge E. Hallynb5376772007-10-16 23:31:36 -07003181 if (strcmp(name, XATTR_NAME_SELINUX))
3182 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
3184 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003185 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return -EOPNOTSUPP;
3187
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003188 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 return -EPERM;
3190
Eric Paris50c205f2012-04-04 15:01:43 -04003191 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003192 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Paul Moore20cdef82016-04-04 14:14:42 -04003194 isec = backing_inode_security(dentry);
David Howells275bb412008-11-14 10:39:19 +11003195 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 FILE__RELABELFROM, &ad);
3197 if (rc)
3198 return rc;
3199
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003200 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003201 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003202 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003203 struct audit_buffer *ab;
3204 size_t audit_size;
3205 const char *str;
3206
3207 /* We strip a nul only if it is at the end, otherwise the
3208 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003209 if (value) {
3210 str = value;
3211 if (str[size - 1] == '\0')
3212 audit_size = size - 1;
3213 else
3214 audit_size = size;
3215 } else {
3216 str = "";
3217 audit_size = 0;
3218 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003219 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3220 audit_log_format(ab, "op=setxattr invalid_context=");
3221 audit_log_n_untrustedstring(ab, value, audit_size);
3222 audit_log_end(ab);
3223
Stephen Smalley12b29f32008-05-07 13:03:20 -04003224 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003225 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003226 rc = security_context_to_sid_force(value, size, &newsid);
3227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 if (rc)
3229 return rc;
3230
David Howells275bb412008-11-14 10:39:19 +11003231 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 FILE__RELABELTO, &ad);
3233 if (rc)
3234 return rc;
3235
David Howells275bb412008-11-14 10:39:19 +11003236 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003237 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 if (rc)
3239 return rc;
3240
3241 return avc_has_perm(newsid,
3242 sbsec->sid,
3243 SECCLASS_FILESYSTEM,
3244 FILESYSTEM__ASSOCIATE,
3245 &ad);
3246}
3247
David Howells8f0cfa52008-04-29 00:59:41 -07003248static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003249 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003250 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251{
David Howellsc6f493d2015-03-17 22:26:22 +00003252 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003253 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 u32 newsid;
3255 int rc;
3256
3257 if (strcmp(name, XATTR_NAME_SELINUX)) {
3258 /* Not an attribute we recognize, so nothing to do. */
3259 return;
3260 }
3261
Stephen Smalley12b29f32008-05-07 13:03:20 -04003262 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003264 printk(KERN_ERR "SELinux: unable to map context to SID"
3265 "for (%s, %lu), rc=%d\n",
3266 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 return;
3268 }
3269
Paul Moore20cdef82016-04-04 14:14:42 -04003270 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003271 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003272 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003274 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003275 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 return;
3278}
3279
David Howells8f0cfa52008-04-29 00:59:41 -07003280static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281{
David Howells88e67f32008-11-14 10:39:21 +11003282 const struct cred *cred = current_cred();
3283
Eric Paris2875fa02011-04-28 16:04:24 -04003284 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285}
3286
Eric Paris828dfe12008-04-17 13:17:49 -04003287static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288{
David Howells88e67f32008-11-14 10:39:21 +11003289 const struct cred *cred = current_cred();
3290
Eric Paris2875fa02011-04-28 16:04:24 -04003291 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292}
3293
David Howells8f0cfa52008-04-29 00:59:41 -07003294static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003296 if (strcmp(name, XATTR_NAME_SELINUX))
3297 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
3299 /* No one is allowed to remove a SELinux security label.
3300 You can change the label, but all data must be labeled. */
3301 return -EACCES;
3302}
3303
James Morrisd381d8a2005-10-30 14:59:22 -08003304/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003305 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003306 *
3307 * Permission check is handled by selinux_inode_getxattr hook.
3308 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003309static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310{
David P. Quigley42492592008-02-04 22:29:39 -08003311 u32 size;
3312 int error;
3313 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003314 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003316 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3317 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003319 /*
3320 * If the caller has CAP_MAC_ADMIN, then get the raw context
3321 * value even if it is not defined by current policy; otherwise,
3322 * use the in-core value under current policy.
3323 * Use the non-auditing forms of the permission checks since
3324 * getxattr may be called by unprivileged processes commonly
3325 * and lack of permission just means that we fall back to the
3326 * in-core context value, not a denial.
3327 */
Paul Moore20cdef82016-04-04 14:14:42 -04003328 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003329 if (has_cap_mac_admin(false))
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003330 error = security_sid_to_context_force(isec->sid, &context,
3331 &size);
3332 else
3333 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003334 if (error)
3335 return error;
3336 error = size;
3337 if (alloc) {
3338 *buffer = context;
3339 goto out_nofree;
3340 }
3341 kfree(context);
3342out_nofree:
3343 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344}
3345
3346static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003347 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348{
Paul Moore2c971652016-04-19 16:36:28 -04003349 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 u32 newsid;
3351 int rc;
3352
3353 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3354 return -EOPNOTSUPP;
3355
3356 if (!value || !size)
3357 return -EACCES;
3358
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003359 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 if (rc)
3361 return rc;
3362
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003363 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003364 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003366 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003367 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 return 0;
3369}
3370
3371static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3372{
3373 const int len = sizeof(XATTR_NAME_SELINUX);
3374 if (buffer && len <= buffer_size)
3375 memcpy(buffer, XATTR_NAME_SELINUX, len);
3376 return len;
3377}
3378
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003379static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003380{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003381 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003382 *secid = isec->sid;
3383}
3384
Vivek Goyal56909eb2016-07-13 10:44:48 -04003385static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3386{
3387 u32 sid;
3388 struct task_security_struct *tsec;
3389 struct cred *new_creds = *new;
3390
3391 if (new_creds == NULL) {
3392 new_creds = prepare_creds();
3393 if (!new_creds)
3394 return -ENOMEM;
3395 }
3396
3397 tsec = new_creds->security;
3398 /* Get label from overlay inode and set it in create_sid */
3399 selinux_inode_getsecid(d_inode(src), &sid);
3400 tsec->create_sid = sid;
3401 *new = new_creds;
3402 return 0;
3403}
3404
Vivek Goyal19472b62016-07-13 10:44:50 -04003405static int selinux_inode_copy_up_xattr(const char *name)
3406{
3407 /* The copy_up hook above sets the initial context on an inode, but we
3408 * don't then want to overwrite it by blindly copying all the lower
3409 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3410 */
3411 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3412 return 1; /* Discard */
3413 /*
3414 * Any other attribute apart from SELINUX is not claimed, supported
3415 * by selinux.
3416 */
3417 return -EOPNOTSUPP;
3418}
3419
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420/* file security operations */
3421
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003422static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423{
David Howells88e67f32008-11-14 10:39:21 +11003424 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003425 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3428 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3429 mask |= MAY_APPEND;
3430
Paul Moore389fb8002009-03-27 17:10:34 -04003431 return file_has_perm(cred, file,
3432 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433}
3434
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003435static int selinux_file_permission(struct file *file, int mask)
3436{
Al Viro496ad9a2013-01-23 17:07:38 -05003437 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003438 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003439 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003440 u32 sid = current_sid();
3441
Paul Moore389fb8002009-03-27 17:10:34 -04003442 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003443 /* No permission to check. Existence test. */
3444 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003445
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003446 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003447 if (sid == fsec->sid && fsec->isid == isec->sid &&
3448 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003449 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003450 return 0;
3451
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003452 return selinux_revalidate_file_permission(file, mask);
3453}
3454
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455static int selinux_file_alloc_security(struct file *file)
3456{
3457 return file_alloc_security(file);
3458}
3459
3460static void selinux_file_free_security(struct file *file)
3461{
3462 file_free_security(file);
3463}
3464
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003465/*
3466 * Check whether a task has the ioctl permission and cmd
3467 * operation to an inode.
3468 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003469static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003470 u32 requested, u16 cmd)
3471{
3472 struct common_audit_data ad;
3473 struct file_security_struct *fsec = file->f_security;
3474 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003475 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003476 struct lsm_ioctlop_audit ioctl;
3477 u32 ssid = cred_sid(cred);
3478 int rc;
3479 u8 driver = cmd >> 8;
3480 u8 xperm = cmd & 0xff;
3481
3482 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3483 ad.u.op = &ioctl;
3484 ad.u.op->cmd = cmd;
3485 ad.u.op->path = file->f_path;
3486
3487 if (ssid != fsec->sid) {
3488 rc = avc_has_perm(ssid, fsec->sid,
3489 SECCLASS_FD,
3490 FD__USE,
3491 &ad);
3492 if (rc)
3493 goto out;
3494 }
3495
3496 if (unlikely(IS_PRIVATE(inode)))
3497 return 0;
3498
Paul Moore20cdef82016-04-04 14:14:42 -04003499 isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003500 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3501 requested, driver, xperm, &ad);
3502out:
3503 return rc;
3504}
3505
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3507 unsigned long arg)
3508{
David Howells88e67f32008-11-14 10:39:21 +11003509 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003510 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511
Eric Paris0b24dcb2011-02-25 15:39:20 -05003512 switch (cmd) {
3513 case FIONREAD:
3514 /* fall through */
3515 case FIBMAP:
3516 /* fall through */
3517 case FIGETBSZ:
3518 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003519 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003520 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003521 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003522 error = file_has_perm(cred, file, FILE__GETATTR);
3523 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524
Al Viro2f99c362012-03-23 16:04:05 -04003525 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003526 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003527 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003528 error = file_has_perm(cred, file, FILE__SETATTR);
3529 break;
3530
3531 /* sys_ioctl() checks */
3532 case FIONBIO:
3533 /* fall through */
3534 case FIOASYNC:
3535 error = file_has_perm(cred, file, 0);
3536 break;
3537
3538 case KDSKBENT:
3539 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003540 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003541 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003542 break;
3543
3544 /* default case assumes that the command will go
3545 * to the file's ioctl() function.
3546 */
3547 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003548 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003549 }
3550 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551}
3552
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003553static int default_noexec;
3554
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3556{
David Howells88e67f32008-11-14 10:39:21 +11003557 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003558 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003559 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003560
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003561 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003562 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3563 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 /*
3565 * We are making executable an anonymous mapping or a
3566 * private file mapping that will also be writable.
3567 * This has an additional check.
3568 */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003569 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3570 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003572 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574
3575 if (file) {
3576 /* read access is always possible with a mapping */
3577 u32 av = FILE__READ;
3578
3579 /* write access only matters if the mapping is shared */
3580 if (shared && (prot & PROT_WRITE))
3581 av |= FILE__WRITE;
3582
3583 if (prot & PROT_EXEC)
3584 av |= FILE__EXECUTE;
3585
David Howells88e67f32008-11-14 10:39:21 +11003586 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 }
David Howellsd84f4f92008-11-14 10:39:23 +11003588
3589error:
3590 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591}
3592
Al Viroe5467852012-05-30 13:30:51 -04003593static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003595 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003596
3597 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3598 u32 sid = current_sid();
3599 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3600 MEMPROTECT__MMAP_ZERO, NULL);
3601 }
3602
3603 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003604}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605
Al Viroe5467852012-05-30 13:30:51 -04003606static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3607 unsigned long prot, unsigned long flags)
3608{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003609 struct common_audit_data ad;
3610 int rc;
3611
3612 if (file) {
3613 ad.type = LSM_AUDIT_DATA_FILE;
3614 ad.u.file = file;
3615 rc = inode_has_perm(current_cred(), file_inode(file),
3616 FILE__MAP, &ad);
3617 if (rc)
3618 return rc;
3619 }
3620
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 if (selinux_checkreqprot)
3622 prot = reqprot;
3623
3624 return file_map_prot_check(file, prot,
3625 (flags & MAP_TYPE) == MAP_SHARED);
3626}
3627
3628static int selinux_file_mprotect(struct vm_area_struct *vma,
3629 unsigned long reqprot,
3630 unsigned long prot)
3631{
David Howells88e67f32008-11-14 10:39:21 +11003632 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003633 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
3635 if (selinux_checkreqprot)
3636 prot = reqprot;
3637
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003638 if (default_noexec &&
3639 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003640 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003641 if (vma->vm_start >= vma->vm_mm->start_brk &&
3642 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003643 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3644 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003645 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003646 ((vma->vm_start <= vma->vm_mm->start_stack &&
3647 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003648 vma_is_stack_for_current(vma))) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003649 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3650 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003651 } else if (vma->vm_file && vma->anon_vma) {
3652 /*
3653 * We are making executable a file mapping that has
3654 * had some COW done. Since pages might have been
3655 * written, check ability to execute the possibly
3656 * modified content. This typically should only
3657 * occur for text relocations.
3658 */
David Howellsd84f4f92008-11-14 10:39:23 +11003659 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003660 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003661 if (rc)
3662 return rc;
3663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664
3665 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3666}
3667
3668static int selinux_file_lock(struct file *file, unsigned int cmd)
3669{
David Howells88e67f32008-11-14 10:39:21 +11003670 const struct cred *cred = current_cred();
3671
3672 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673}
3674
3675static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3676 unsigned long arg)
3677{
David Howells88e67f32008-11-14 10:39:21 +11003678 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 int err = 0;
3680
3681 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003682 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003683 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003684 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003686 }
3687 /* fall through */
3688 case F_SETOWN:
3689 case F_SETSIG:
3690 case F_GETFL:
3691 case F_GETOWN:
3692 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003693 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003694 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003695 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003696 break;
3697 case F_GETLK:
3698 case F_SETLK:
3699 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003700 case F_OFD_GETLK:
3701 case F_OFD_SETLK:
3702 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003704 case F_GETLK64:
3705 case F_SETLK64:
3706 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707#endif
David Howells88e67f32008-11-14 10:39:21 +11003708 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003709 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 }
3711
3712 return err;
3713}
3714
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003715static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 struct file_security_struct *fsec;
3718
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003720 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721}
3722
3723static int selinux_file_send_sigiotask(struct task_struct *tsk,
3724 struct fown_struct *fown, int signum)
3725{
Eric Paris828dfe12008-04-17 13:17:49 -04003726 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003727 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 struct file_security_struct *fsec;
3730
3731 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003732 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 fsec = file->f_security;
3735
3736 if (!signum)
3737 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3738 else
3739 perm = signal_to_av(signum);
3740
David Howells275bb412008-11-14 10:39:19 +11003741 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 SECCLASS_PROCESS, perm, NULL);
3743}
3744
3745static int selinux_file_receive(struct file *file)
3746{
David Howells88e67f32008-11-14 10:39:21 +11003747 const struct cred *cred = current_cred();
3748
3749 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750}
3751
Eric Paris83d49852012-04-04 13:45:40 -04003752static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003753{
3754 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003755 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003756
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003757 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003758 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003759 /*
3760 * Save inode label and policy sequence number
3761 * at open-time so that selinux_file_permission
3762 * can determine whether revalidation is necessary.
3763 * Task label is already saved in the file security
3764 * struct as its SID.
3765 */
3766 fsec->isid = isec->sid;
3767 fsec->pseqno = avc_policy_seqno();
3768 /*
3769 * Since the inode label or policy seqno may have changed
3770 * between the selinux_inode_permission check and the saving
3771 * of state above, recheck that access is still permitted.
3772 * Otherwise, access might never be revalidated against the
3773 * new inode label or new policy.
3774 * This check is not redundant - do not remove.
3775 */
David Howells13f8e982013-06-13 23:37:55 +01003776 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003777}
3778
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779/* task security operations */
3780
Tetsuo Handaa79be232017-03-28 23:08:45 +09003781static int selinux_task_alloc(struct task_struct *task,
3782 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003784 u32 sid = current_sid();
3785
3786 return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787}
3788
David Howellsf1752ee2008-11-14 10:39:17 +11003789/*
David Howellsee18d642009-09-02 09:14:21 +01003790 * allocate the SELinux part of blank credentials
3791 */
3792static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3793{
3794 struct task_security_struct *tsec;
3795
3796 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3797 if (!tsec)
3798 return -ENOMEM;
3799
3800 cred->security = tsec;
3801 return 0;
3802}
3803
3804/*
David Howellsf1752ee2008-11-14 10:39:17 +11003805 * detach and free the LSM part of a set of credentials
3806 */
3807static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808{
David Howellsf1752ee2008-11-14 10:39:17 +11003809 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003810
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003811 /*
3812 * cred->security == NULL if security_cred_alloc_blank() or
3813 * security_prepare_creds() returned an error.
3814 */
3815 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003816 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003817 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818}
3819
David Howellsd84f4f92008-11-14 10:39:23 +11003820/*
3821 * prepare a new set of credentials for modification
3822 */
3823static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3824 gfp_t gfp)
3825{
3826 const struct task_security_struct *old_tsec;
3827 struct task_security_struct *tsec;
3828
3829 old_tsec = old->security;
3830
3831 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3832 if (!tsec)
3833 return -ENOMEM;
3834
3835 new->security = tsec;
3836 return 0;
3837}
3838
3839/*
David Howellsee18d642009-09-02 09:14:21 +01003840 * transfer the SELinux data to a blank set of creds
3841 */
3842static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3843{
3844 const struct task_security_struct *old_tsec = old->security;
3845 struct task_security_struct *tsec = new->security;
3846
3847 *tsec = *old_tsec;
3848}
3849
3850/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003851 * set the security data for a kernel service
3852 * - all the creation contexts are set to unlabelled
3853 */
3854static int selinux_kernel_act_as(struct cred *new, u32 secid)
3855{
3856 struct task_security_struct *tsec = new->security;
3857 u32 sid = current_sid();
3858 int ret;
3859
3860 ret = avc_has_perm(sid, secid,
3861 SECCLASS_KERNEL_SERVICE,
3862 KERNEL_SERVICE__USE_AS_OVERRIDE,
3863 NULL);
3864 if (ret == 0) {
3865 tsec->sid = secid;
3866 tsec->create_sid = 0;
3867 tsec->keycreate_sid = 0;
3868 tsec->sockcreate_sid = 0;
3869 }
3870 return ret;
3871}
3872
3873/*
3874 * set the file creation context in a security record to the same as the
3875 * objective context of the specified inode
3876 */
3877static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3878{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003879 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003880 struct task_security_struct *tsec = new->security;
3881 u32 sid = current_sid();
3882 int ret;
3883
3884 ret = avc_has_perm(sid, isec->sid,
3885 SECCLASS_KERNEL_SERVICE,
3886 KERNEL_SERVICE__CREATE_FILES_AS,
3887 NULL);
3888
3889 if (ret == 0)
3890 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003891 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003892}
3893
Eric Parisdd8dbf22009-11-03 16:35:32 +11003894static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003895{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003896 struct common_audit_data ad;
3897
Eric Paris50c205f2012-04-04 15:01:43 -04003898 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003899 ad.u.kmod_name = kmod_name;
3900
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003901 return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11003902 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003903}
3904
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003905static int selinux_kernel_module_from_file(struct file *file)
3906{
3907 struct common_audit_data ad;
3908 struct inode_security_struct *isec;
3909 struct file_security_struct *fsec;
3910 u32 sid = current_sid();
3911 int rc;
3912
3913 /* init_module */
3914 if (file == NULL)
3915 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
3916 SYSTEM__MODULE_LOAD, NULL);
3917
3918 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003919
Vivek Goyal43af5de2016-09-09 11:37:49 -04003920 ad.type = LSM_AUDIT_DATA_FILE;
3921 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003922
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003923 fsec = file->f_security;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003924 if (sid != fsec->sid) {
3925 rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
3926 if (rc)
3927 return rc;
3928 }
3929
Paul Moore20cdef82016-04-04 14:14:42 -04003930 isec = inode_security(file_inode(file));
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003931 return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
3932 SYSTEM__MODULE_LOAD, &ad);
3933}
3934
3935static int selinux_kernel_read_file(struct file *file,
3936 enum kernel_read_file_id id)
3937{
3938 int rc = 0;
3939
3940 switch (id) {
3941 case READING_MODULE:
3942 rc = selinux_kernel_module_from_file(file);
3943 break;
3944 default:
3945 break;
3946 }
3947
3948 return rc;
3949}
3950
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3952{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003953 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3954 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955}
3956
3957static int selinux_task_getpgid(struct task_struct *p)
3958{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003959 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3960 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961}
3962
3963static int selinux_task_getsid(struct task_struct *p)
3964{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003965 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3966 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967}
3968
David Quigleyf9008e4c2006-06-30 01:55:46 -07003969static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3970{
David Howells275bb412008-11-14 10:39:19 +11003971 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003972}
3973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974static int selinux_task_setnice(struct task_struct *p, int nice)
3975{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003976 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3977 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978}
3979
James Morris03e68062006-06-23 02:03:58 -07003980static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3981{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003982 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3983 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07003984}
3985
David Quigleya1836a42006-06-30 01:55:49 -07003986static int selinux_task_getioprio(struct task_struct *p)
3987{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003988 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3989 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07003990}
3991
Stephen Smalley791ec492017-02-17 07:57:00 -05003992int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
3993 unsigned int flags)
3994{
3995 u32 av = 0;
3996
Stephen Smalley84e68852017-02-28 09:35:08 -05003997 if (!flags)
3998 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05003999 if (flags & LSM_PRLIMIT_WRITE)
4000 av |= PROCESS__SETRLIMIT;
4001 if (flags & LSM_PRLIMIT_READ)
4002 av |= PROCESS__GETRLIMIT;
4003 return avc_has_perm(cred_sid(cred), cred_sid(tcred),
4004 SECCLASS_PROCESS, av, NULL);
4005}
4006
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004007static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
4008 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02004010 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
4012 /* Control the ability to change the hard limit (whether
4013 lowering or raising it), so that the hard limit can
4014 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11004015 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004017 return avc_has_perm(current_sid(), task_sid(p),
4018 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020 return 0;
4021}
4022
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09004023static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004025 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
4026 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027}
4028
4029static int selinux_task_getscheduler(struct task_struct *p)
4030{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004031 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
4032 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033}
4034
David Quigley35601542006-06-23 02:04:01 -07004035static int selinux_task_movememory(struct task_struct *p)
4036{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004037 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
4038 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07004039}
4040
David Quigleyf9008e4c2006-06-30 01:55:46 -07004041static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
4042 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 if (!sig)
4047 perm = PROCESS__SIGNULL; /* null signal; existence test */
4048 else
4049 perm = signal_to_av(sig);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004050 if (!secid)
4051 secid = current_sid();
4052 return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053}
4054
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055static void selinux_task_to_inode(struct task_struct *p,
4056 struct inode *inode)
4057{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11004059 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004061 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004062 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004063 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004064 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004065 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066}
4067
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004069static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004070 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071{
4072 int offset, ihlen, ret = -EINVAL;
4073 struct iphdr _iph, *ih;
4074
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004075 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4077 if (ih == NULL)
4078 goto out;
4079
4080 ihlen = ih->ihl * 4;
4081 if (ihlen < sizeof(_iph))
4082 goto out;
4083
Eric Paris48c62af2012-04-02 13:15:44 -04004084 ad->u.net->v4info.saddr = ih->saddr;
4085 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 ret = 0;
4087
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004088 if (proto)
4089 *proto = ih->protocol;
4090
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004092 case IPPROTO_TCP: {
4093 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Eric Paris828dfe12008-04-17 13:17:49 -04004095 if (ntohs(ih->frag_off) & IP_OFFSET)
4096 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
4098 offset += ihlen;
4099 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4100 if (th == NULL)
4101 break;
4102
Eric Paris48c62af2012-04-02 13:15:44 -04004103 ad->u.net->sport = th->source;
4104 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Eric Paris828dfe12008-04-17 13:17:49 -04004108 case IPPROTO_UDP: {
4109 struct udphdr _udph, *uh;
4110
4111 if (ntohs(ih->frag_off) & IP_OFFSET)
4112 break;
4113
4114 offset += ihlen;
4115 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4116 if (uh == NULL)
4117 break;
4118
Eric Paris48c62af2012-04-02 13:15:44 -04004119 ad->u.net->sport = uh->source;
4120 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004121 break;
4122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
James Morris2ee92d42006-11-13 16:09:01 -08004124 case IPPROTO_DCCP: {
4125 struct dccp_hdr _dccph, *dh;
4126
4127 if (ntohs(ih->frag_off) & IP_OFFSET)
4128 break;
4129
4130 offset += ihlen;
4131 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4132 if (dh == NULL)
4133 break;
4134
Eric Paris48c62af2012-04-02 13:15:44 -04004135 ad->u.net->sport = dh->dccph_sport;
4136 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004137 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004138 }
James Morris2ee92d42006-11-13 16:09:01 -08004139
Eric Paris828dfe12008-04-17 13:17:49 -04004140 default:
4141 break;
4142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143out:
4144 return ret;
4145}
4146
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004147#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
4149/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004150static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004151 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152{
4153 u8 nexthdr;
4154 int ret = -EINVAL, offset;
4155 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004156 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004158 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4160 if (ip6 == NULL)
4161 goto out;
4162
Eric Paris48c62af2012-04-02 13:15:44 -04004163 ad->u.net->v6info.saddr = ip6->saddr;
4164 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 ret = 0;
4166
4167 nexthdr = ip6->nexthdr;
4168 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004169 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 if (offset < 0)
4171 goto out;
4172
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004173 if (proto)
4174 *proto = nexthdr;
4175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 switch (nexthdr) {
4177 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004178 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
4180 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4181 if (th == NULL)
4182 break;
4183
Eric Paris48c62af2012-04-02 13:15:44 -04004184 ad->u.net->sport = th->source;
4185 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 break;
4187 }
4188
4189 case IPPROTO_UDP: {
4190 struct udphdr _udph, *uh;
4191
4192 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4193 if (uh == NULL)
4194 break;
4195
Eric Paris48c62af2012-04-02 13:15:44 -04004196 ad->u.net->sport = uh->source;
4197 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 break;
4199 }
4200
James Morris2ee92d42006-11-13 16:09:01 -08004201 case IPPROTO_DCCP: {
4202 struct dccp_hdr _dccph, *dh;
4203
4204 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4205 if (dh == NULL)
4206 break;
4207
Eric Paris48c62af2012-04-02 13:15:44 -04004208 ad->u.net->sport = dh->dccph_sport;
4209 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004210 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004211 }
James Morris2ee92d42006-11-13 16:09:01 -08004212
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 /* includes fragments */
4214 default:
4215 break;
4216 }
4217out:
4218 return ret;
4219}
4220
4221#endif /* IPV6 */
4222
Thomas Liu2bf49692009-07-14 12:14:09 -04004223static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004224 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225{
David Howellscf9481e2008-07-27 21:31:07 +10004226 char *addrp;
4227 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Eric Paris48c62af2012-04-02 13:15:44 -04004229 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004231 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004232 if (ret)
4233 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004234 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4235 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004236 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004238#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004240 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004241 if (ret)
4242 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004243 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4244 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004245 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246#endif /* IPV6 */
4247 default:
David Howellscf9481e2008-07-27 21:31:07 +10004248 addrp = NULL;
4249 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 }
4251
David Howellscf9481e2008-07-27 21:31:07 +10004252parse_error:
4253 printk(KERN_WARNING
4254 "SELinux: failure in selinux_parse_skb(),"
4255 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004257
4258okay:
4259 if (_addrp)
4260 *_addrp = addrp;
4261 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262}
4263
Paul Moore4f6a9932007-03-01 14:35:22 -05004264/**
Paul Moore220deb92008-01-29 08:38:23 -05004265 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004266 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004267 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004268 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004269 *
4270 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004271 * Check the various different forms of network peer labeling and determine
4272 * the peer label/SID for the packet; most of the magic actually occurs in
4273 * the security server function security_net_peersid_cmp(). The function
4274 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4275 * or -EACCES if @sid is invalid due to inconsistencies with the different
4276 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004277 *
4278 */
Paul Moore220deb92008-01-29 08:38:23 -05004279static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004280{
Paul Moore71f1cb02008-01-29 08:51:16 -05004281 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004282 u32 xfrm_sid;
4283 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004284 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004285
Paul Moore817eff72013-12-10 14:57:54 -05004286 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004287 if (unlikely(err))
4288 return -EACCES;
4289 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4290 if (unlikely(err))
4291 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004292
Paul Moore71f1cb02008-01-29 08:51:16 -05004293 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
4294 if (unlikely(err)) {
4295 printk(KERN_WARNING
4296 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4297 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004298 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004299 }
Paul Moore220deb92008-01-29 08:38:23 -05004300
4301 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004302}
4303
Paul Moore446b8022013-12-04 16:10:51 -05004304/**
4305 * selinux_conn_sid - Determine the child socket label for a connection
4306 * @sk_sid: the parent socket's SID
4307 * @skb_sid: the packet's SID
4308 * @conn_sid: the resulting connection SID
4309 *
4310 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4311 * combined with the MLS information from @skb_sid in order to create
4312 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4313 * of @sk_sid. Returns zero on success, negative values on failure.
4314 *
4315 */
4316static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4317{
4318 int err = 0;
4319
4320 if (skb_sid != SECSID_NULL)
4321 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4322 else
4323 *conn_sid = sk_sid;
4324
4325 return err;
4326}
4327
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004329
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004330static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4331 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004332{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004333 if (tsec->sockcreate_sid > SECSID_NULL) {
4334 *socksid = tsec->sockcreate_sid;
4335 return 0;
4336 }
4337
4338 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4339 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004340}
4341
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004342static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343{
Paul Moore253bfae2010-04-22 14:46:19 -04004344 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004345 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004346 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Paul Moore253bfae2010-04-22 14:46:19 -04004348 if (sksec->sid == SECINITSID_KERNEL)
4349 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Eric Paris50c205f2012-04-04 15:01:43 -04004351 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004352 ad.u.net = &net;
4353 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004355 return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
4356 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357}
4358
4359static int selinux_socket_create(int family, int type,
4360 int protocol, int kern)
4361{
Paul Moore5fb49872010-04-22 14:46:19 -04004362 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004363 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004364 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004365 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
4367 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004368 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
David Howells275bb412008-11-14 10:39:19 +11004370 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004371 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4372 if (rc)
4373 return rc;
4374
Paul Moored4f2d972010-04-22 14:46:18 -04004375 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376}
4377
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004378static int selinux_socket_post_create(struct socket *sock, int family,
4379 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380{
Paul Moore5fb49872010-04-22 14:46:19 -04004381 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004382 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004383 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004384 u16 sclass = socket_type_to_security_class(family, type, protocol);
4385 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004386 int err = 0;
4387
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004388 if (!kern) {
4389 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004390 if (err)
4391 return err;
4392 }
David Howells275bb412008-11-14 10:39:19 +11004393
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004394 isec->sclass = sclass;
4395 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004396 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004398 if (sock->sk) {
4399 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004400 sksec->sclass = sclass;
4401 sksec->sid = sid;
Paul Moore389fb8002009-03-27 17:10:34 -04004402 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004403 }
4404
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004405 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406}
4407
4408/* Range of port numbers used to automatically bind.
4409 Need to determine whether we should perform a name_bind
4410 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411
4412static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4413{
Paul Moore253bfae2010-04-22 14:46:19 -04004414 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 u16 family;
4416 int err;
4417
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004418 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 if (err)
4420 goto out;
4421
4422 /*
4423 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004424 * Multiple address binding for SCTP is not supported yet: we just
4425 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 */
Paul Moore253bfae2010-04-22 14:46:19 -04004427 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 if (family == PF_INET || family == PF_INET6) {
4429 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004430 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004431 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004432 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 struct sockaddr_in *addr4 = NULL;
4434 struct sockaddr_in6 *addr6 = NULL;
4435 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004436 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 if (family == PF_INET) {
Alexander Potapenkoe2f586b2017-03-06 19:46:14 +01004439 if (addrlen < sizeof(struct sockaddr_in)) {
4440 err = -EINVAL;
4441 goto out;
4442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 addr4 = (struct sockaddr_in *)address;
4444 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 addrp = (char *)&addr4->sin_addr.s_addr;
4446 } else {
Alexander Potapenkoe2f586b2017-03-06 19:46:14 +01004447 if (addrlen < SIN6_LEN_RFC2133) {
4448 err = -EINVAL;
4449 goto out;
4450 }
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;
4454 }
4455
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004456 if (snum) {
4457 int low, high;
4458
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004459 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004460
Krister Johansen4548b682017-01-20 17:49:11 -08004461 if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
4462 snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004463 err = sel_netport_sid(sk->sk_protocol,
4464 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004465 if (err)
4466 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004467 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004468 ad.u.net = &net;
4469 ad.u.net->sport = htons(snum);
4470 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004471 err = avc_has_perm(sksec->sid, sid,
4472 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004473 SOCKET__NAME_BIND, &ad);
4474 if (err)
4475 goto out;
4476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 }
Eric Paris828dfe12008-04-17 13:17:49 -04004478
Paul Moore253bfae2010-04-22 14:46:19 -04004479 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004480 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 node_perm = TCP_SOCKET__NODE_BIND;
4482 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004483
James Morris13402582005-09-30 14:24:34 -04004484 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 node_perm = UDP_SOCKET__NODE_BIND;
4486 break;
James Morris2ee92d42006-11-13 16:09:01 -08004487
4488 case SECCLASS_DCCP_SOCKET:
4489 node_perm = DCCP_SOCKET__NODE_BIND;
4490 break;
4491
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 default:
4493 node_perm = RAWIP_SOCKET__NODE_BIND;
4494 break;
4495 }
Eric Paris828dfe12008-04-17 13:17:49 -04004496
Paul Moore224dfbd2008-01-29 08:38:13 -05004497 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 if (err)
4499 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004500
Eric Paris50c205f2012-04-04 15:01:43 -04004501 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004502 ad.u.net = &net;
4503 ad.u.net->sport = htons(snum);
4504 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
4506 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004507 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 else
Eric Paris48c62af2012-04-02 13:15:44 -04004509 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
Paul Moore253bfae2010-04-22 14:46:19 -04004511 err = avc_has_perm(sksec->sid, sid,
4512 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 if (err)
4514 goto out;
4515 }
4516out:
4517 return err;
4518}
4519
4520static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4521{
Paul Moore014ab192008-10-10 10:16:33 -04004522 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004523 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 int err;
4525
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004526 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 if (err)
4528 return err;
4529
4530 /*
James Morris2ee92d42006-11-13 16:09:01 -08004531 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 */
Paul Moore253bfae2010-04-22 14:46:19 -04004533 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4534 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004535 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004536 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 struct sockaddr_in *addr4 = NULL;
4538 struct sockaddr_in6 *addr6 = NULL;
4539 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004540 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541
4542 if (sk->sk_family == PF_INET) {
4543 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004544 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 return -EINVAL;
4546 snum = ntohs(addr4->sin_port);
4547 } else {
4548 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004549 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 return -EINVAL;
4551 snum = ntohs(addr6->sin6_port);
4552 }
4553
Paul Moore3e1121722008-04-10 10:48:14 -04004554 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 if (err)
4556 goto out;
4557
Paul Moore253bfae2010-04-22 14:46:19 -04004558 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004559 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4560
Eric Paris50c205f2012-04-04 15:01:43 -04004561 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004562 ad.u.net = &net;
4563 ad.u.net->dport = htons(snum);
4564 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004565 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 if (err)
4567 goto out;
4568 }
4569
Paul Moore014ab192008-10-10 10:16:33 -04004570 err = selinux_netlbl_socket_connect(sk, address);
4571
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572out:
4573 return err;
4574}
4575
4576static int selinux_socket_listen(struct socket *sock, int backlog)
4577{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004578 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579}
4580
4581static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4582{
4583 int err;
4584 struct inode_security_struct *isec;
4585 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004586 u16 sclass;
4587 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004589 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 if (err)
4591 return err;
4592
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004593 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004594 spin_lock(&isec->lock);
4595 sclass = isec->sclass;
4596 sid = isec->sid;
4597 spin_unlock(&isec->lock);
4598
4599 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4600 newisec->sclass = sclass;
4601 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004602 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603
4604 return 0;
4605}
4606
4607static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004608 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004610 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611}
4612
4613static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4614 int size, int flags)
4615{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004616 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617}
4618
4619static int selinux_socket_getsockname(struct socket *sock)
4620{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004621 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622}
4623
4624static int selinux_socket_getpeername(struct socket *sock)
4625{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004626 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627}
4628
Eric Paris828dfe12008-04-17 13:17:49 -04004629static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630{
Paul Mooref8687af2006-10-30 15:22:15 -08004631 int err;
4632
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004633 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004634 if (err)
4635 return err;
4636
4637 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638}
4639
4640static int selinux_socket_getsockopt(struct socket *sock, int level,
4641 int optname)
4642{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004643 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644}
4645
4646static int selinux_socket_shutdown(struct socket *sock, int how)
4647{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004648 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649}
4650
David S. Miller3610cda2011-01-05 15:38:53 -08004651static int selinux_socket_unix_stream_connect(struct sock *sock,
4652 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653 struct sock *newsk)
4654{
David S. Miller3610cda2011-01-05 15:38:53 -08004655 struct sk_security_struct *sksec_sock = sock->sk_security;
4656 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004657 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004658 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004659 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 int err;
4661
Eric Paris50c205f2012-04-04 15:01:43 -04004662 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004663 ad.u.net = &net;
4664 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665
Paul Moore4d1e2452010-04-22 14:46:18 -04004666 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4667 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4669 if (err)
4670 return err;
4671
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004673 sksec_new->peer_sid = sksec_sock->sid;
4674 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4675 &sksec_new->sid);
4676 if (err)
4677 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004678
Paul Moore4d1e2452010-04-22 14:46:18 -04004679 /* connecting socket */
4680 sksec_sock->peer_sid = sksec_new->sid;
4681
4682 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683}
4684
4685static int selinux_socket_unix_may_send(struct socket *sock,
4686 struct socket *other)
4687{
Paul Moore253bfae2010-04-22 14:46:19 -04004688 struct sk_security_struct *ssec = sock->sk->sk_security;
4689 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004690 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004691 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692
Eric Paris50c205f2012-04-04 15:01:43 -04004693 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004694 ad.u.net = &net;
4695 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
Paul Moore253bfae2010-04-22 14:46:19 -04004697 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4698 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699}
4700
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004701static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4702 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004703 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004704{
4705 int err;
4706 u32 if_sid;
4707 u32 node_sid;
4708
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004709 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004710 if (err)
4711 return err;
4712 err = avc_has_perm(peer_sid, if_sid,
4713 SECCLASS_NETIF, NETIF__INGRESS, ad);
4714 if (err)
4715 return err;
4716
4717 err = sel_netnode_sid(addrp, family, &node_sid);
4718 if (err)
4719 return err;
4720 return avc_has_perm(peer_sid, node_sid,
4721 SECCLASS_NODE, NODE__RECVFROM, ad);
4722}
4723
Paul Moore220deb92008-01-29 08:38:23 -05004724static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004725 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004726{
Paul Moore277d3422008-12-31 12:54:11 -05004727 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004728 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004729 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004730 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004731 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004732 char *addrp;
4733
Eric Paris50c205f2012-04-04 15:01:43 -04004734 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004735 ad.u.net = &net;
4736 ad.u.net->netif = skb->skb_iif;
4737 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004738 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4739 if (err)
4740 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004741
Paul Moore58bfbb52009-03-27 17:10:41 -04004742 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004743 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004744 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004745 if (err)
4746 return err;
4747 }
Paul Moore220deb92008-01-29 08:38:23 -05004748
Steffen Klassertb9679a72011-02-23 12:55:21 +01004749 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4750 if (err)
4751 return err;
4752 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004753
James Morris4e5ab4c2006-06-09 00:33:33 -07004754 return err;
4755}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004756
James Morris4e5ab4c2006-06-09 00:33:33 -07004757static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4758{
Paul Moore220deb92008-01-29 08:38:23 -05004759 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004760 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004761 u16 family = sk->sk_family;
4762 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004763 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004764 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004765 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004766 u8 secmark_active;
4767 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004768
James Morris4e5ab4c2006-06-09 00:33:33 -07004769 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004770 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004771
4772 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004773 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004774 family = PF_INET;
4775
Paul Moored8395c82008-10-10 10:16:30 -04004776 /* If any sort of compatibility mode is enabled then handoff processing
4777 * to the selinux_sock_rcv_skb_compat() function to deal with the
4778 * special handling. We do this in an attempt to keep this function
4779 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004780 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004781 return selinux_sock_rcv_skb_compat(sk, skb, family);
4782
4783 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004784 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004785 if (!secmark_active && !peerlbl_active)
4786 return 0;
4787
Eric Paris50c205f2012-04-04 15:01:43 -04004788 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004789 ad.u.net = &net;
4790 ad.u.net->netif = skb->skb_iif;
4791 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004792 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004793 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004794 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004795
Paul Moored8395c82008-10-10 10:16:30 -04004796 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004797 u32 peer_sid;
4798
4799 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4800 if (err)
4801 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004802 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4803 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004804 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004805 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004806 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004807 }
Paul Moored621d352008-01-29 08:43:36 -05004808 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4809 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004810 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004811 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004812 return err;
4813 }
Paul Moored621d352008-01-29 08:43:36 -05004814 }
4815
Paul Moored8395c82008-10-10 10:16:30 -04004816 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004817 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4818 PACKET__RECV, &ad);
4819 if (err)
4820 return err;
4821 }
4822
Paul Moored621d352008-01-29 08:43:36 -05004823 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824}
4825
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004826static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4827 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828{
4829 int err = 0;
4830 char *scontext;
4831 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004832 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004833 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834
Paul Moore253bfae2010-04-22 14:46:19 -04004835 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4836 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004837 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004838 if (peer_sid == SECSID_NULL)
4839 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004841 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004843 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844
4845 if (scontext_len > len) {
4846 err = -ERANGE;
4847 goto out_len;
4848 }
4849
4850 if (copy_to_user(optval, scontext, scontext_len))
4851 err = -EFAULT;
4852
4853out_len:
4854 if (put_user(scontext_len, optlen))
4855 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857 return err;
4858}
4859
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004860static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004861{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004862 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004863 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004864 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004865
Paul Mooreaa862902008-10-10 10:16:29 -04004866 if (skb && skb->protocol == htons(ETH_P_IP))
4867 family = PF_INET;
4868 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4869 family = PF_INET6;
4870 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004871 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004872 else
4873 goto out;
4874
Paul Moore899134f2016-03-28 15:19:10 -04004875 if (sock && family == PF_UNIX) {
4876 isec = inode_security_novalidate(SOCK_INODE(sock));
4877 peer_secid = isec->sid;
4878 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004879 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004880
Paul Moore75e22912008-01-29 08:38:04 -05004881out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004882 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004883 if (peer_secid == SECSID_NULL)
4884 return -EINVAL;
4885 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004886}
4887
Al Viro7d877f32005-10-21 03:20:43 -04004888static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889{
Paul Moore84914b72010-04-22 14:46:18 -04004890 struct sk_security_struct *sksec;
4891
4892 sksec = kzalloc(sizeof(*sksec), priority);
4893 if (!sksec)
4894 return -ENOMEM;
4895
4896 sksec->peer_sid = SECINITSID_UNLABELED;
4897 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004898 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004899 selinux_netlbl_sk_security_reset(sksec);
4900 sk->sk_security = sksec;
4901
4902 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903}
4904
4905static void selinux_sk_free_security(struct sock *sk)
4906{
Paul Moore84914b72010-04-22 14:46:18 -04004907 struct sk_security_struct *sksec = sk->sk_security;
4908
4909 sk->sk_security = NULL;
4910 selinux_netlbl_sk_security_free(sksec);
4911 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912}
4913
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004914static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4915{
Eric Parisdd3e7832010-04-07 15:08:46 -04004916 struct sk_security_struct *sksec = sk->sk_security;
4917 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004918
Eric Parisdd3e7832010-04-07 15:08:46 -04004919 newsksec->sid = sksec->sid;
4920 newsksec->peer_sid = sksec->peer_sid;
4921 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004922
Eric Parisdd3e7832010-04-07 15:08:46 -04004923 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004924}
4925
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004926static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004927{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004928 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004929 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004930 else {
4931 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004932
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004933 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004934 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004935}
4936
Eric Paris828dfe12008-04-17 13:17:49 -04004937static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004938{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004939 struct inode_security_struct *isec =
4940 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004941 struct sk_security_struct *sksec = sk->sk_security;
4942
Paul Moore2873ead2014-07-28 10:42:48 -04004943 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4944 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004945 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004946 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004947}
4948
Adrian Bunk9a673e52006-08-15 00:03:53 -07004949static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4950 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004951{
4952 struct sk_security_struct *sksec = sk->sk_security;
4953 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004954 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004955 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004956 u32 peersid;
4957
Paul Mooreaa862902008-10-10 10:16:29 -04004958 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004959 if (err)
4960 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004961 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4962 if (err)
4963 return err;
4964 req->secid = connsid;
4965 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004966
Paul Moore389fb8002009-03-27 17:10:34 -04004967 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004968}
4969
Adrian Bunk9a673e52006-08-15 00:03:53 -07004970static void selinux_inet_csk_clone(struct sock *newsk,
4971 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004972{
4973 struct sk_security_struct *newsksec = newsk->sk_security;
4974
4975 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004976 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004977 /* NOTE: Ideally, we should also get the isec->sid for the
4978 new socket in sync, but we don't have the isec available yet.
4979 So we will wait until sock_graft to do it, by which
4980 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004981
Paul Moore9f2ad662006-11-17 17:38:53 -05004982 /* We don't need to take any sort of lock here as we are the only
4983 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004984 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004985}
4986
Paul Moore014ab192008-10-10 10:16:33 -04004987static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004988{
Paul Mooreaa862902008-10-10 10:16:29 -04004989 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004990 struct sk_security_struct *sksec = sk->sk_security;
4991
Paul Mooreaa862902008-10-10 10:16:29 -04004992 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4993 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4994 family = PF_INET;
4995
4996 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004997}
4998
Eric Paris2606fd12010-10-13 16:24:41 -04004999static int selinux_secmark_relabel_packet(u32 sid)
5000{
5001 const struct task_security_struct *__tsec;
5002 u32 tsid;
5003
5004 __tsec = current_security();
5005 tsid = __tsec->sid;
5006
5007 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
5008}
5009
5010static void selinux_secmark_refcount_inc(void)
5011{
5012 atomic_inc(&selinux_secmark_refcount);
5013}
5014
5015static void selinux_secmark_refcount_dec(void)
5016{
5017 atomic_dec(&selinux_secmark_refcount);
5018}
5019
Adrian Bunk9a673e52006-08-15 00:03:53 -07005020static void selinux_req_classify_flow(const struct request_sock *req,
5021 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005022{
David S. Miller1d28f422011-03-12 00:29:39 -05005023 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005024}
5025
Paul Moore5dbbaf22013-01-14 07:12:19 +00005026static int selinux_tun_dev_alloc_security(void **security)
5027{
5028 struct tun_security_struct *tunsec;
5029
5030 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
5031 if (!tunsec)
5032 return -ENOMEM;
5033 tunsec->sid = current_sid();
5034
5035 *security = tunsec;
5036 return 0;
5037}
5038
5039static void selinux_tun_dev_free_security(void *security)
5040{
5041 kfree(security);
5042}
5043
Paul Mooreed6d76e2009-08-28 18:12:49 -04005044static int selinux_tun_dev_create(void)
5045{
5046 u32 sid = current_sid();
5047
5048 /* we aren't taking into account the "sockcreate" SID since the socket
5049 * that is being created here is not a socket in the traditional sense,
5050 * instead it is a private sock, accessible only to the kernel, and
5051 * representing a wide range of network traffic spanning multiple
5052 * connections unlike traditional sockets - check the TUN driver to
5053 * get a better understanding of why this socket is special */
5054
5055 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
5056 NULL);
5057}
5058
Paul Moore5dbbaf22013-01-14 07:12:19 +00005059static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005060{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005061 struct tun_security_struct *tunsec = security;
5062
5063 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
5064 TUN_SOCKET__ATTACH_QUEUE, NULL);
5065}
5066
5067static int selinux_tun_dev_attach(struct sock *sk, void *security)
5068{
5069 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005070 struct sk_security_struct *sksec = sk->sk_security;
5071
5072 /* we don't currently perform any NetLabel based labeling here and it
5073 * isn't clear that we would want to do so anyway; while we could apply
5074 * labeling without the support of the TUN user the resulting labeled
5075 * traffic from the other end of the connection would almost certainly
5076 * cause confusion to the TUN user that had no idea network labeling
5077 * protocols were being used */
5078
Paul Moore5dbbaf22013-01-14 07:12:19 +00005079 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005080 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005081
5082 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005083}
5084
Paul Moore5dbbaf22013-01-14 07:12:19 +00005085static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005086{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005087 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005088 u32 sid = current_sid();
5089 int err;
5090
Paul Moore5dbbaf22013-01-14 07:12:19 +00005091 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005092 TUN_SOCKET__RELABELFROM, NULL);
5093 if (err)
5094 return err;
5095 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
5096 TUN_SOCKET__RELABELTO, NULL);
5097 if (err)
5098 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005099 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005100
5101 return 0;
5102}
5103
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
5105{
5106 int err = 0;
5107 u32 perm;
5108 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005109 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005110
Hong zhi guo77954982013-03-27 06:49:35 +00005111 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 err = -EINVAL;
5113 goto out;
5114 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005115 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005116
Paul Moore253bfae2010-04-22 14:46:19 -04005117 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 if (err) {
5119 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005120 pr_warn_ratelimited("SELinux: unrecognized netlink"
5121 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5122 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005123 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005124 secclass_map[sksec->sclass - 1].name,
5125 task_pid_nr(current), current->comm);
Eric Paris39c9aed2008-11-05 09:34:42 -05005126 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 err = 0;
5128 }
5129
5130 /* Ignore */
5131 if (err == -ENOENT)
5132 err = 0;
5133 goto out;
5134 }
5135
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005136 err = sock_has_perm(sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137out:
5138 return err;
5139}
5140
5141#ifdef CONFIG_NETFILTER
5142
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005143static unsigned int selinux_ip_forward(struct sk_buff *skb,
5144 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005145 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146{
Paul Mooredfaebe92008-10-10 10:16:31 -04005147 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005148 char *addrp;
5149 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005150 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005151 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005152 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005153 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005154 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005155
Paul Mooreeffad8d2008-01-29 08:49:27 -05005156 if (!selinux_policycap_netpeer)
5157 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005158
Paul Mooreeffad8d2008-01-29 08:49:27 -05005159 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005160 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005161 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005162 if (!secmark_active && !peerlbl_active)
5163 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005164
Paul Moored8395c82008-10-10 10:16:30 -04005165 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5166 return NF_DROP;
5167
Eric Paris50c205f2012-04-04 15:01:43 -04005168 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005169 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005170 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005171 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005172 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5173 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174
Paul Mooredfaebe92008-10-10 10:16:31 -04005175 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005176 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5177 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005178 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005179 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005180 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005181 }
5182 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005183
5184 if (secmark_active)
5185 if (avc_has_perm(peer_sid, skb->secmark,
5186 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5187 return NF_DROP;
5188
Paul Moore948bf852008-10-10 10:16:32 -04005189 if (netlbl_active)
5190 /* we do this in the FORWARD path and not the POST_ROUTING
5191 * path because we want to make sure we apply the necessary
5192 * labeling before IPsec is applied so we can leverage AH
5193 * protection */
5194 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5195 return NF_DROP;
5196
Paul Mooreeffad8d2008-01-29 08:49:27 -05005197 return NF_ACCEPT;
5198}
5199
Eric W. Biederman06198b32015-09-18 14:33:06 -05005200static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005201 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005202 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005203{
David S. Miller238e54c2015-04-03 20:32:56 -04005204 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005205}
5206
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005207#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005208static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005209 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005210 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005211{
David S. Miller238e54c2015-04-03 20:32:56 -04005212 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005213}
5214#endif /* IPV6 */
5215
Paul Moore948bf852008-10-10 10:16:32 -04005216static unsigned int selinux_ip_output(struct sk_buff *skb,
5217 u16 family)
5218{
Paul Moore47180062013-12-04 16:10:45 -05005219 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005220 u32 sid;
5221
5222 if (!netlbl_enabled())
5223 return NF_ACCEPT;
5224
5225 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5226 * because we want to make sure we apply the necessary labeling
5227 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005228 sk = skb->sk;
5229 if (sk) {
5230 struct sk_security_struct *sksec;
5231
Eric Dumazete446f9d2015-10-08 05:01:55 -07005232 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005233 /* if the socket is the listening state then this
5234 * packet is a SYN-ACK packet which means it needs to
5235 * be labeled based on the connection/request_sock and
5236 * not the parent socket. unfortunately, we can't
5237 * lookup the request_sock yet as it isn't queued on
5238 * the parent socket until after the SYN-ACK is sent.
5239 * the "solution" is to simply pass the packet as-is
5240 * as any IP option based labeling should be copied
5241 * from the initial connection request (in the IP
5242 * layer). it is far from ideal, but until we get a
5243 * security label in the packet itself this is the
5244 * best we can do. */
5245 return NF_ACCEPT;
5246
5247 /* standard practice, label using the parent socket */
5248 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005249 sid = sksec->sid;
5250 } else
5251 sid = SECINITSID_KERNEL;
5252 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5253 return NF_DROP;
5254
5255 return NF_ACCEPT;
5256}
5257
Eric W. Biederman06198b32015-09-18 14:33:06 -05005258static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005259 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005260 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005261{
5262 return selinux_ip_output(skb, PF_INET);
5263}
5264
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005265#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005266static unsigned int selinux_ipv6_output(void *priv,
5267 struct sk_buff *skb,
5268 const struct nf_hook_state *state)
5269{
5270 return selinux_ip_output(skb, PF_INET6);
5271}
5272#endif /* IPV6 */
5273
Paul Mooreeffad8d2008-01-29 08:49:27 -05005274static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5275 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005276 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005277{
Eric Dumazet54abc682015-11-08 10:54:07 -08005278 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005279 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005280 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005281 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005282 char *addrp;
5283 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005284
Paul Mooreeffad8d2008-01-29 08:49:27 -05005285 if (sk == NULL)
5286 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005287 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005288
Eric Paris50c205f2012-04-04 15:01:43 -04005289 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005290 ad.u.net = &net;
5291 ad.u.net->netif = ifindex;
5292 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005293 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5294 return NF_DROP;
5295
Paul Moore58bfbb52009-03-27 17:10:41 -04005296 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005297 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005298 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005299 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005300
Steffen Klassertb9679a72011-02-23 12:55:21 +01005301 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5302 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005303
Paul Mooreeffad8d2008-01-29 08:49:27 -05005304 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305}
5306
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005307static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5308 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005309 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005311 u32 secmark_perm;
5312 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005313 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005314 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005315 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005316 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005317 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005318 u8 secmark_active;
5319 u8 peerlbl_active;
5320
Paul Mooreeffad8d2008-01-29 08:49:27 -05005321 /* If any sort of compatibility mode is enabled then handoff processing
5322 * to the selinux_ip_postroute_compat() function to deal with the
5323 * special handling. We do this in an attempt to keep this function
5324 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04005325 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04005326 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005327
Paul Mooreeffad8d2008-01-29 08:49:27 -05005328 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005329 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005330 if (!secmark_active && !peerlbl_active)
5331 return NF_ACCEPT;
5332
Eric Dumazet54abc682015-11-08 10:54:07 -08005333 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005334
Paul Mooreeffad8d2008-01-29 08:49:27 -05005335#ifdef CONFIG_XFRM
5336 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5337 * packet transformation so allow the packet to pass without any checks
5338 * since we'll have another chance to perform access control checks
5339 * when the packet is on it's final way out.
5340 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005341 * is NULL, in this case go ahead and apply access control.
5342 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5343 * TCP listening state we cannot wait until the XFRM processing
5344 * is done as we will miss out on the SA label if we do;
5345 * unfortunately, this means more work, but it is only once per
5346 * connection. */
5347 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005348 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005349 return NF_ACCEPT;
5350#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005351
Paul Moored8395c82008-10-10 10:16:30 -04005352 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005353 /* Without an associated socket the packet is either coming
5354 * from the kernel or it is being forwarded; check the packet
5355 * to determine which and if the packet is being forwarded
5356 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005357 if (skb->skb_iif) {
5358 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005359 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005360 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005361 } else {
5362 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005363 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005364 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005365 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005366 /* Locally generated packet but the associated socket is in the
5367 * listening state which means this is a SYN-ACK packet. In
5368 * this particular case the correct security label is assigned
5369 * to the connection/request_sock but unfortunately we can't
5370 * query the request_sock as it isn't queued on the parent
5371 * socket until after the SYN-ACK packet is sent; the only
5372 * viable choice is to regenerate the label like we do in
5373 * selinux_inet_conn_request(). See also selinux_ip_output()
5374 * for similar problems. */
5375 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005376 struct sk_security_struct *sksec;
5377
Eric Dumazete446f9d2015-10-08 05:01:55 -07005378 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005379 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5380 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005381 /* At this point, if the returned skb peerlbl is SECSID_NULL
5382 * and the packet has been through at least one XFRM
5383 * transformation then we must be dealing with the "final"
5384 * form of labeled IPsec packet; since we've already applied
5385 * all of our access controls on this packet we can safely
5386 * pass the packet. */
5387 if (skb_sid == SECSID_NULL) {
5388 switch (family) {
5389 case PF_INET:
5390 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5391 return NF_ACCEPT;
5392 break;
5393 case PF_INET6:
5394 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5395 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005396 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005397 default:
5398 return NF_DROP_ERR(-ECONNREFUSED);
5399 }
5400 }
Paul Moore446b8022013-12-04 16:10:51 -05005401 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5402 return NF_DROP;
5403 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005404 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005405 /* Locally generated packet, fetch the security label from the
5406 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005407 struct sk_security_struct *sksec = sk->sk_security;
5408 peer_sid = sksec->sid;
5409 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005410 }
5411
Eric Paris50c205f2012-04-04 15:01:43 -04005412 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005413 ad.u.net = &net;
5414 ad.u.net->netif = ifindex;
5415 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005416 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005417 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005418
Paul Mooreeffad8d2008-01-29 08:49:27 -05005419 if (secmark_active)
5420 if (avc_has_perm(peer_sid, skb->secmark,
5421 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005422 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005423
5424 if (peerlbl_active) {
5425 u32 if_sid;
5426 u32 node_sid;
5427
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005428 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005429 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005430 if (avc_has_perm(peer_sid, if_sid,
5431 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005432 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005433
5434 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005435 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005436 if (avc_has_perm(peer_sid, node_sid,
5437 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005438 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005439 }
5440
5441 return NF_ACCEPT;
5442}
5443
Eric W. Biederman06198b32015-09-18 14:33:06 -05005444static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005445 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005446 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005447{
David S. Miller238e54c2015-04-03 20:32:56 -04005448 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005449}
5450
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005451#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005452static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005453 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005454 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455{
David S. Miller238e54c2015-04-03 20:32:56 -04005456 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458#endif /* IPV6 */
5459
5460#endif /* CONFIG_NETFILTER */
5461
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5463{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005464 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465}
5466
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005467static int ipc_alloc_security(struct kern_ipc_perm *perm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468 u16 sclass)
5469{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470 struct ipc_security_struct *isec;
5471
James Morris89d155e2005-10-30 14:59:21 -08005472 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473 if (!isec)
5474 return -ENOMEM;
5475
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005477 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478 perm->security = isec;
5479
5480 return 0;
5481}
5482
5483static void ipc_free_security(struct kern_ipc_perm *perm)
5484{
5485 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486 perm->security = NULL;
5487 kfree(isec);
5488}
5489
5490static int msg_msg_alloc_security(struct msg_msg *msg)
5491{
5492 struct msg_security_struct *msec;
5493
James Morris89d155e2005-10-30 14:59:21 -08005494 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495 if (!msec)
5496 return -ENOMEM;
5497
Linus Torvalds1da177e2005-04-16 15:20:36 -07005498 msec->sid = SECINITSID_UNLABELED;
5499 msg->security = msec;
5500
5501 return 0;
5502}
5503
5504static void msg_msg_free_security(struct msg_msg *msg)
5505{
5506 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507
5508 msg->security = NULL;
5509 kfree(msec);
5510}
5511
5512static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005513 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005516 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005517 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 isec = ipc_perms->security;
5520
Eric Paris50c205f2012-04-04 15:01:43 -04005521 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522 ad.u.ipc_id = ipc_perms->key;
5523
David Howells275bb412008-11-14 10:39:19 +11005524 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525}
5526
5527static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5528{
5529 return msg_msg_alloc_security(msg);
5530}
5531
5532static void selinux_msg_msg_free_security(struct msg_msg *msg)
5533{
5534 msg_msg_free_security(msg);
5535}
5536
5537/* message queue security operations */
5538static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5539{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005541 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005542 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543 int rc;
5544
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005545 rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546 if (rc)
5547 return rc;
5548
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549 isec = msq->q_perm.security;
5550
Eric Paris50c205f2012-04-04 15:01:43 -04005551 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005552 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553
David Howells275bb412008-11-14 10:39:19 +11005554 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 MSGQ__CREATE, &ad);
5556 if (rc) {
5557 ipc_free_security(&msq->q_perm);
5558 return rc;
5559 }
5560 return 0;
5561}
5562
5563static void selinux_msg_queue_free_security(struct msg_queue *msq)
5564{
5565 ipc_free_security(&msq->q_perm);
5566}
5567
5568static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5569{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005571 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005572 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574 isec = msq->q_perm.security;
5575
Eric Paris50c205f2012-04-04 15:01:43 -04005576 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577 ad.u.ipc_id = msq->q_perm.key;
5578
David Howells275bb412008-11-14 10:39:19 +11005579 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580 MSGQ__ASSOCIATE, &ad);
5581}
5582
5583static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5584{
5585 int err;
5586 int perms;
5587
Eric Paris828dfe12008-04-17 13:17:49 -04005588 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589 case IPC_INFO:
5590 case MSG_INFO:
5591 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005592 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5593 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594 case IPC_STAT:
5595 case MSG_STAT:
5596 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5597 break;
5598 case IPC_SET:
5599 perms = MSGQ__SETATTR;
5600 break;
5601 case IPC_RMID:
5602 perms = MSGQ__DESTROY;
5603 break;
5604 default:
5605 return 0;
5606 }
5607
Stephen Smalley6af963f2005-05-01 08:58:39 -07005608 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 return err;
5610}
5611
5612static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5613{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614 struct ipc_security_struct *isec;
5615 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005616 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005617 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618 int rc;
5619
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620 isec = msq->q_perm.security;
5621 msec = msg->security;
5622
5623 /*
5624 * First time through, need to assign label to the message
5625 */
5626 if (msec->sid == SECINITSID_UNLABELED) {
5627 /*
5628 * Compute new sid based on current process and
5629 * message queue this message will be stored in
5630 */
David Howells275bb412008-11-14 10:39:19 +11005631 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005632 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633 if (rc)
5634 return rc;
5635 }
5636
Eric Paris50c205f2012-04-04 15:01:43 -04005637 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 ad.u.ipc_id = msq->q_perm.key;
5639
5640 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005641 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 MSGQ__WRITE, &ad);
5643 if (!rc)
5644 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005645 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5646 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647 if (!rc)
5648 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005649 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5650 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651
5652 return rc;
5653}
5654
5655static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5656 struct task_struct *target,
5657 long type, int mode)
5658{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659 struct ipc_security_struct *isec;
5660 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005661 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005662 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663 int rc;
5664
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 isec = msq->q_perm.security;
5666 msec = msg->security;
5667
Eric Paris50c205f2012-04-04 15:01:43 -04005668 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005669 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
David Howells275bb412008-11-14 10:39:19 +11005671 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672 SECCLASS_MSGQ, MSGQ__READ, &ad);
5673 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005674 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675 SECCLASS_MSG, MSG__RECEIVE, &ad);
5676 return rc;
5677}
5678
5679/* Shared Memory security operations */
5680static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5681{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005683 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005684 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685 int rc;
5686
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005687 rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688 if (rc)
5689 return rc;
5690
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691 isec = shp->shm_perm.security;
5692
Eric Paris50c205f2012-04-04 15:01:43 -04005693 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005694 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695
David Howells275bb412008-11-14 10:39:19 +11005696 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 SHM__CREATE, &ad);
5698 if (rc) {
5699 ipc_free_security(&shp->shm_perm);
5700 return rc;
5701 }
5702 return 0;
5703}
5704
5705static void selinux_shm_free_security(struct shmid_kernel *shp)
5706{
5707 ipc_free_security(&shp->shm_perm);
5708}
5709
5710static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5711{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005713 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005714 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716 isec = shp->shm_perm.security;
5717
Eric Paris50c205f2012-04-04 15:01:43 -04005718 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719 ad.u.ipc_id = shp->shm_perm.key;
5720
David Howells275bb412008-11-14 10:39:19 +11005721 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005722 SHM__ASSOCIATE, &ad);
5723}
5724
5725/* Note, at this point, shp is locked down */
5726static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5727{
5728 int perms;
5729 int err;
5730
Eric Paris828dfe12008-04-17 13:17:49 -04005731 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732 case IPC_INFO:
5733 case SHM_INFO:
5734 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005735 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5736 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737 case IPC_STAT:
5738 case SHM_STAT:
5739 perms = SHM__GETATTR | SHM__ASSOCIATE;
5740 break;
5741 case IPC_SET:
5742 perms = SHM__SETATTR;
5743 break;
5744 case SHM_LOCK:
5745 case SHM_UNLOCK:
5746 perms = SHM__LOCK;
5747 break;
5748 case IPC_RMID:
5749 perms = SHM__DESTROY;
5750 break;
5751 default:
5752 return 0;
5753 }
5754
Stephen Smalley6af963f2005-05-01 08:58:39 -07005755 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756 return err;
5757}
5758
5759static int selinux_shm_shmat(struct shmid_kernel *shp,
5760 char __user *shmaddr, int shmflg)
5761{
5762 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763
5764 if (shmflg & SHM_RDONLY)
5765 perms = SHM__READ;
5766 else
5767 perms = SHM__READ | SHM__WRITE;
5768
Stephen Smalley6af963f2005-05-01 08:58:39 -07005769 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770}
5771
5772/* Semaphore security operations */
5773static int selinux_sem_alloc_security(struct sem_array *sma)
5774{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005776 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005777 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778 int rc;
5779
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005780 rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781 if (rc)
5782 return rc;
5783
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 isec = sma->sem_perm.security;
5785
Eric Paris50c205f2012-04-04 15:01:43 -04005786 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005787 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788
David Howells275bb412008-11-14 10:39:19 +11005789 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005790 SEM__CREATE, &ad);
5791 if (rc) {
5792 ipc_free_security(&sma->sem_perm);
5793 return rc;
5794 }
5795 return 0;
5796}
5797
5798static void selinux_sem_free_security(struct sem_array *sma)
5799{
5800 ipc_free_security(&sma->sem_perm);
5801}
5802
5803static int selinux_sem_associate(struct sem_array *sma, int semflg)
5804{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005806 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005807 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808
Linus Torvalds1da177e2005-04-16 15:20:36 -07005809 isec = sma->sem_perm.security;
5810
Eric Paris50c205f2012-04-04 15:01:43 -04005811 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812 ad.u.ipc_id = sma->sem_perm.key;
5813
David Howells275bb412008-11-14 10:39:19 +11005814 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815 SEM__ASSOCIATE, &ad);
5816}
5817
5818/* Note, at this point, sma is locked down */
5819static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5820{
5821 int err;
5822 u32 perms;
5823
Eric Paris828dfe12008-04-17 13:17:49 -04005824 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005825 case IPC_INFO:
5826 case SEM_INFO:
5827 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005828 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5829 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830 case GETPID:
5831 case GETNCNT:
5832 case GETZCNT:
5833 perms = SEM__GETATTR;
5834 break;
5835 case GETVAL:
5836 case GETALL:
5837 perms = SEM__READ;
5838 break;
5839 case SETVAL:
5840 case SETALL:
5841 perms = SEM__WRITE;
5842 break;
5843 case IPC_RMID:
5844 perms = SEM__DESTROY;
5845 break;
5846 case IPC_SET:
5847 perms = SEM__SETATTR;
5848 break;
5849 case IPC_STAT:
5850 case SEM_STAT:
5851 perms = SEM__GETATTR | SEM__ASSOCIATE;
5852 break;
5853 default:
5854 return 0;
5855 }
5856
Stephen Smalley6af963f2005-05-01 08:58:39 -07005857 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858 return err;
5859}
5860
5861static int selinux_sem_semop(struct sem_array *sma,
5862 struct sembuf *sops, unsigned nsops, int alter)
5863{
5864 u32 perms;
5865
5866 if (alter)
5867 perms = SEM__READ | SEM__WRITE;
5868 else
5869 perms = SEM__READ;
5870
Stephen Smalley6af963f2005-05-01 08:58:39 -07005871 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872}
5873
5874static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5875{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876 u32 av = 0;
5877
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878 av = 0;
5879 if (flag & S_IRUGO)
5880 av |= IPC__UNIX_READ;
5881 if (flag & S_IWUGO)
5882 av |= IPC__UNIX_WRITE;
5883
5884 if (av == 0)
5885 return 0;
5886
Stephen Smalley6af963f2005-05-01 08:58:39 -07005887 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888}
5889
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005890static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5891{
5892 struct ipc_security_struct *isec = ipcp->security;
5893 *secid = isec->sid;
5894}
5895
Eric Paris828dfe12008-04-17 13:17:49 -04005896static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897{
5898 if (inode)
5899 inode_doinit_with_dentry(inode, dentry);
5900}
5901
5902static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005903 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904{
David Howells275bb412008-11-14 10:39:19 +11005905 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005906 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005908 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909
David Howells275bb412008-11-14 10:39:19 +11005910 rcu_read_lock();
5911 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005913 if (current != p) {
5914 error = avc_has_perm(current_sid(), __tsec->sid,
5915 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
5916 if (error)
5917 goto bad;
5918 }
5919
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005921 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005923 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005925 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005927 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005928 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005929 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005930 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005931 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005932 else {
5933 error = -EINVAL;
5934 goto bad;
5935 }
David Howells275bb412008-11-14 10:39:19 +11005936 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
5938 if (!sid)
5939 return 0;
5940
Al Viro04ff9702007-03-12 16:17:58 +00005941 error = security_sid_to_context(sid, value, &len);
5942 if (error)
5943 return error;
5944 return len;
David Howells275bb412008-11-14 10:39:19 +11005945
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005946bad:
David Howells275bb412008-11-14 10:39:19 +11005947 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005948 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949}
5950
Stephen Smalleyb21507e2017-01-09 10:07:31 -05005951static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952{
5953 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11005954 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005955 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 int error;
5957 char *str = value;
5958
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959 /*
5960 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961 */
5962 if (!strcmp(name, "exec"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005963 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5964 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965 else if (!strcmp(name, "fscreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005966 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5967 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005968 else if (!strcmp(name, "keycreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005969 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5970 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07005971 else if (!strcmp(name, "sockcreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005972 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5973 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974 else if (!strcmp(name, "current"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005975 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5976 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977 else
5978 error = -EINVAL;
5979 if (error)
5980 return error;
5981
5982 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05005983 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984 if (str[size-1] == '\n') {
5985 str[size-1] = 0;
5986 size--;
5987 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005988 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005989 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04005990 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005991 struct audit_buffer *ab;
5992 size_t audit_size;
5993
5994 /* We strip a nul only if it is at the end, otherwise the
5995 * context contains a nul and we should audit that */
5996 if (str[size - 1] == '\0')
5997 audit_size = size - 1;
5998 else
5999 audit_size = size;
6000 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
6001 audit_log_format(ab, "op=fscreate invalid_context=");
6002 audit_log_n_untrustedstring(ab, value, audit_size);
6003 audit_log_end(ab);
6004
Stephen Smalley12b29f32008-05-07 13:03:20 -04006005 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04006006 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04006007 error = security_context_to_sid_force(value, size,
6008 &sid);
6009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010 if (error)
6011 return error;
6012 }
6013
David Howellsd84f4f92008-11-14 10:39:23 +11006014 new = prepare_creds();
6015 if (!new)
6016 return -ENOMEM;
6017
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 /* Permission checking based on the specified context is
6019 performed during the actual operation (execve,
6020 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11006021 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07006022 checks and may_create for the file creation checks. The
6023 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11006024 tsec = new->security;
6025 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006027 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006029 } else if (!strcmp(name, "keycreate")) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006030 error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE,
6031 NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07006032 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006033 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006034 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006035 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07006036 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11006037 } else if (!strcmp(name, "current")) {
6038 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11006040 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09006041
David Howellsd84f4f92008-11-14 10:39:23 +11006042 /* Only allow single threaded processes to change context */
6043 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02006044 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11006045 error = security_bounded_transition(tsec->sid, sid);
6046 if (error)
6047 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04006048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049
6050 /* Check permissions for the transition. */
6051 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006052 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006054 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055
6056 /* Check for ptracing, and update the task SID if ok.
6057 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006058 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006059 if (ptsid != 0) {
David Howellsd84f4f92008-11-14 10:39:23 +11006060 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
6061 PROCESS__PTRACE, NULL);
6062 if (error)
6063 goto abort_change;
6064 }
6065
6066 tsec->sid = sid;
6067 } else {
6068 error = -EINVAL;
6069 goto abort_change;
6070 }
6071
6072 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006074
6075abort_change:
6076 abort_creds(new);
6077 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078}
6079
David Quigley746df9b2013-05-22 12:50:35 -04006080static int selinux_ismaclabel(const char *name)
6081{
6082 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6083}
6084
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006085static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6086{
6087 return security_sid_to_context(secid, secdata, seclen);
6088}
6089
David Howells7bf570d2008-04-29 20:52:51 +01006090static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006091{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01006092 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006093}
6094
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006095static void selinux_release_secctx(char *secdata, u32 seclen)
6096{
Paul Moore088999e2007-08-01 11:12:58 -04006097 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006098}
6099
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006100static void selinux_inode_invalidate_secctx(struct inode *inode)
6101{
6102 struct inode_security_struct *isec = inode->i_security;
6103
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006104 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006105 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006106 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006107}
6108
David P. Quigley1ee65e32009-09-03 14:25:57 -04006109/*
6110 * called with inode->i_mutex locked
6111 */
6112static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6113{
6114 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6115}
6116
6117/*
6118 * called with inode->i_mutex locked
6119 */
6120static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6121{
6122 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6123}
6124
6125static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6126{
6127 int len = 0;
6128 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6129 ctx, true);
6130 if (len < 0)
6131 return len;
6132 *ctxlen = len;
6133 return 0;
6134}
Michael LeMayd7200242006-06-22 14:47:17 -07006135#ifdef CONFIG_KEYS
6136
David Howellsd84f4f92008-11-14 10:39:23 +11006137static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006138 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006139{
David Howellsd84f4f92008-11-14 10:39:23 +11006140 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006141 struct key_security_struct *ksec;
6142
6143 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6144 if (!ksec)
6145 return -ENOMEM;
6146
David Howellsd84f4f92008-11-14 10:39:23 +11006147 tsec = cred->security;
6148 if (tsec->keycreate_sid)
6149 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006150 else
David Howellsd84f4f92008-11-14 10:39:23 +11006151 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006152
David Howells275bb412008-11-14 10:39:19 +11006153 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006154 return 0;
6155}
6156
6157static void selinux_key_free(struct key *k)
6158{
6159 struct key_security_struct *ksec = k->security;
6160
6161 k->security = NULL;
6162 kfree(ksec);
6163}
6164
6165static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006166 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006167 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006168{
6169 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006170 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006171 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006172
6173 /* if no specific permissions are requested, we skip the
6174 permission check. No serious, additional covert channels
6175 appear to be created. */
6176 if (perm == 0)
6177 return 0;
6178
David Howellsd84f4f92008-11-14 10:39:23 +11006179 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006180
6181 key = key_ref_to_ptr(key_ref);
6182 ksec = key->security;
6183
6184 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006185}
6186
David Howells70a5bb72008-04-29 01:01:26 -07006187static int selinux_key_getsecurity(struct key *key, char **_buffer)
6188{
6189 struct key_security_struct *ksec = key->security;
6190 char *context = NULL;
6191 unsigned len;
6192 int rc;
6193
6194 rc = security_sid_to_context(ksec->sid, &context, &len);
6195 if (!rc)
6196 rc = len;
6197 *_buffer = context;
6198 return rc;
6199}
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006200#endif
David Howells70a5bb72008-04-29 01:01:26 -07006201
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006202#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006203static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6204{
6205 struct common_audit_data ad;
6206 int err;
6207 u32 sid = 0;
6208 struct ib_security_struct *sec = ib_sec;
6209 struct lsm_ibpkey_audit ibpkey;
6210
Daniel Jurgens409dcf32017-05-19 15:48:59 +03006211 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006212 if (err)
6213 return err;
6214
6215 ad.type = LSM_AUDIT_DATA_IBPKEY;
6216 ibpkey.subnet_prefix = subnet_prefix;
6217 ibpkey.pkey = pkey_val;
6218 ad.u.ibpkey = &ibpkey;
6219 return avc_has_perm(sec->sid, sid,
6220 SECCLASS_INFINIBAND_PKEY,
6221 INFINIBAND_PKEY__ACCESS, &ad);
6222}
6223
Daniel Jurgensab861df2017-05-19 15:48:58 +03006224static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6225 u8 port_num)
6226{
6227 struct common_audit_data ad;
6228 int err;
6229 u32 sid = 0;
6230 struct ib_security_struct *sec = ib_sec;
6231 struct lsm_ibendport_audit ibendport;
6232
6233 err = security_ib_endport_sid(dev_name, port_num, &sid);
6234
6235 if (err)
6236 return err;
6237
6238 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6239 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6240 ibendport.port = port_num;
6241 ad.u.ibendport = &ibendport;
6242 return avc_has_perm(sec->sid, sid,
6243 SECCLASS_INFINIBAND_ENDPORT,
6244 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6245}
6246
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006247static int selinux_ib_alloc_security(void **ib_sec)
6248{
6249 struct ib_security_struct *sec;
6250
6251 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6252 if (!sec)
6253 return -ENOMEM;
6254 sec->sid = current_sid();
6255
6256 *ib_sec = sec;
6257 return 0;
6258}
6259
6260static void selinux_ib_free_security(void *ib_sec)
6261{
6262 kfree(ib_sec);
6263}
Michael LeMayd7200242006-06-22 14:47:17 -07006264#endif
6265
James Morrisca97d932017-02-15 00:18:51 +11006266static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006267 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6268 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6269 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6270 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006271
Casey Schauflere20b0432015-05-02 15:11:36 -07006272 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6273 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6274 LSM_HOOK_INIT(capget, selinux_capget),
6275 LSM_HOOK_INIT(capset, selinux_capset),
6276 LSM_HOOK_INIT(capable, selinux_capable),
6277 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6278 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6279 LSM_HOOK_INIT(syslog, selinux_syslog),
6280 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006281
Casey Schauflere20b0432015-05-02 15:11:36 -07006282 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006283
Casey Schauflere20b0432015-05-02 15:11:36 -07006284 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6285 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6286 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
6287 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288
Casey Schauflere20b0432015-05-02 15:11:36 -07006289 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6290 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
6291 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
6292 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6293 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6294 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6295 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6296 LSM_HOOK_INIT(sb_mount, selinux_mount),
6297 LSM_HOOK_INIT(sb_umount, selinux_umount),
6298 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6299 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
6300 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006301
Casey Schauflere20b0432015-05-02 15:11:36 -07006302 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006303 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006304
Casey Schauflere20b0432015-05-02 15:11:36 -07006305 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6306 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6307 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6308 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6309 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6310 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6311 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6312 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6313 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6314 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6315 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6316 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6317 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6318 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6319 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6320 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6321 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6322 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6323 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6324 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6325 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6326 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6327 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6328 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6329 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006330 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006331 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332
Casey Schauflere20b0432015-05-02 15:11:36 -07006333 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6334 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6335 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6336 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6337 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6338 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6339 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6340 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6341 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6342 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6343 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6344 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006345
Casey Schauflere20b0432015-05-02 15:11:36 -07006346 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347
Tetsuo Handaa79be232017-03-28 23:08:45 +09006348 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07006349 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6350 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6351 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6352 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
6353 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6354 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6355 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006356 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006357 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6358 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6359 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6360 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6361 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6362 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6363 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05006364 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07006365 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6366 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6367 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6368 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6369 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07006370 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006371
Casey Schauflere20b0432015-05-02 15:11:36 -07006372 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6373 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374
Casey Schauflere20b0432015-05-02 15:11:36 -07006375 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6376 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006377
Casey Schauflere20b0432015-05-02 15:11:36 -07006378 LSM_HOOK_INIT(msg_queue_alloc_security,
6379 selinux_msg_queue_alloc_security),
6380 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6381 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6382 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6383 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6384 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006385
Casey Schauflere20b0432015-05-02 15:11:36 -07006386 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6387 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6388 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6389 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6390 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006391
Casey Schauflere20b0432015-05-02 15:11:36 -07006392 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6393 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6394 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6395 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6396 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006397
Casey Schauflere20b0432015-05-02 15:11:36 -07006398 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006399
Casey Schauflere20b0432015-05-02 15:11:36 -07006400 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6401 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006402
Casey Schauflere20b0432015-05-02 15:11:36 -07006403 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6404 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6405 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6406 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006407 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006408 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6409 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6410 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411
Casey Schauflere20b0432015-05-02 15:11:36 -07006412 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6413 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006414
Casey Schauflere20b0432015-05-02 15:11:36 -07006415 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6416 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6417 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6418 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6419 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6420 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6421 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6422 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6423 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6424 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6425 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6426 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6427 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6428 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6429 LSM_HOOK_INIT(socket_getpeersec_stream,
6430 selinux_socket_getpeersec_stream),
6431 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6432 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6433 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6434 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6435 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6436 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6437 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6438 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6439 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6440 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6441 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6442 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6443 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6444 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6445 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6446 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6447 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6448 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6449 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006450#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006451 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgensab861df2017-05-19 15:48:58 +03006452 LSM_HOOK_INIT(ib_endport_manage_subnet,
6453 selinux_ib_endport_manage_subnet),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006454 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6455 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6456#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006457#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006458 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6459 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6460 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6461 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6462 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6463 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6464 selinux_xfrm_state_alloc_acquire),
6465 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6466 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6467 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6468 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6469 selinux_xfrm_state_pol_flow_match),
6470 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006471#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006472
6473#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006474 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6475 LSM_HOOK_INIT(key_free, selinux_key_free),
6476 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6477 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006478#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006479
6480#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006481 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6482 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6483 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6484 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006485#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486};
6487
6488static __init int selinux_init(void)
6489{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006490 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006491 selinux_enabled = 0;
6492 return 0;
6493 }
6494
Linus Torvalds1da177e2005-04-16 15:20:36 -07006495 if (!selinux_enabled) {
6496 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6497 return 0;
6498 }
6499
6500 printk(KERN_INFO "SELinux: Initializing.\n");
6501
6502 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006503 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006504
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006505 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6506
James Morris7cae7e22006-03-22 00:09:22 -08006507 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6508 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006509 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006510 file_security_cache = kmem_cache_create("selinux_file_security",
6511 sizeof(struct file_security_struct),
6512 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513 avc_init();
6514
Casey Schauflerd69dece52017-01-18 17:09:05 -08006515 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006516
Paul Moore615e51f2014-06-26 14:33:56 -04006517 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6518 panic("SELinux: Unable to register AVC netcache callback\n");
6519
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03006520 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6521 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6522
Eric Paris828dfe12008-04-17 13:17:49 -04006523 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006524 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006525 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006526 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006527
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528 return 0;
6529}
6530
Al Viroe8c26252010-03-23 06:36:54 -04006531static void delayed_superblock_init(struct super_block *sb, void *unused)
6532{
6533 superblock_doinit(sb, NULL);
6534}
6535
Linus Torvalds1da177e2005-04-16 15:20:36 -07006536void selinux_complete_init(void)
6537{
Eric Parisfadcdb42007-02-22 18:11:31 -05006538 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006539
6540 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006541 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006542 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543}
6544
6545/* SELinux requires early initialization in order to label
6546 all processes and objects when they are created. */
6547security_initcall(selinux_init);
6548
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006549#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550
Jiri Pirko25db6be2014-09-03 17:42:13 +02006551static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006552 {
6553 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006554 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006555 .hooknum = NF_INET_POST_ROUTING,
6556 .priority = NF_IP_PRI_SELINUX_LAST,
6557 },
6558 {
6559 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006560 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006561 .hooknum = NF_INET_FORWARD,
6562 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006563 },
6564 {
6565 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006566 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006567 .hooknum = NF_INET_LOCAL_OUT,
6568 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006569 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04006570#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006571 {
6572 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006573 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006574 .hooknum = NF_INET_POST_ROUTING,
6575 .priority = NF_IP6_PRI_SELINUX_LAST,
6576 },
6577 {
6578 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006579 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006580 .hooknum = NF_INET_FORWARD,
6581 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006582 },
Huw Davies2917f572016-06-27 15:06:15 -04006583 {
6584 .hook = selinux_ipv6_output,
6585 .pf = NFPROTO_IPV6,
6586 .hooknum = NF_INET_LOCAL_OUT,
6587 .priority = NF_IP6_PRI_SELINUX_FIRST,
6588 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006590};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591
Florian Westphal8e71bf72017-04-21 11:49:09 +02006592static int __net_init selinux_nf_register(struct net *net)
6593{
6594 return nf_register_net_hooks(net, selinux_nf_ops,
6595 ARRAY_SIZE(selinux_nf_ops));
6596}
6597
6598static void __net_exit selinux_nf_unregister(struct net *net)
6599{
6600 nf_unregister_net_hooks(net, selinux_nf_ops,
6601 ARRAY_SIZE(selinux_nf_ops));
6602}
6603
6604static struct pernet_operations selinux_net_ops = {
6605 .init = selinux_nf_register,
6606 .exit = selinux_nf_unregister,
6607};
6608
Linus Torvalds1da177e2005-04-16 15:20:36 -07006609static int __init selinux_nf_ip_init(void)
6610{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006611 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006612
6613 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006614 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006615
6616 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6617
Florian Westphal8e71bf72017-04-21 11:49:09 +02006618 err = register_pernet_subsys(&selinux_net_ops);
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006619 if (err)
Florian Westphal8e71bf72017-04-21 11:49:09 +02006620 panic("SELinux: register_pernet_subsys: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006621
Jiri Pirko25db6be2014-09-03 17:42:13 +02006622 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006623}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624__initcall(selinux_nf_ip_init);
6625
6626#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6627static void selinux_nf_ip_exit(void)
6628{
Eric Parisfadcdb42007-02-22 18:11:31 -05006629 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006630
Florian Westphal8e71bf72017-04-21 11:49:09 +02006631 unregister_pernet_subsys(&selinux_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006632}
6633#endif
6634
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006635#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006636
6637#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6638#define selinux_nf_ip_exit()
6639#endif
6640
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006641#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006642
6643#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006644static int selinux_disabled;
6645
Linus Torvalds1da177e2005-04-16 15:20:36 -07006646int selinux_disable(void)
6647{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006648 if (ss_initialized) {
6649 /* Not permitted after initial policy load. */
6650 return -EINVAL;
6651 }
6652
6653 if (selinux_disabled) {
6654 /* Only do this once. */
6655 return -EINVAL;
6656 }
6657
6658 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6659
6660 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006661 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006662
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006663 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664
Eric Parisaf8ff042009-09-20 21:23:01 -04006665 /* Try to destroy the avc node cache */
6666 avc_disable();
6667
Linus Torvalds1da177e2005-04-16 15:20:36 -07006668 /* Unregister netfilter hooks. */
6669 selinux_nf_ip_exit();
6670
6671 /* Unregister selinuxfs. */
6672 exit_sel_fs();
6673
6674 return 0;
6675}
6676#endif