blob: b59255f86274195a6e493ebcf313bc4644827fd8 [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 Moore3e112172008-04-10 10:48:14 -040093#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080094#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050095#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020096#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100097#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Paul Moored621d352008-01-29 08:43:36 -050099/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000100static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400103int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105static int __init enforcing_setup(char *str)
106{
Eric Parisf5269712008-05-14 11:27:45 -0400107 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900108 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400109 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return 1;
111}
112__setup("enforcing=", enforcing_setup);
113#endif
114
115#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
116int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
117
118static int __init selinux_enabled_setup(char *str)
119{
Eric Parisf5269712008-05-14 11:27:45 -0400120 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900121 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400122 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return 1;
124}
125__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400126#else
127int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#endif
129
Christoph Lametere18b8902006-12-06 20:33:20 -0800130static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400131static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800132
Paul Moored621d352008-01-29 08:43:36 -0500133/**
134 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
135 *
136 * Description:
137 * This function checks the SECMARK reference counter to see if any SECMARK
138 * targets are currently configured, if the reference counter is greater than
139 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400140 * enabled, false (0) if SECMARK is disabled. If the always_check_network
141 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500142 *
143 */
144static int selinux_secmark_enabled(void)
145{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400146 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
147}
148
149/**
150 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
151 *
152 * Description:
153 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
154 * (1) if any are enabled or false (0) if neither are enabled. If the
155 * always_check_network policy capability is enabled, peer labeling
156 * is always considered enabled.
157 *
158 */
159static int selinux_peerlbl_enabled(void)
160{
161 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500162}
163
Paul Moore615e51f2014-06-26 14:33:56 -0400164static int selinux_netcache_avc_callback(u32 event)
165{
166 if (event == AVC_CALLBACK_RESET) {
167 sel_netif_flush();
168 sel_netnode_flush();
169 sel_netport_flush();
170 synchronize_net();
171 }
172 return 0;
173}
174
Daniel Jurgens8f408ab2017-05-19 15:48:53 +0300175static int selinux_lsm_notifier_avc_callback(u32 event)
176{
177 if (event == AVC_CALLBACK_RESET)
178 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
179
180 return 0;
181}
182
David Howellsd84f4f92008-11-14 10:39:23 +1100183/*
184 * initialise the security for the init task
185 */
186static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187{
David Howells3b11a1d2008-11-14 10:39:26 +1100188 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 struct task_security_struct *tsec;
190
James Morris89d155e2005-10-30 14:59:21 -0800191 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100193 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
David Howellsd84f4f92008-11-14 10:39:23 +1100195 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100196 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197}
198
David Howells275bb412008-11-14 10:39:19 +1100199/*
David Howells88e67f32008-11-14 10:39:21 +1100200 * get the security ID of a set of credentials
201 */
202static inline u32 cred_sid(const struct cred *cred)
203{
204 const struct task_security_struct *tsec;
205
206 tsec = cred->security;
207 return tsec->sid;
208}
209
210/*
David Howells3b11a1d2008-11-14 10:39:26 +1100211 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100212 */
213static inline u32 task_sid(const struct task_struct *task)
214{
David Howells275bb412008-11-14 10:39:19 +1100215 u32 sid;
216
217 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100218 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100219 rcu_read_unlock();
220 return sid;
221}
222
David Howells88e67f32008-11-14 10:39:21 +1100223/* Allocate and free functions for each kind of security blob. */
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static int inode_alloc_security(struct inode *inode)
226{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100228 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Josef Bacika02fe132008-04-04 09:35:05 +1100230 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 if (!isec)
232 return -ENOMEM;
233
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +0100234 spin_lock_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 isec->inode = inode;
237 isec->sid = SECINITSID_UNLABELED;
238 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100239 isec->task_sid = sid;
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100240 isec->initialized = LABEL_INVALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 inode->i_security = isec;
242
243 return 0;
244}
245
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500246static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
247
248/*
249 * Try reloading inode security labels that have been marked as invalid. The
250 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100251 * allowed; when set to false, returns -ECHILD when the label is
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500252 * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
253 * when no dentry is available, set it to NULL instead.
254 */
255static int __inode_security_revalidate(struct inode *inode,
256 struct dentry *opt_dentry,
257 bool may_sleep)
258{
259 struct inode_security_struct *isec = inode->i_security;
260
261 might_sleep_if(may_sleep);
262
Paul Moore1ac424762016-04-18 16:41:38 -0400263 if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500264 if (!may_sleep)
265 return -ECHILD;
266
267 /*
268 * Try reloading the inode security label. This will fail if
269 * @opt_dentry is NULL and no dentry for this inode can be
270 * found; in that case, continue using the old label.
271 */
272 inode_doinit_with_dentry(inode, opt_dentry);
273 }
274 return 0;
275}
276
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500277static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
278{
279 return inode->i_security;
280}
281
282static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
283{
284 int error;
285
286 error = __inode_security_revalidate(inode, NULL, !rcu);
287 if (error)
288 return ERR_PTR(error);
289 return inode->i_security;
290}
291
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500292/*
293 * Get the security label of an inode.
294 */
295static struct inode_security_struct *inode_security(struct inode *inode)
296{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500297 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500298 return inode->i_security;
299}
300
Paul Moore2c971652016-04-19 16:36:28 -0400301static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
302{
303 struct inode *inode = d_backing_inode(dentry);
304
305 return inode->i_security;
306}
307
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500308/*
309 * Get the security label of a dentry's backing inode.
310 */
311static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
312{
313 struct inode *inode = d_backing_inode(dentry);
314
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500315 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500316 return inode->i_security;
317}
318
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500319static void inode_free_rcu(struct rcu_head *head)
320{
321 struct inode_security_struct *isec;
322
323 isec = container_of(head, struct inode_security_struct, rcu);
324 kmem_cache_free(sel_inode_cache, isec);
325}
326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327static void inode_free_security(struct inode *inode)
328{
329 struct inode_security_struct *isec = inode->i_security;
330 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
331
Waiman Long9629d042015-07-10 17:19:56 -0400332 /*
333 * As not all inode security structures are in a list, we check for
334 * empty list outside of the lock to make sure that we won't waste
335 * time taking a lock doing nothing.
336 *
337 * The list_del_init() function can be safely called more than once.
338 * It should not be possible for this function to be called with
339 * concurrent list_add(), but for better safety against future changes
340 * in the code, we use list_empty_careful() here.
341 */
342 if (!list_empty_careful(&isec->list)) {
343 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400345 spin_unlock(&sbsec->isec_lock);
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500348 /*
349 * The inode may still be referenced in a path walk and
350 * a call to selinux_inode_permission() can be made
351 * after inode_free_security() is called. Ideally, the VFS
352 * wouldn't do this, but fixing that is a much harder
353 * job. For now, simply free the i_security via RCU, and
354 * leave the current inode->i_security pointer intact.
355 * The inode will be freed after the RCU grace period too.
356 */
357 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
360static int file_alloc_security(struct file *file)
361{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100363 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Sangwoo63205652015-10-21 17:44:30 -0400365 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (!fsec)
367 return -ENOMEM;
368
David Howells275bb412008-11-14 10:39:19 +1100369 fsec->sid = sid;
370 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 file->f_security = fsec;
372
373 return 0;
374}
375
376static void file_free_security(struct file *file)
377{
378 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400380 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
382
383static int superblock_alloc_security(struct super_block *sb)
384{
385 struct superblock_security_struct *sbsec;
386
James Morris89d155e2005-10-30 14:59:21 -0800387 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 if (!sbsec)
389 return -ENOMEM;
390
Eric Parisbc7e9822006-09-25 23:32:02 -0700391 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 INIT_LIST_HEAD(&sbsec->isec_head);
393 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 sbsec->sb = sb;
395 sbsec->sid = SECINITSID_UNLABELED;
396 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700397 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 sb->s_security = sbsec;
399
400 return 0;
401}
402
403static void superblock_free_security(struct super_block *sb)
404{
405 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 sb->s_security = NULL;
407 kfree(sbsec);
408}
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410static inline int inode_doinit(struct inode *inode)
411{
412 return inode_doinit_with_dentry(inode, NULL);
413}
414
415enum {
Eric Paris31e87932007-09-19 17:19:12 -0400416 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 Opt_context = 1,
418 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500419 Opt_defcontext = 3,
420 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500421 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400422 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423};
424
Eric Parisd355987f2012-08-24 15:58:53 -0400425#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
426
Steven Whitehousea447c092008-10-13 10:46:57 +0100427static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400428 {Opt_context, CONTEXT_STR "%s"},
429 {Opt_fscontext, FSCONTEXT_STR "%s"},
430 {Opt_defcontext, DEFCONTEXT_STR "%s"},
431 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500432 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400433 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434};
435
436#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
437
Eric Parisc312feb2006-07-10 04:43:53 -0700438static int may_context_mount_sb_relabel(u32 sid,
439 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100440 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700441{
David Howells275bb412008-11-14 10:39:19 +1100442 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700443 int rc;
444
445 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
446 FILESYSTEM__RELABELFROM, NULL);
447 if (rc)
448 return rc;
449
450 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
451 FILESYSTEM__RELABELTO, NULL);
452 return rc;
453}
454
Eric Paris08089252006-07-10 04:43:55 -0700455static int may_context_mount_inode_relabel(u32 sid,
456 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100457 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700458{
David Howells275bb412008-11-14 10:39:19 +1100459 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700460 int rc;
461 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
462 FILESYSTEM__RELABELFROM, NULL);
463 if (rc)
464 return rc;
465
466 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
467 FILESYSTEM__ASSOCIATE, NULL);
468 return rc;
469}
470
Eric Parisb43e7252012-10-10 14:27:35 -0400471static int selinux_is_sblabel_mnt(struct super_block *sb)
472{
473 struct superblock_security_struct *sbsec = sb->s_security;
474
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500475 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
476 sbsec->behavior == SECURITY_FS_USE_TRANS ||
477 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400478 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500479 /* Special handling. Genfs but also in-core setxattr handler */
480 !strcmp(sb->s_type->name, "sysfs") ||
481 !strcmp(sb->s_type->name, "pstore") ||
482 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liua2c7c6f2017-01-09 10:07:30 -0500483 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley2651225b2017-02-28 10:35:56 -0500484 !strcmp(sb->s_type->name, "rootfs") ||
485 (selinux_policycap_cgroupseclabel &&
486 (!strcmp(sb->s_type->name, "cgroup") ||
487 !strcmp(sb->s_type->name, "cgroup2")));
Eric Parisb43e7252012-10-10 14:27:35 -0400488}
489
Eric Parisc9180a52007-11-30 13:00:35 -0500490static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 struct superblock_security_struct *sbsec = sb->s_security;
493 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000494 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 int rc = 0;
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
498 /* Make sure that the xattr handler exists and that no
499 error other than -ENODATA is returned by getxattr on
500 the root directory. -ENODATA is ok, as this may be
501 the first boot of the SELinux kernel before we have
502 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200503 if (!(root_inode->i_opflags & IOP_XATTR)) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800504 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
505 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 rc = -EOPNOTSUPP;
507 goto out;
508 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200509
510 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 if (rc < 0 && rc != -ENODATA) {
512 if (rc == -EOPNOTSUPP)
513 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800514 "%s) has no security xattr handler\n",
515 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 else
517 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800518 "%s) getxattr errno %d\n", sb->s_id,
519 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 goto out;
521 }
522 }
523
Eric Pariseadcabc2012-08-24 15:59:14 -0400524 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400525 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400526 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500529 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
531 /* Initialize any other inodes associated with the superblock, e.g.
532 inodes created prior to initial policy load or inodes created
533 during get_sb by a pseudo filesystem that directly
534 populates itself. */
535 spin_lock(&sbsec->isec_lock);
536next_inode:
537 if (!list_empty(&sbsec->isec_head)) {
538 struct inode_security_struct *isec =
539 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500540 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400542 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 spin_unlock(&sbsec->isec_lock);
544 inode = igrab(inode);
545 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500546 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 inode_doinit(inode);
548 iput(inode);
549 }
550 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 goto next_inode;
552 }
553 spin_unlock(&sbsec->isec_lock);
554out:
Eric Parisc9180a52007-11-30 13:00:35 -0500555 return rc;
556}
557
558/*
559 * This function should allow an FS to ask what it's mount security
560 * options were so it can use those later for submounts, displaying
561 * mount options, or whatever.
562 */
563static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500564 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500565{
566 int rc = 0, i;
567 struct superblock_security_struct *sbsec = sb->s_security;
568 char *context = NULL;
569 u32 len;
570 char tmp;
571
Eric Parise0007522008-03-05 10:31:54 -0500572 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500573
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500574 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500575 return -EINVAL;
576
577 if (!ss_initialized)
578 return -EINVAL;
579
Eric Parisaf8e50c2012-08-24 15:59:00 -0400580 /* make sure we always check enough bits to cover the mask */
581 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
582
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500583 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500584 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400585 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500586 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500587 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500588 tmp >>= 1;
589 }
David P. Quigley11689d42009-01-16 09:22:03 -0500590 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400591 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500592 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500593
Eric Parise0007522008-03-05 10:31:54 -0500594 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
595 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500596 rc = -ENOMEM;
597 goto out_free;
598 }
599
Eric Parise0007522008-03-05 10:31:54 -0500600 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
601 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500602 rc = -ENOMEM;
603 goto out_free;
604 }
605
606 i = 0;
607 if (sbsec->flags & FSCONTEXT_MNT) {
608 rc = security_sid_to_context(sbsec->sid, &context, &len);
609 if (rc)
610 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500611 opts->mnt_opts[i] = context;
612 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500613 }
614 if (sbsec->flags & CONTEXT_MNT) {
615 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
616 if (rc)
617 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500618 opts->mnt_opts[i] = context;
619 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500620 }
621 if (sbsec->flags & DEFCONTEXT_MNT) {
622 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
623 if (rc)
624 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500625 opts->mnt_opts[i] = context;
626 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500627 }
628 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500629 struct dentry *root = sbsec->sb->s_root;
630 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500631
632 rc = security_sid_to_context(isec->sid, &context, &len);
633 if (rc)
634 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500635 opts->mnt_opts[i] = context;
636 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500637 }
Eric Paris12f348b2012-10-09 10:56:25 -0400638 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500639 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400640 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500641 }
Eric Parisc9180a52007-11-30 13:00:35 -0500642
Eric Parise0007522008-03-05 10:31:54 -0500643 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500644
645 return 0;
646
647out_free:
Eric Parise0007522008-03-05 10:31:54 -0500648 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500649 return rc;
650}
651
652static int bad_option(struct superblock_security_struct *sbsec, char flag,
653 u32 old_sid, u32 new_sid)
654{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500655 char mnt_flags = sbsec->flags & SE_MNTMASK;
656
Eric Parisc9180a52007-11-30 13:00:35 -0500657 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500658 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500659 if (!(sbsec->flags & flag) ||
660 (old_sid != new_sid))
661 return 1;
662
663 /* check if we were passed the same options twice,
664 * aka someone passed context=a,context=b
665 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500666 if (!(sbsec->flags & SE_SBINITIALIZED))
667 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500668 return 1;
669 return 0;
670}
Eric Parise0007522008-03-05 10:31:54 -0500671
Eric Parisc9180a52007-11-30 13:00:35 -0500672/*
673 * Allow filesystems with binary mount data to explicitly set mount point
674 * labeling information.
675 */
Eric Parise0007522008-03-05 10:31:54 -0500676static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400677 struct security_mnt_opts *opts,
678 unsigned long kern_flags,
679 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500680{
David Howells275bb412008-11-14 10:39:19 +1100681 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500682 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500683 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800684 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500685 struct dentry *root = sbsec->sb->s_root;
Paul Moore2c971652016-04-19 16:36:28 -0400686 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500687 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
688 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500689 char **mount_options = opts->mnt_opts;
690 int *flags = opts->mnt_opts_flags;
691 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500692
693 mutex_lock(&sbsec->lock);
694
695 if (!ss_initialized) {
696 if (!num_opts) {
697 /* Defer initialization until selinux_complete_init,
698 after the initial policy is loaded and the security
699 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500700 goto out;
701 }
702 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400703 printk(KERN_WARNING "SELinux: Unable to set superblock options "
704 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500705 goto out;
706 }
David Quigley649f6e72013-05-22 12:50:36 -0400707 if (kern_flags && !set_kern_flags) {
708 /* Specifying internal flags without providing a place to
709 * place the results is not allowed */
710 rc = -EINVAL;
711 goto out;
712 }
Eric Parisc9180a52007-11-30 13:00:35 -0500713
714 /*
Eric Parise0007522008-03-05 10:31:54 -0500715 * Binary mount data FS will come through this function twice. Once
716 * from an explicit call and once from the generic calls from the vfs.
717 * Since the generic VFS calls will not contain any security mount data
718 * we need to skip the double mount verification.
719 *
720 * This does open a hole in which we will not notice if the first
721 * mount using this sb set explict options and a second mount using
722 * this sb does not set any security options. (The first options
723 * will be used for both mounts)
724 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500725 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500726 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400727 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500728
Paul Moore2c971652016-04-19 16:36:28 -0400729 root_isec = backing_inode_security_novalidate(root);
730
Eric Parise0007522008-03-05 10:31:54 -0500731 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500732 * parse the mount options, check if they are valid sids.
733 * also check if someone is trying to mount the same sb more
734 * than once with different security options.
735 */
736 for (i = 0; i < num_opts; i++) {
737 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500738
Eric Paris12f348b2012-10-09 10:56:25 -0400739 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500740 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400741 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500742 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400743 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800744 "(%s) failed for (dev %s, type %s) errno=%d\n",
745 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500746 goto out;
747 }
748 switch (flags[i]) {
749 case FSCONTEXT_MNT:
750 fscontext_sid = sid;
751
752 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
753 fscontext_sid))
754 goto out_double_mount;
755
756 sbsec->flags |= FSCONTEXT_MNT;
757 break;
758 case CONTEXT_MNT:
759 context_sid = sid;
760
761 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
762 context_sid))
763 goto out_double_mount;
764
765 sbsec->flags |= CONTEXT_MNT;
766 break;
767 case ROOTCONTEXT_MNT:
768 rootcontext_sid = sid;
769
770 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
771 rootcontext_sid))
772 goto out_double_mount;
773
774 sbsec->flags |= ROOTCONTEXT_MNT;
775
776 break;
777 case DEFCONTEXT_MNT:
778 defcontext_sid = sid;
779
780 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
781 defcontext_sid))
782 goto out_double_mount;
783
784 sbsec->flags |= DEFCONTEXT_MNT;
785
786 break;
787 default:
788 rc = -EINVAL;
789 goto out;
790 }
791 }
792
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500793 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500794 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500795 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500796 goto out_double_mount;
797 rc = 0;
798 goto out;
799 }
800
James Morris089be432008-07-15 18:32:49 +1000801 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400802 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
803
Stephen Smalley8e014722015-06-04 16:22:17 -0400804 if (!strcmp(sb->s_type->name, "debugfs") ||
805 !strcmp(sb->s_type->name, "sysfs") ||
806 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400807 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500808
David Quigleyeb9ae682013-05-22 12:50:37 -0400809 if (!sbsec->behavior) {
810 /*
811 * Determine the labeling behavior to use for this
812 * filesystem type.
813 */
Paul Moore98f700f2013-09-18 13:52:20 -0400814 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400815 if (rc) {
816 printk(KERN_WARNING
817 "%s: security_fs_use(%s) returned %d\n",
818 __func__, sb->s_type->name, rc);
819 goto out;
820 }
Eric Parisc9180a52007-11-30 13:00:35 -0500821 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500822
823 /*
Stephen Smalley01593d32017-01-09 10:07:31 -0500824 * If this is a user namespace mount and the filesystem type is not
825 * explicitly whitelisted, then no contexts are allowed on the command
826 * line and security labels must be ignored.
Seth Forsheeaad82892016-04-26 14:36:20 -0500827 */
Stephen Smalley01593d32017-01-09 10:07:31 -0500828 if (sb->s_user_ns != &init_user_ns &&
829 strcmp(sb->s_type->name, "tmpfs") &&
830 strcmp(sb->s_type->name, "ramfs") &&
831 strcmp(sb->s_type->name, "devpts")) {
Seth Forsheeaad82892016-04-26 14:36:20 -0500832 if (context_sid || fscontext_sid || rootcontext_sid ||
833 defcontext_sid) {
834 rc = -EACCES;
835 goto out;
836 }
837 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
838 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
839 rc = security_transition_sid(current_sid(), current_sid(),
840 SECCLASS_FILE, NULL,
841 &sbsec->mntpoint_sid);
842 if (rc)
843 goto out;
844 }
845 goto out_set_opts;
846 }
847
Eric Parisc9180a52007-11-30 13:00:35 -0500848 /* sets the context of the superblock for the fs being mounted. */
849 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100850 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500851 if (rc)
852 goto out;
853
854 sbsec->sid = fscontext_sid;
855 }
856
857 /*
858 * Switch to using mount point labeling behavior.
859 * sets the label used on all file below the mountpoint, and will set
860 * the superblock context if not already set.
861 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400862 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
863 sbsec->behavior = SECURITY_FS_USE_NATIVE;
864 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
865 }
866
Eric Parisc9180a52007-11-30 13:00:35 -0500867 if (context_sid) {
868 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100869 rc = may_context_mount_sb_relabel(context_sid, sbsec,
870 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500871 if (rc)
872 goto out;
873 sbsec->sid = context_sid;
874 } else {
David Howells275bb412008-11-14 10:39:19 +1100875 rc = may_context_mount_inode_relabel(context_sid, sbsec,
876 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500877 if (rc)
878 goto out;
879 }
880 if (!rootcontext_sid)
881 rootcontext_sid = context_sid;
882
883 sbsec->mntpoint_sid = context_sid;
884 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
885 }
886
887 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100888 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
889 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500890 if (rc)
891 goto out;
892
893 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500894 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500895 }
896
897 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400898 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
899 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500900 rc = -EINVAL;
901 printk(KERN_WARNING "SELinux: defcontext option is "
902 "invalid for this filesystem type\n");
903 goto out;
904 }
905
906 if (defcontext_sid != sbsec->def_sid) {
907 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100908 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500909 if (rc)
910 goto out;
911 }
912
913 sbsec->def_sid = defcontext_sid;
914 }
915
Seth Forsheeaad82892016-04-26 14:36:20 -0500916out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500917 rc = sb_finish_set_opts(sb);
918out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700919 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500921out_double_mount:
922 rc = -EINVAL;
923 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800924 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500925 goto out;
926}
927
Jeff Layton094f7b62013-04-01 08:14:24 -0400928static int selinux_cmp_sb_context(const struct super_block *oldsb,
929 const struct super_block *newsb)
930{
931 struct superblock_security_struct *old = oldsb->s_security;
932 struct superblock_security_struct *new = newsb->s_security;
933 char oldflags = old->flags & SE_MNTMASK;
934 char newflags = new->flags & SE_MNTMASK;
935
936 if (oldflags != newflags)
937 goto mismatch;
938 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
939 goto mismatch;
940 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
941 goto mismatch;
942 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
943 goto mismatch;
944 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500945 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
946 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400947 if (oldroot->sid != newroot->sid)
948 goto mismatch;
949 }
950 return 0;
951mismatch:
952 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
953 "different security settings for (dev %s, "
954 "type %s)\n", newsb->s_id, newsb->s_type->name);
955 return -EBUSY;
956}
957
958static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500959 struct super_block *newsb)
960{
961 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
962 struct superblock_security_struct *newsbsec = newsb->s_security;
963
964 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
965 int set_context = (oldsbsec->flags & CONTEXT_MNT);
966 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
967
Eric Paris0f5e6422008-04-21 16:24:11 -0400968 /*
969 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400970 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400971 */
Al Viroe8c26252010-03-23 06:36:54 -0400972 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400973 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500974
Eric Parisc9180a52007-11-30 13:00:35 -0500975 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500976 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500977
Jeff Layton094f7b62013-04-01 08:14:24 -0400978 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500979 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400980 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400981
Eric Parisc9180a52007-11-30 13:00:35 -0500982 mutex_lock(&newsbsec->lock);
983
984 newsbsec->flags = oldsbsec->flags;
985
986 newsbsec->sid = oldsbsec->sid;
987 newsbsec->def_sid = oldsbsec->def_sid;
988 newsbsec->behavior = oldsbsec->behavior;
989
990 if (set_context) {
991 u32 sid = oldsbsec->mntpoint_sid;
992
993 if (!set_fscontext)
994 newsbsec->sid = sid;
995 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500996 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500997 newisec->sid = sid;
998 }
999 newsbsec->mntpoint_sid = sid;
1000 }
1001 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001002 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
1003 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -05001004
1005 newisec->sid = oldisec->sid;
1006 }
1007
1008 sb_finish_set_opts(newsb);
1009 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -04001010 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001011}
1012
Adrian Bunk2e1479d2008-03-17 22:29:23 +02001013static int selinux_parse_opts_str(char *options,
1014 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001015{
Eric Parise0007522008-03-05 10:31:54 -05001016 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -05001017 char *context = NULL, *defcontext = NULL;
1018 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -05001019 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001020
Eric Parise0007522008-03-05 10:31:54 -05001021 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001022
1023 /* Standard string-based options. */
1024 while ((p = strsep(&options, "|")) != NULL) {
1025 int token;
1026 substring_t args[MAX_OPT_ARGS];
1027
1028 if (!*p)
1029 continue;
1030
1031 token = match_token(p, tokens, args);
1032
1033 switch (token) {
1034 case Opt_context:
1035 if (context || defcontext) {
1036 rc = -EINVAL;
1037 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1038 goto out_err;
1039 }
1040 context = match_strdup(&args[0]);
1041 if (!context) {
1042 rc = -ENOMEM;
1043 goto out_err;
1044 }
1045 break;
1046
1047 case Opt_fscontext:
1048 if (fscontext) {
1049 rc = -EINVAL;
1050 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1051 goto out_err;
1052 }
1053 fscontext = match_strdup(&args[0]);
1054 if (!fscontext) {
1055 rc = -ENOMEM;
1056 goto out_err;
1057 }
1058 break;
1059
1060 case Opt_rootcontext:
1061 if (rootcontext) {
1062 rc = -EINVAL;
1063 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1064 goto out_err;
1065 }
1066 rootcontext = match_strdup(&args[0]);
1067 if (!rootcontext) {
1068 rc = -ENOMEM;
1069 goto out_err;
1070 }
1071 break;
1072
1073 case Opt_defcontext:
1074 if (context || defcontext) {
1075 rc = -EINVAL;
1076 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1077 goto out_err;
1078 }
1079 defcontext = match_strdup(&args[0]);
1080 if (!defcontext) {
1081 rc = -ENOMEM;
1082 goto out_err;
1083 }
1084 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001085 case Opt_labelsupport:
1086 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001087 default:
1088 rc = -EINVAL;
1089 printk(KERN_WARNING "SELinux: unknown mount option\n");
1090 goto out_err;
1091
1092 }
1093 }
1094
Eric Parise0007522008-03-05 10:31:54 -05001095 rc = -ENOMEM;
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001096 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_KERNEL);
Eric Parise0007522008-03-05 10:31:54 -05001097 if (!opts->mnt_opts)
1098 goto out_err;
1099
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001100 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int),
1101 GFP_KERNEL);
Eric Parise0007522008-03-05 10:31:54 -05001102 if (!opts->mnt_opts_flags) {
1103 kfree(opts->mnt_opts);
1104 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001105 }
1106
Eric Parise0007522008-03-05 10:31:54 -05001107 if (fscontext) {
1108 opts->mnt_opts[num_mnt_opts] = fscontext;
1109 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1110 }
1111 if (context) {
1112 opts->mnt_opts[num_mnt_opts] = context;
1113 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1114 }
1115 if (rootcontext) {
1116 opts->mnt_opts[num_mnt_opts] = rootcontext;
1117 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1118 }
1119 if (defcontext) {
1120 opts->mnt_opts[num_mnt_opts] = defcontext;
1121 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1122 }
1123
1124 opts->num_mnt_opts = num_mnt_opts;
1125 return 0;
1126
Eric Parisc9180a52007-11-30 13:00:35 -05001127out_err:
1128 kfree(context);
1129 kfree(defcontext);
1130 kfree(fscontext);
1131 kfree(rootcontext);
1132 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133}
Eric Parise0007522008-03-05 10:31:54 -05001134/*
1135 * string mount options parsing and call set the sbsec
1136 */
1137static int superblock_doinit(struct super_block *sb, void *data)
1138{
1139 int rc = 0;
1140 char *options = data;
1141 struct security_mnt_opts opts;
1142
1143 security_init_mnt_opts(&opts);
1144
1145 if (!data)
1146 goto out;
1147
1148 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1149
1150 rc = selinux_parse_opts_str(options, &opts);
1151 if (rc)
1152 goto out_err;
1153
1154out:
David Quigley649f6e72013-05-22 12:50:36 -04001155 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001156
1157out_err:
1158 security_free_mnt_opts(&opts);
1159 return rc;
1160}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Adrian Bunk3583a712008-07-22 20:21:23 +03001162static void selinux_write_opts(struct seq_file *m,
1163 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001164{
1165 int i;
1166 char *prefix;
1167
1168 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001169 char *has_comma;
1170
1171 if (opts->mnt_opts[i])
1172 has_comma = strchr(opts->mnt_opts[i], ',');
1173 else
1174 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001175
1176 switch (opts->mnt_opts_flags[i]) {
1177 case CONTEXT_MNT:
1178 prefix = CONTEXT_STR;
1179 break;
1180 case FSCONTEXT_MNT:
1181 prefix = FSCONTEXT_STR;
1182 break;
1183 case ROOTCONTEXT_MNT:
1184 prefix = ROOTCONTEXT_STR;
1185 break;
1186 case DEFCONTEXT_MNT:
1187 prefix = DEFCONTEXT_STR;
1188 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001189 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001190 seq_putc(m, ',');
1191 seq_puts(m, LABELSUPP_STR);
1192 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001193 default:
1194 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001195 return;
Eric Paris2069f452008-07-04 09:47:13 +10001196 };
1197 /* we need a comma before each option */
1198 seq_putc(m, ',');
1199 seq_puts(m, prefix);
1200 if (has_comma)
1201 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001202 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001203 if (has_comma)
1204 seq_putc(m, '\"');
1205 }
1206}
1207
1208static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1209{
1210 struct security_mnt_opts opts;
1211 int rc;
1212
1213 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001214 if (rc) {
1215 /* before policy load we may get EINVAL, don't show anything */
1216 if (rc == -EINVAL)
1217 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001218 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001219 }
Eric Paris2069f452008-07-04 09:47:13 +10001220
1221 selinux_write_opts(m, &opts);
1222
1223 security_free_mnt_opts(&opts);
1224
1225 return rc;
1226}
1227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228static inline u16 inode_mode_to_security_class(umode_t mode)
1229{
1230 switch (mode & S_IFMT) {
1231 case S_IFSOCK:
1232 return SECCLASS_SOCK_FILE;
1233 case S_IFLNK:
1234 return SECCLASS_LNK_FILE;
1235 case S_IFREG:
1236 return SECCLASS_FILE;
1237 case S_IFBLK:
1238 return SECCLASS_BLK_FILE;
1239 case S_IFDIR:
1240 return SECCLASS_DIR;
1241 case S_IFCHR:
1242 return SECCLASS_CHR_FILE;
1243 case S_IFIFO:
1244 return SECCLASS_FIFO_FILE;
1245
1246 }
1247
1248 return SECCLASS_FILE;
1249}
1250
James Morris13402582005-09-30 14:24:34 -04001251static inline int default_protocol_stream(int protocol)
1252{
1253 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1254}
1255
1256static inline int default_protocol_dgram(int protocol)
1257{
1258 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1259}
1260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1262{
Stephen Smalleyda69a532017-01-09 10:07:30 -05001263 int extsockclass = selinux_policycap_extsockclass;
1264
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 switch (family) {
1266 case PF_UNIX:
1267 switch (type) {
1268 case SOCK_STREAM:
1269 case SOCK_SEQPACKET:
1270 return SECCLASS_UNIX_STREAM_SOCKET;
1271 case SOCK_DGRAM:
1272 return SECCLASS_UNIX_DGRAM_SOCKET;
1273 }
1274 break;
1275 case PF_INET:
1276 case PF_INET6:
1277 switch (type) {
1278 case SOCK_STREAM:
Stephen Smalleyda69a532017-01-09 10:07:30 -05001279 case SOCK_SEQPACKET:
James Morris13402582005-09-30 14:24:34 -04001280 if (default_protocol_stream(protocol))
1281 return SECCLASS_TCP_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001282 else if (extsockclass && protocol == IPPROTO_SCTP)
1283 return SECCLASS_SCTP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001284 else
1285 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001287 if (default_protocol_dgram(protocol))
1288 return SECCLASS_UDP_SOCKET;
Stephen Smalleyef379792017-01-09 10:07:31 -05001289 else if (extsockclass && (protocol == IPPROTO_ICMP ||
1290 protocol == IPPROTO_ICMPV6))
Stephen Smalleyda69a532017-01-09 10:07:30 -05001291 return SECCLASS_ICMP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001292 else
1293 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001294 case SOCK_DCCP:
1295 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001296 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return SECCLASS_RAWIP_SOCKET;
1298 }
1299 break;
1300 case PF_NETLINK:
1301 switch (protocol) {
1302 case NETLINK_ROUTE:
1303 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001304 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1306 case NETLINK_NFLOG:
1307 return SECCLASS_NETLINK_NFLOG_SOCKET;
1308 case NETLINK_XFRM:
1309 return SECCLASS_NETLINK_XFRM_SOCKET;
1310 case NETLINK_SELINUX:
1311 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001312 case NETLINK_ISCSI:
1313 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 case NETLINK_AUDIT:
1315 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001316 case NETLINK_FIB_LOOKUP:
1317 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1318 case NETLINK_CONNECTOR:
1319 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1320 case NETLINK_NETFILTER:
1321 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 case NETLINK_DNRTMSG:
1323 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001324 case NETLINK_KOBJECT_UEVENT:
1325 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001326 case NETLINK_GENERIC:
1327 return SECCLASS_NETLINK_GENERIC_SOCKET;
1328 case NETLINK_SCSITRANSPORT:
1329 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1330 case NETLINK_RDMA:
1331 return SECCLASS_NETLINK_RDMA_SOCKET;
1332 case NETLINK_CRYPTO:
1333 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 default:
1335 return SECCLASS_NETLINK_SOCKET;
1336 }
1337 case PF_PACKET:
1338 return SECCLASS_PACKET_SOCKET;
1339 case PF_KEY:
1340 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001341 case PF_APPLETALK:
1342 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
1344
Stephen Smalleyda69a532017-01-09 10:07:30 -05001345 if (extsockclass) {
1346 switch (family) {
1347 case PF_AX25:
1348 return SECCLASS_AX25_SOCKET;
1349 case PF_IPX:
1350 return SECCLASS_IPX_SOCKET;
1351 case PF_NETROM:
1352 return SECCLASS_NETROM_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001353 case PF_ATMPVC:
1354 return SECCLASS_ATMPVC_SOCKET;
1355 case PF_X25:
1356 return SECCLASS_X25_SOCKET;
1357 case PF_ROSE:
1358 return SECCLASS_ROSE_SOCKET;
1359 case PF_DECnet:
1360 return SECCLASS_DECNET_SOCKET;
1361 case PF_ATMSVC:
1362 return SECCLASS_ATMSVC_SOCKET;
1363 case PF_RDS:
1364 return SECCLASS_RDS_SOCKET;
1365 case PF_IRDA:
1366 return SECCLASS_IRDA_SOCKET;
1367 case PF_PPPOX:
1368 return SECCLASS_PPPOX_SOCKET;
1369 case PF_LLC:
1370 return SECCLASS_LLC_SOCKET;
Stephen Smalleyda69a532017-01-09 10:07:30 -05001371 case PF_CAN:
1372 return SECCLASS_CAN_SOCKET;
1373 case PF_TIPC:
1374 return SECCLASS_TIPC_SOCKET;
1375 case PF_BLUETOOTH:
1376 return SECCLASS_BLUETOOTH_SOCKET;
1377 case PF_IUCV:
1378 return SECCLASS_IUCV_SOCKET;
1379 case PF_RXRPC:
1380 return SECCLASS_RXRPC_SOCKET;
1381 case PF_ISDN:
1382 return SECCLASS_ISDN_SOCKET;
1383 case PF_PHONET:
1384 return SECCLASS_PHONET_SOCKET;
1385 case PF_IEEE802154:
1386 return SECCLASS_IEEE802154_SOCKET;
1387 case PF_CAIF:
1388 return SECCLASS_CAIF_SOCKET;
1389 case PF_ALG:
1390 return SECCLASS_ALG_SOCKET;
1391 case PF_NFC:
1392 return SECCLASS_NFC_SOCKET;
1393 case PF_VSOCK:
1394 return SECCLASS_VSOCK_SOCKET;
1395 case PF_KCM:
1396 return SECCLASS_KCM_SOCKET;
1397 case PF_QIPCRTR:
1398 return SECCLASS_QIPCRTR_SOCKET;
Linus Torvalds3051bf32017-02-22 10:15:09 -08001399 case PF_SMC:
1400 return SECCLASS_SMC_SOCKET;
1401#if PF_MAX > 44
Stephen Smalleyda69a532017-01-09 10:07:30 -05001402#error New address family defined, please update this function.
1403#endif
1404 }
1405 }
1406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 return SECCLASS_SOCKET;
1408}
1409
Stephen Smalley134509d2015-06-04 16:22:17 -04001410static int selinux_genfs_get_sid(struct dentry *dentry,
1411 u16 tclass,
1412 u16 flags,
1413 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001415 int rc;
Al Virofc640052016-04-10 01:33:30 -04001416 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001417 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Eric Paris828dfe12008-04-17 13:17:49 -04001419 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 if (!buffer)
1421 return -ENOMEM;
1422
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001423 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1424 if (IS_ERR(path))
1425 rc = PTR_ERR(path);
1426 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001427 if (flags & SE_SBPROC) {
1428 /* each process gets a /proc/PID/ entry. Strip off the
1429 * PID part to get a valid selinux labeling.
1430 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1431 while (path[1] >= '0' && path[1] <= '9') {
1432 path[1] = '/';
1433 path++;
1434 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001435 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001436 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 free_page((unsigned long)buffer);
1439 return rc;
1440}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442/* The inode's security attributes must be initialized before first use. */
1443static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1444{
1445 struct superblock_security_struct *sbsec = NULL;
1446 struct inode_security_struct *isec = inode->i_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001447 u32 task_sid, sid = 0;
1448 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 struct dentry *dentry;
1450#define INITCONTEXTLEN 255
1451 char *context = NULL;
1452 unsigned len = 0;
1453 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001455 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001456 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001458 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001459 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001460 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001462 if (isec->sclass == SECCLASS_FILE)
1463 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1464
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001466 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 /* Defer initialization until selinux_complete_init,
1468 after the initial policy is loaded and the security
1469 server is ready to handle calls. */
1470 spin_lock(&sbsec->isec_lock);
1471 if (list_empty(&isec->list))
1472 list_add(&isec->list, &sbsec->isec_head);
1473 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001474 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 }
1476
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001477 sclass = isec->sclass;
1478 task_sid = isec->task_sid;
1479 sid = isec->sid;
1480 isec->initialized = LABEL_PENDING;
1481 spin_unlock(&isec->lock);
1482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001484 case SECURITY_FS_USE_NATIVE:
1485 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001487 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001488 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 break;
1490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 /* Need a dentry, since the xattr API requires one.
1492 Life would be simpler if we could just pass the inode. */
1493 if (opt_dentry) {
1494 /* Called from d_instantiate or d_splice_alias. */
1495 dentry = dget(opt_dentry);
1496 } else {
1497 /* Called from selinux_complete_init, try to find a dentry. */
1498 dentry = d_find_alias(inode);
1499 }
1500 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001501 /*
1502 * this is can be hit on boot when a file is accessed
1503 * before the policy is loaded. When we load policy we
1504 * may find inodes that have no dentry on the
1505 * sbsec->isec_head list. No reason to complain as these
1506 * will get fixed up the next time we go through
1507 * inode_doinit with a dentry, before these inodes could
1508 * be used again by userspace.
1509 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001510 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 }
1512
1513 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001514 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (!context) {
1516 rc = -ENOMEM;
1517 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001518 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001520 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001521 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001523 kfree(context);
1524
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001526 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 if (rc < 0) {
1528 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001529 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001532 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 if (!context) {
1534 rc = -ENOMEM;
1535 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001536 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001538 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001539 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 }
1541 dput(dentry);
1542 if (rc < 0) {
1543 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001544 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001545 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 -rc, inode->i_sb->s_id, inode->i_ino);
1547 kfree(context);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001548 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 }
1550 /* Map ENODATA to the default file SID */
1551 sid = sbsec->def_sid;
1552 rc = 0;
1553 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001554 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001555 sbsec->def_sid,
1556 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001558 char *dev = inode->i_sb->s_id;
1559 unsigned long ino = inode->i_ino;
1560
1561 if (rc == -EINVAL) {
1562 if (printk_ratelimit())
1563 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1564 "context=%s. This indicates you may need to relabel the inode or the "
1565 "filesystem in question.\n", ino, dev, context);
1566 } else {
1567 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1568 "returned %d for dev=%s ino=%ld\n",
1569 __func__, context, -rc, dev, ino);
1570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 kfree(context);
1572 /* Leave with the unlabeled SID */
1573 rc = 0;
1574 break;
1575 }
1576 }
1577 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 break;
1579 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001580 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 break;
1582 case SECURITY_FS_USE_TRANS:
1583 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001584 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
1586 /* Try to obtain a transition SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001587 rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001589 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001591 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001592 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001593 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001595 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001596 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Stephen Smalley134509d2015-06-04 16:22:17 -04001598 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001599 /* We must have a dentry to determine the label on
1600 * procfs inodes */
1601 if (opt_dentry)
1602 /* Called from d_instantiate or
1603 * d_splice_alias. */
1604 dentry = dget(opt_dentry);
1605 else
1606 /* Called from selinux_complete_init, try to
1607 * find a dentry. */
1608 dentry = d_find_alias(inode);
1609 /*
1610 * This can be hit on boot when a file is accessed
1611 * before the policy is loaded. When we load policy we
1612 * may find inodes that have no dentry on the
1613 * sbsec->isec_head list. No reason to complain as
1614 * these will get fixed up the next time we go through
1615 * inode_doinit() with a dentry, before these inodes
1616 * could be used again by userspace.
1617 */
1618 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001619 goto out;
1620 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001621 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001622 dput(dentry);
1623 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001624 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 }
1626 break;
1627 }
1628
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001629out:
1630 spin_lock(&isec->lock);
1631 if (isec->initialized == LABEL_PENDING) {
1632 if (!sid || rc) {
1633 isec->initialized = LABEL_INVALID;
1634 goto out_unlock;
1635 }
1636
1637 isec->initialized = LABEL_INITIALIZED;
1638 isec->sid = sid;
1639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Eric Paris23970742006-09-25 23:32:01 -07001641out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001642 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 return rc;
1644}
1645
1646/* Convert a Linux signal to an access vector. */
1647static inline u32 signal_to_av(int sig)
1648{
1649 u32 perm = 0;
1650
1651 switch (sig) {
1652 case SIGCHLD:
1653 /* Commonly granted from child to parent. */
1654 perm = PROCESS__SIGCHLD;
1655 break;
1656 case SIGKILL:
1657 /* Cannot be caught or ignored */
1658 perm = PROCESS__SIGKILL;
1659 break;
1660 case SIGSTOP:
1661 /* Cannot be caught or ignored */
1662 perm = PROCESS__SIGSTOP;
1663 break;
1664 default:
1665 /* All other signals. */
1666 perm = PROCESS__SIGNAL;
1667 break;
1668 }
1669
1670 return perm;
1671}
1672
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001673#if CAP_LAST_CAP > 63
1674#error Fix SELinux to handle capabilities > 63.
1675#endif
1676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001678static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001679 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
Thomas Liu2bf49692009-07-14 12:14:09 -04001681 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001682 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001683 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001684 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001685 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001686 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
Eric Paris50c205f2012-04-04 15:01:43 -04001688 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 ad.u.cap = cap;
1690
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001691 switch (CAP_TO_INDEX(cap)) {
1692 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001693 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001694 break;
1695 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001696 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001697 break;
1698 default:
1699 printk(KERN_ERR
1700 "SELinux: out of range capability %d\n", cap);
1701 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001702 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001703 }
Eric Paris06112162008-11-11 22:02:50 +11001704
David Howells275bb412008-11-14 10:39:19 +11001705 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001706 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001707 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001708 if (rc2)
1709 return rc2;
1710 }
Eric Paris06112162008-11-11 22:02:50 +11001711 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712}
1713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714/* Check whether a task has a particular permission to an inode.
1715 The 'adp' parameter is optional and allows other audit
1716 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001717static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 struct inode *inode,
1719 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001720 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001723 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
David Howellse0e81732009-09-02 09:13:40 +01001725 validate_creds(cred);
1726
Eric Paris828dfe12008-04-17 13:17:49 -04001727 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001728 return 0;
1729
David Howells88e67f32008-11-14 10:39:21 +11001730 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 isec = inode->i_security;
1732
Linus Torvalds19e49832013-10-04 12:54:11 -07001733 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734}
1735
1736/* Same as inode_has_perm, but pass explicit audit data containing
1737 the dentry to help the auditing code to more easily generate the
1738 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001739static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 struct dentry *dentry,
1741 u32 av)
1742{
David Howellsc6f493d2015-03-17 22:26:22 +00001743 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001744 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001745
Eric Paris50c205f2012-04-04 15:01:43 -04001746 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001747 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001748 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001749 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001750}
1751
1752/* Same as inode_has_perm, but pass explicit audit data containing
1753 the path to help the auditing code to more easily generate the
1754 pathname if needed. */
1755static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001756 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001757 u32 av)
1758{
David Howellsc6f493d2015-03-17 22:26:22 +00001759 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001760 struct common_audit_data ad;
1761
Eric Paris50c205f2012-04-04 15:01:43 -04001762 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001763 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001764 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001765 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766}
1767
David Howells13f8e982013-06-13 23:37:55 +01001768/* Same as path_has_perm, but uses the inode from the file struct. */
1769static inline int file_path_has_perm(const struct cred *cred,
1770 struct file *file,
1771 u32 av)
1772{
1773 struct common_audit_data ad;
1774
Vivek Goyal43af5de2016-09-09 11:37:49 -04001775 ad.type = LSM_AUDIT_DATA_FILE;
1776 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001777 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001778}
1779
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780/* Check whether a task can use an open file descriptor to
1781 access an inode in a given way. Check access to the
1782 descriptor itself, and then use dentry_has_perm to
1783 check a particular permission to the file.
1784 Access to the descriptor is implicitly granted if it
1785 has the same SID as the process. If av is zero, then
1786 access to the file is not checked, e.g. for cases
1787 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001788static int file_has_perm(const struct cred *cred,
1789 struct file *file,
1790 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001793 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001794 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001795 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 int rc;
1797
Vivek Goyal43af5de2016-09-09 11:37:49 -04001798 ad.type = LSM_AUDIT_DATA_FILE;
1799 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
David Howells275bb412008-11-14 10:39:19 +11001801 if (sid != fsec->sid) {
1802 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 SECCLASS_FD,
1804 FD__USE,
1805 &ad);
1806 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001807 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 }
1809
1810 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001811 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001813 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
David Howells88e67f32008-11-14 10:39:21 +11001815out:
1816 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817}
1818
David Howellsc3c188b2015-07-10 17:19:58 -04001819/*
1820 * Determine the label for an inode that might be unioned.
1821 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001822static int
1823selinux_determine_inode_label(const struct task_security_struct *tsec,
1824 struct inode *dir,
1825 const struct qstr *name, u16 tclass,
1826 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001827{
1828 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001829
1830 if ((sbsec->flags & SE_SBINITIALIZED) &&
1831 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1832 *_new_isid = sbsec->mntpoint_sid;
1833 } else if ((sbsec->flags & SBLABEL_MNT) &&
1834 tsec->create_sid) {
1835 *_new_isid = tsec->create_sid;
1836 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001837 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001838 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1839 name, _new_isid);
1840 }
1841
1842 return 0;
1843}
1844
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845/* Check whether a task can create a file. */
1846static int may_create(struct inode *dir,
1847 struct dentry *dentry,
1848 u16 tclass)
1849{
Paul Moore5fb49872010-04-22 14:46:19 -04001850 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 struct inode_security_struct *dsec;
1852 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001853 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001854 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 int rc;
1856
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001857 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 sbsec = dir->i_sb->s_security;
1859
David Howells275bb412008-11-14 10:39:19 +11001860 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001861
Eric Paris50c205f2012-04-04 15:01:43 -04001862 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001863 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
David Howells275bb412008-11-14 10:39:19 +11001865 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 DIR__ADD_NAME | DIR__SEARCH,
1867 &ad);
1868 if (rc)
1869 return rc;
1870
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001871 rc = selinux_determine_inode_label(current_security(), dir,
1872 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001873 if (rc)
1874 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
David Howells275bb412008-11-14 10:39:19 +11001876 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 if (rc)
1878 return rc;
1879
1880 return avc_has_perm(newsid, sbsec->sid,
1881 SECCLASS_FILESYSTEM,
1882 FILESYSTEM__ASSOCIATE, &ad);
1883}
1884
Eric Paris828dfe12008-04-17 13:17:49 -04001885#define MAY_LINK 0
1886#define MAY_UNLINK 1
1887#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
1889/* Check whether a task can link, unlink, or rmdir a file/directory. */
1890static int may_link(struct inode *dir,
1891 struct dentry *dentry,
1892 int kind)
1893
1894{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001896 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001897 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 u32 av;
1899 int rc;
1900
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001901 dsec = inode_security(dir);
1902 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
Eric Paris50c205f2012-04-04 15:01:43 -04001904 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001905 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
1907 av = DIR__SEARCH;
1908 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001909 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (rc)
1911 return rc;
1912
1913 switch (kind) {
1914 case MAY_LINK:
1915 av = FILE__LINK;
1916 break;
1917 case MAY_UNLINK:
1918 av = FILE__UNLINK;
1919 break;
1920 case MAY_RMDIR:
1921 av = DIR__RMDIR;
1922 break;
1923 default:
Eric Paris744ba352008-04-17 11:52:44 -04001924 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1925 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 return 0;
1927 }
1928
David Howells275bb412008-11-14 10:39:19 +11001929 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 return rc;
1931}
1932
1933static inline int may_rename(struct inode *old_dir,
1934 struct dentry *old_dentry,
1935 struct inode *new_dir,
1936 struct dentry *new_dentry)
1937{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001939 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001940 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 u32 av;
1942 int old_is_dir, new_is_dir;
1943 int rc;
1944
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001945 old_dsec = inode_security(old_dir);
1946 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001947 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001948 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
Eric Paris50c205f2012-04-04 15:01:43 -04001950 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Eric Parisa2694342011-04-25 13:10:27 -04001952 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001953 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1955 if (rc)
1956 return rc;
David Howells275bb412008-11-14 10:39:19 +11001957 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 old_isec->sclass, FILE__RENAME, &ad);
1959 if (rc)
1960 return rc;
1961 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001962 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 old_isec->sclass, DIR__REPARENT, &ad);
1964 if (rc)
1965 return rc;
1966 }
1967
Eric Parisa2694342011-04-25 13:10:27 -04001968 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001970 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001972 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 if (rc)
1974 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001975 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001976 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001977 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001978 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 new_isec->sclass,
1980 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1981 if (rc)
1982 return rc;
1983 }
1984
1985 return 0;
1986}
1987
1988/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001989static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 struct super_block *sb,
1991 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001992 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001995 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001998 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999}
2000
2001/* Convert a Linux mode and permission mask to an access vector. */
2002static inline u32 file_mask_to_av(int mode, int mask)
2003{
2004 u32 av = 0;
2005
Al Virodba19c62011-07-25 20:49:29 -04002006 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 if (mask & MAY_EXEC)
2008 av |= FILE__EXECUTE;
2009 if (mask & MAY_READ)
2010 av |= FILE__READ;
2011
2012 if (mask & MAY_APPEND)
2013 av |= FILE__APPEND;
2014 else if (mask & MAY_WRITE)
2015 av |= FILE__WRITE;
2016
2017 } else {
2018 if (mask & MAY_EXEC)
2019 av |= DIR__SEARCH;
2020 if (mask & MAY_WRITE)
2021 av |= DIR__WRITE;
2022 if (mask & MAY_READ)
2023 av |= DIR__READ;
2024 }
2025
2026 return av;
2027}
2028
2029/* Convert a Linux file to an access vector. */
2030static inline u32 file_to_av(struct file *file)
2031{
2032 u32 av = 0;
2033
2034 if (file->f_mode & FMODE_READ)
2035 av |= FILE__READ;
2036 if (file->f_mode & FMODE_WRITE) {
2037 if (file->f_flags & O_APPEND)
2038 av |= FILE__APPEND;
2039 else
2040 av |= FILE__WRITE;
2041 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002042 if (!av) {
2043 /*
2044 * Special file opened with flags 3 for ioctl-only use.
2045 */
2046 av = FILE__IOCTL;
2047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
2049 return av;
2050}
2051
Eric Paris8b6a5a32008-10-29 17:06:46 -04002052/*
2053 * Convert a file to an access vector and include the correct open
2054 * open permission.
2055 */
2056static inline u32 open_file_to_av(struct file *file)
2057{
2058 u32 av = file_to_av(file);
Stephen Smalleyccb54472017-05-12 12:41:24 -04002059 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002060
Stephen Smalleyccb54472017-05-12 12:41:24 -04002061 if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002062 av |= FILE__OPEN;
2063
Eric Paris8b6a5a32008-10-29 17:06:46 -04002064 return av;
2065}
2066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067/* Hook functions begin here. */
2068
Stephen Smalley79af7302015-01-21 10:54:10 -05002069static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2070{
2071 u32 mysid = current_sid();
2072 u32 mgrsid = task_sid(mgr);
2073
2074 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
2075 BINDER__SET_CONTEXT_MGR, NULL);
2076}
2077
2078static int selinux_binder_transaction(struct task_struct *from,
2079 struct task_struct *to)
2080{
2081 u32 mysid = current_sid();
2082 u32 fromsid = task_sid(from);
2083 u32 tosid = task_sid(to);
2084 int rc;
2085
2086 if (mysid != fromsid) {
2087 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2088 BINDER__IMPERSONATE, NULL);
2089 if (rc)
2090 return rc;
2091 }
2092
2093 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2094 NULL);
2095}
2096
2097static int selinux_binder_transfer_binder(struct task_struct *from,
2098 struct task_struct *to)
2099{
2100 u32 fromsid = task_sid(from);
2101 u32 tosid = task_sid(to);
2102
2103 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2104 NULL);
2105}
2106
2107static int selinux_binder_transfer_file(struct task_struct *from,
2108 struct task_struct *to,
2109 struct file *file)
2110{
2111 u32 sid = task_sid(to);
2112 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002113 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002114 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002115 struct common_audit_data ad;
2116 int rc;
2117
2118 ad.type = LSM_AUDIT_DATA_PATH;
2119 ad.u.path = file->f_path;
2120
2121 if (sid != fsec->sid) {
2122 rc = avc_has_perm(sid, fsec->sid,
2123 SECCLASS_FD,
2124 FD__USE,
2125 &ad);
2126 if (rc)
2127 return rc;
2128 }
2129
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002130 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002131 return 0;
2132
Paul Moore20cdef82016-04-04 14:14:42 -04002133 isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002134 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2135 &ad);
2136}
2137
Ingo Molnar9e488582009-05-07 19:26:19 +10002138static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002139 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002141 u32 sid = current_sid();
2142 u32 csid = task_sid(child);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002143
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002144 if (mode & PTRACE_MODE_READ)
2145 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
2146
2147 return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
David Howells5cd9c582008-08-14 11:37:28 +01002148}
2149
2150static int selinux_ptrace_traceme(struct task_struct *parent)
2151{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002152 return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS,
2153 PROCESS__PTRACE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154}
2155
2156static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002157 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002159 return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS,
2160 PROCESS__GETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161}
2162
David Howellsd84f4f92008-11-14 10:39:23 +11002163static int selinux_capset(struct cred *new, const struct cred *old,
2164 const kernel_cap_t *effective,
2165 const kernel_cap_t *inheritable,
2166 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002168 return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
2169 PROCESS__SETCAP, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170}
2171
James Morris5626d3e2009-01-30 10:05:06 +11002172/*
2173 * (This comment used to live with the selinux_task_setuid hook,
2174 * which was removed).
2175 *
2176 * Since setuid only affects the current process, and since the SELinux
2177 * controls are not based on the Linux identity attributes, SELinux does not
2178 * need to control this operation. However, SELinux does control the use of
2179 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2180 */
2181
Eric Paris6a9de492012-01-03 12:25:14 -05002182static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2183 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002185 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186}
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2189{
David Howells88e67f32008-11-14 10:39:21 +11002190 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 int rc = 0;
2192
2193 if (!sb)
2194 return 0;
2195
2196 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002197 case Q_SYNC:
2198 case Q_QUOTAON:
2199 case Q_QUOTAOFF:
2200 case Q_SETINFO:
2201 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002202 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002203 break;
2204 case Q_GETFMT:
2205 case Q_GETINFO:
2206 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002207 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002208 break;
2209 default:
2210 rc = 0; /* let the kernel handle invalid cmds */
2211 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 }
2213 return rc;
2214}
2215
2216static int selinux_quota_on(struct dentry *dentry)
2217{
David Howells88e67f32008-11-14 10:39:21 +11002218 const struct cred *cred = current_cred();
2219
Eric Paris2875fa02011-04-28 16:04:24 -04002220 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221}
2222
Eric Paris12b30522010-11-15 18:36:29 -05002223static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002226 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2227 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002228 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2229 SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
Kees Cookd78ca3c2010-02-03 15:37:13 -08002230 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2231 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2232 /* Set level of messages printed to console */
2233 case SYSLOG_ACTION_CONSOLE_LEVEL:
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002234 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2235 SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
2236 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 }
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002238 /* All other syslog types */
2239 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
2240 SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241}
2242
2243/*
2244 * Check that a process has enough memory to allocate a new virtual
2245 * mapping. 0 means there is enough memory for the allocation to
2246 * succeed and -ENOMEM implies there is not.
2247 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 * Do not audit the selinux permission check, as this is applied to all
2249 * processes that allocate mappings.
2250 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002251static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252{
2253 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002255 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002256 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if (rc == 0)
2258 cap_sys_admin = 1;
2259
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002260 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261}
2262
2263/* binprm security operations */
2264
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002265static u32 ptrace_parent_sid(void)
Paul Moore0c6181c2016-03-30 21:41:21 -04002266{
2267 u32 sid = 0;
2268 struct task_struct *tracer;
2269
2270 rcu_read_lock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002271 tracer = ptrace_parent(current);
Paul Moore0c6181c2016-03-30 21:41:21 -04002272 if (tracer)
2273 sid = task_sid(tracer);
2274 rcu_read_unlock();
2275
2276 return sid;
2277}
2278
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002279static int check_nnp_nosuid(const struct linux_binprm *bprm,
2280 const struct task_security_struct *old_tsec,
2281 const struct task_security_struct *new_tsec)
2282{
2283 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002284 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002285 int rc;
2286
2287 if (!nnp && !nosuid)
2288 return 0; /* neither NNP nor nosuid */
2289
2290 if (new_tsec->sid == old_tsec->sid)
2291 return 0; /* No change in credentials */
2292
2293 /*
2294 * The only transitions we permit under NNP or nosuid
2295 * are transitions to bounded SIDs, i.e. SIDs that are
2296 * guaranteed to only be allowed a subset of the permissions
2297 * of the current SID.
2298 */
2299 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2300 if (rc) {
2301 /*
2302 * On failure, preserve the errno values for NNP vs nosuid.
2303 * NNP: Operation not permitted for caller.
2304 * nosuid: Permission denied to file.
2305 */
2306 if (nnp)
2307 return -EPERM;
2308 else
2309 return -EACCES;
2310 }
2311 return 0;
2312}
2313
David Howellsa6f76f22008-11-14 10:39:24 +11002314static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315{
David Howellsa6f76f22008-11-14 10:39:24 +11002316 const struct task_security_struct *old_tsec;
2317 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002319 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002320 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 int rc;
2322
David Howellsa6f76f22008-11-14 10:39:24 +11002323 /* SELinux context only depends on initial program or script and not
2324 * the script interpreter */
2325 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 return 0;
2327
David Howellsa6f76f22008-11-14 10:39:24 +11002328 old_tsec = current_security();
2329 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002330 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
2332 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002333 new_tsec->sid = old_tsec->sid;
2334 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Michael LeMay28eba5b2006-06-27 02:53:42 -07002336 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002337 new_tsec->create_sid = 0;
2338 new_tsec->keycreate_sid = 0;
2339 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
David Howellsa6f76f22008-11-14 10:39:24 +11002341 if (old_tsec->exec_sid) {
2342 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002344 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002345
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002346 /* Fail on NNP or nosuid if not an allowed transition. */
2347 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2348 if (rc)
2349 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 } else {
2351 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002352 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002353 SECCLASS_PROCESS, NULL,
2354 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 if (rc)
2356 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002357
2358 /*
2359 * Fallback to old SID on NNP or nosuid if not an allowed
2360 * transition.
2361 */
2362 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2363 if (rc)
2364 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 }
2366
Vivek Goyal43af5de2016-09-09 11:37:49 -04002367 ad.type = LSM_AUDIT_DATA_FILE;
2368 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
David Howellsa6f76f22008-11-14 10:39:24 +11002370 if (new_tsec->sid == old_tsec->sid) {
2371 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2373 if (rc)
2374 return rc;
2375 } else {
2376 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002377 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2379 if (rc)
2380 return rc;
2381
David Howellsa6f76f22008-11-14 10:39:24 +11002382 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2384 if (rc)
2385 return rc;
2386
David Howellsa6f76f22008-11-14 10:39:24 +11002387 /* Check for shared state */
2388 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2389 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2390 SECCLASS_PROCESS, PROCESS__SHARE,
2391 NULL);
2392 if (rc)
2393 return -EPERM;
2394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
David Howellsa6f76f22008-11-14 10:39:24 +11002396 /* Make sure that anyone attempting to ptrace over a task that
2397 * changes its SID has the appropriate permit */
Eric W. Biederman9227dd22017-01-23 17:26:31 +13002398 if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05002399 u32 ptsid = ptrace_parent_sid();
David Howellsa6f76f22008-11-14 10:39:24 +11002400 if (ptsid != 0) {
2401 rc = avc_has_perm(ptsid, new_tsec->sid,
2402 SECCLASS_PROCESS,
2403 PROCESS__PTRACE, NULL);
2404 if (rc)
2405 return -EPERM;
2406 }
2407 }
2408
2409 /* Clear any possibly unsafe personality bits on exec: */
2410 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 }
2412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 return 0;
2414}
2415
Eric Paris828dfe12008-04-17 13:17:49 -04002416static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417{
Paul Moore5fb49872010-04-22 14:46:19 -04002418 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002419 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 int atsecure = 0;
2421
David Howells275bb412008-11-14 10:39:19 +11002422 sid = tsec->sid;
2423 osid = tsec->osid;
2424
2425 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 /* Enable secure mode for SIDs transitions unless
2427 the noatsecure permission is granted between
2428 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002429 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002430 SECCLASS_PROCESS,
2431 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 }
2433
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002434 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435}
2436
Al Viroc3c073f2012-08-21 22:32:06 -04002437static int match_file(const void *p, struct file *file, unsigned fd)
2438{
2439 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2440}
2441
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002443static inline void flush_unauthorized_files(const struct cred *cred,
2444 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002447 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002448 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002449 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002451 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002453 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002454 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002455 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002458 Use file_path_has_perm on the tty path directly
2459 rather than using file_has_perm, as this particular
2460 open file may belong to another process and we are
2461 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002462 file_priv = list_first_entry(&tty->tty_files,
2463 struct tty_file_private, list);
2464 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002465 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002466 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 }
Peter Hurley4a510962016-01-09 21:35:23 -08002468 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002469 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002471 /* Reset controlling tty. */
2472 if (drop_tty)
2473 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
2475 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002476 n = iterate_fd(files, 0, match_file, cred);
2477 if (!n) /* none found? */
2478 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Al Viroc3c073f2012-08-21 22:32:06 -04002480 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002481 if (IS_ERR(devnull))
2482 devnull = NULL;
2483 /* replace all the matching ones with this */
2484 do {
2485 replace_fd(n - 1, devnull, 0);
2486 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2487 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002488 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489}
2490
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491/*
David Howellsa6f76f22008-11-14 10:39:24 +11002492 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 */
David Howellsa6f76f22008-11-14 10:39:24 +11002494static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495{
David Howellsa6f76f22008-11-14 10:39:24 +11002496 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 int rc, i;
2499
David Howellsa6f76f22008-11-14 10:39:24 +11002500 new_tsec = bprm->cred->security;
2501 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 return;
2503
2504 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002505 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
David Howellsa6f76f22008-11-14 10:39:24 +11002507 /* Always clear parent death signal on SID transitions. */
2508 current->pdeath_signal = 0;
2509
2510 /* Check whether the new SID can inherit resource limits from the old
2511 * SID. If not, reset all soft limits to the lower of the current
2512 * task's hard limit and the init task's soft limit.
2513 *
2514 * Note that the setting of hard limits (even to lower them) can be
2515 * controlled by the setrlimit check. The inclusion of the init task's
2516 * soft limit into the computation is to avoid resetting soft limits
2517 * higher than the default soft limit for cases where the default is
2518 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2519 */
2520 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2521 PROCESS__RLIMITINH, NULL);
2522 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002523 /* protect against do_prlimit() */
2524 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002525 for (i = 0; i < RLIM_NLIMITS; i++) {
2526 rlim = current->signal->rlim + i;
2527 initrlim = init_task.signal->rlim + i;
2528 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2529 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002530 task_unlock(current);
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002531 if (IS_ENABLED(CONFIG_POSIX_TIMERS))
2532 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002533 }
2534}
2535
2536/*
2537 * Clean up the process immediately after the installation of new credentials
2538 * due to exec
2539 */
2540static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2541{
2542 const struct task_security_struct *tsec = current_security();
2543 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002544 u32 osid, sid;
2545 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002546
David Howellsa6f76f22008-11-14 10:39:24 +11002547 osid = tsec->osid;
2548 sid = tsec->sid;
2549
2550 if (sid == osid)
2551 return;
2552
2553 /* Check whether the new SID can inherit signal state from the old SID.
2554 * If not, clear itimers to avoid subsequent signal generation and
2555 * flush and unblock signals.
2556 *
2557 * This must occur _after_ the task SID has been updated so that any
2558 * kill done after the flush will be checked against the new SID.
2559 */
2560 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 if (rc) {
Nicolas Pitrebaa73d92016-11-11 00:10:10 -05002562 if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
2563 memset(&itimer, 0, sizeof itimer);
2564 for (i = 0; i < 3; i++)
2565 do_setitimer(i, &itimer, NULL);
2566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002568 if (!fatal_signal_pending(current)) {
2569 flush_sigqueue(&current->pending);
2570 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002571 flush_signal_handlers(current, 1);
2572 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002573 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 spin_unlock_irq(&current->sighand->siglock);
2576 }
2577
David Howellsa6f76f22008-11-14 10:39:24 +11002578 /* Wake up the parent if it is waiting so that it can recheck
2579 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002580 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002581 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002582 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583}
2584
2585/* superblock security operations */
2586
2587static int selinux_sb_alloc_security(struct super_block *sb)
2588{
2589 return superblock_alloc_security(sb);
2590}
2591
2592static void selinux_sb_free_security(struct super_block *sb)
2593{
2594 superblock_free_security(sb);
2595}
2596
2597static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2598{
2599 if (plen > olen)
2600 return 0;
2601
2602 return !memcmp(prefix, option, plen);
2603}
2604
2605static inline int selinux_option(char *option, int len)
2606{
Eric Paris832cbd92008-04-01 13:24:09 -04002607 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2608 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2609 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002610 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2611 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612}
2613
2614static inline void take_option(char **to, char *from, int *first, int len)
2615{
2616 if (!*first) {
2617 **to = ',';
2618 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002619 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 *first = 0;
2621 memcpy(*to, from, len);
2622 *to += len;
2623}
2624
Eric Paris828dfe12008-04-17 13:17:49 -04002625static inline void take_selinux_option(char **to, char *from, int *first,
2626 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002627{
2628 int current_size = 0;
2629
2630 if (!*first) {
2631 **to = '|';
2632 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002633 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002634 *first = 0;
2635
2636 while (current_size < len) {
2637 if (*from != '"') {
2638 **to = *from;
2639 *to += 1;
2640 }
2641 from += 1;
2642 current_size += 1;
2643 }
2644}
2645
Eric Parise0007522008-03-05 10:31:54 -05002646static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647{
2648 int fnosec, fsec, rc = 0;
2649 char *in_save, *in_curr, *in_end;
2650 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002651 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
2653 in_curr = orig;
2654 sec_curr = copy;
2655
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2657 if (!nosec) {
2658 rc = -ENOMEM;
2659 goto out;
2660 }
2661
2662 nosec_save = nosec;
2663 fnosec = fsec = 1;
2664 in_save = in_end = orig;
2665
2666 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002667 if (*in_end == '"')
2668 open_quote = !open_quote;
2669 if ((*in_end == ',' && open_quote == 0) ||
2670 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 int len = in_end - in_curr;
2672
2673 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002674 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 else
2676 take_option(&nosec, in_curr, &fnosec, len);
2677
2678 in_curr = in_end + 1;
2679 }
2680 } while (*in_end++);
2681
Eric Paris6931dfc2005-06-30 02:58:51 -07002682 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002683 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684out:
2685 return rc;
2686}
2687
Eric Paris026eb162011-03-03 16:09:14 -05002688static int selinux_sb_remount(struct super_block *sb, void *data)
2689{
2690 int rc, i, *flags;
2691 struct security_mnt_opts opts;
2692 char *secdata, **mount_options;
2693 struct superblock_security_struct *sbsec = sb->s_security;
2694
2695 if (!(sbsec->flags & SE_SBINITIALIZED))
2696 return 0;
2697
2698 if (!data)
2699 return 0;
2700
2701 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2702 return 0;
2703
2704 security_init_mnt_opts(&opts);
2705 secdata = alloc_secdata();
2706 if (!secdata)
2707 return -ENOMEM;
2708 rc = selinux_sb_copy_data(data, secdata);
2709 if (rc)
2710 goto out_free_secdata;
2711
2712 rc = selinux_parse_opts_str(secdata, &opts);
2713 if (rc)
2714 goto out_free_secdata;
2715
2716 mount_options = opts.mnt_opts;
2717 flags = opts.mnt_opts_flags;
2718
2719 for (i = 0; i < opts.num_mnt_opts; i++) {
2720 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002721
Eric Paris12f348b2012-10-09 10:56:25 -04002722 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002723 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002724 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002725 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002726 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002727 "(%s) failed for (dev %s, type %s) errno=%d\n",
2728 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002729 goto out_free_opts;
2730 }
2731 rc = -EINVAL;
2732 switch (flags[i]) {
2733 case FSCONTEXT_MNT:
2734 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2735 goto out_bad_option;
2736 break;
2737 case CONTEXT_MNT:
2738 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2739 goto out_bad_option;
2740 break;
2741 case ROOTCONTEXT_MNT: {
2742 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002743 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002744
2745 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2746 goto out_bad_option;
2747 break;
2748 }
2749 case DEFCONTEXT_MNT:
2750 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2751 goto out_bad_option;
2752 break;
2753 default:
2754 goto out_free_opts;
2755 }
2756 }
2757
2758 rc = 0;
2759out_free_opts:
2760 security_free_mnt_opts(&opts);
2761out_free_secdata:
2762 free_secdata(secdata);
2763 return rc;
2764out_bad_option:
2765 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002766 "during remount (dev %s, type=%s)\n", sb->s_id,
2767 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002768 goto out_free_opts;
2769}
2770
James Morris12204e22008-12-19 10:44:42 +11002771static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772{
David Howells88e67f32008-11-14 10:39:21 +11002773 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002774 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 int rc;
2776
2777 rc = superblock_doinit(sb, data);
2778 if (rc)
2779 return rc;
2780
James Morris74192242008-12-19 11:41:10 +11002781 /* Allow all mounts performed by the kernel */
2782 if (flags & MS_KERNMOUNT)
2783 return 0;
2784
Eric Paris50c205f2012-04-04 15:01:43 -04002785 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002786 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002787 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788}
2789
David Howells726c3342006-06-23 02:02:58 -07002790static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
David Howells88e67f32008-11-14 10:39:21 +11002792 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002793 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Eric Paris50c205f2012-04-04 15:01:43 -04002795 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002796 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002797 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798}
2799
Al Viro808d4e32012-10-11 11:42:01 -04002800static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002801 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002802 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002803 unsigned long flags,
2804 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805{
David Howells88e67f32008-11-14 10:39:21 +11002806 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
2808 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002809 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002810 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 else
Eric Paris2875fa02011-04-28 16:04:24 -04002812 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813}
2814
2815static int selinux_umount(struct vfsmount *mnt, int flags)
2816{
David Howells88e67f32008-11-14 10:39:21 +11002817 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
David Howells88e67f32008-11-14 10:39:21 +11002819 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002820 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821}
2822
2823/* inode security operations */
2824
2825static int selinux_inode_alloc_security(struct inode *inode)
2826{
2827 return inode_alloc_security(inode);
2828}
2829
2830static void selinux_inode_free_security(struct inode *inode)
2831{
2832 inode_free_security(inode);
2833}
2834
David Quigleyd47be3d2013-05-22 12:50:34 -04002835static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002836 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002837 u32 *ctxlen)
2838{
David Quigleyd47be3d2013-05-22 12:50:34 -04002839 u32 newsid;
2840 int rc;
2841
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002842 rc = selinux_determine_inode_label(current_security(),
2843 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002844 inode_mode_to_security_class(mode),
2845 &newsid);
2846 if (rc)
2847 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002848
2849 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2850}
2851
Vivek Goyala518b0a2016-07-13 10:44:53 -04002852static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2853 struct qstr *name,
2854 const struct cred *old,
2855 struct cred *new)
2856{
2857 u32 newsid;
2858 int rc;
2859 struct task_security_struct *tsec;
2860
2861 rc = selinux_determine_inode_label(old->security,
2862 d_inode(dentry->d_parent), name,
2863 inode_mode_to_security_class(mode),
2864 &newsid);
2865 if (rc)
2866 return rc;
2867
2868 tsec = new->security;
2869 tsec->create_sid = newsid;
2870 return 0;
2871}
2872
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002873static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002874 const struct qstr *qstr,
2875 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002876 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002877{
Paul Moore5fb49872010-04-22 14:46:19 -04002878 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002879 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002880 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002881 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002882 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002883
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002884 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002885
David Howells275bb412008-11-14 10:39:19 +11002886 sid = tsec->sid;
2887 newsid = tsec->create_sid;
2888
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002889 rc = selinux_determine_inode_label(current_security(),
David Howellsc3c188b2015-07-10 17:19:58 -04002890 dir, qstr,
2891 inode_mode_to_security_class(inode->i_mode),
2892 &newsid);
2893 if (rc)
2894 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002895
Eric Paris296fddf2006-09-25 23:32:00 -07002896 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002897 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002898 struct inode_security_struct *isec = inode->i_security;
2899 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2900 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002901 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002902 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002903
Eric Paris12f348b2012-10-09 10:56:25 -04002904 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002905 return -EOPNOTSUPP;
2906
Tetsuo Handa95489062013-07-25 05:44:02 +09002907 if (name)
2908 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002909
2910 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002911 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002912 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002913 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002914 *value = context;
2915 *len = clen;
2916 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002917
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002918 return 0;
2919}
2920
Al Viro4acdaf22011-07-26 01:42:34 -04002921static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922{
2923 return may_create(dir, dentry, SECCLASS_FILE);
2924}
2925
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2927{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 return may_link(dir, old_dentry, MAY_LINK);
2929}
2930
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2932{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 return may_link(dir, dentry, MAY_UNLINK);
2934}
2935
2936static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2937{
2938 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2939}
2940
Al Viro18bb1db2011-07-26 01:41:39 -04002941static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942{
2943 return may_create(dir, dentry, SECCLASS_DIR);
2944}
2945
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2947{
2948 return may_link(dir, dentry, MAY_RMDIR);
2949}
2950
Al Viro1a67aaf2011-07-26 01:52:52 -04002951static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2954}
2955
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002957 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958{
2959 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2960}
2961
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962static int selinux_inode_readlink(struct dentry *dentry)
2963{
David Howells88e67f32008-11-14 10:39:21 +11002964 const struct cred *cred = current_cred();
2965
Eric Paris2875fa02011-04-28 16:04:24 -04002966 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967}
2968
NeilBrownbda0be72015-03-23 13:37:39 +11002969static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2970 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971{
David Howells88e67f32008-11-14 10:39:21 +11002972 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002973 struct common_audit_data ad;
2974 struct inode_security_struct *isec;
2975 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
NeilBrownbda0be72015-03-23 13:37:39 +11002977 validate_creds(cred);
2978
2979 ad.type = LSM_AUDIT_DATA_DENTRY;
2980 ad.u.dentry = dentry;
2981 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002982 isec = inode_security_rcu(inode, rcu);
2983 if (IS_ERR(isec))
2984 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002985
2986 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2987 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988}
2989
Eric Parisd4cf970d2012-04-04 15:01:42 -04002990static noinline int audit_inode_permission(struct inode *inode,
2991 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002992 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002993 unsigned flags)
2994{
2995 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002996 struct inode_security_struct *isec = inode->i_security;
2997 int rc;
2998
Eric Paris50c205f2012-04-04 15:01:43 -04002999 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003000 ad.u.inode = inode;
3001
3002 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07003003 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003004 if (rc)
3005 return rc;
3006 return 0;
3007}
3008
Al Viroe74f71e2011-06-20 19:38:15 -04003009static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010{
David Howells88e67f32008-11-14 10:39:21 +11003011 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003012 u32 perms;
3013 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04003014 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003015 struct inode_security_struct *isec;
3016 u32 sid;
3017 struct av_decision avd;
3018 int rc, rc2;
3019 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
Eric Parisb782e0a2010-07-23 11:44:03 -04003021 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003022 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3023
Eric Parisb782e0a2010-07-23 11:44:03 -04003024 /* No permission to check. Existence test. */
3025 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
Eric Paris2e334052012-04-04 15:01:42 -04003028 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003029
Eric Paris2e334052012-04-04 15:01:42 -04003030 if (unlikely(IS_PRIVATE(inode)))
3031 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003032
3033 perms = file_mask_to_av(inode->i_mode, mask);
3034
Eric Paris2e334052012-04-04 15:01:42 -04003035 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003036 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
3037 if (IS_ERR(isec))
3038 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003039
3040 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
3041 audited = avc_audit_required(perms, &avd, rc,
3042 from_access ? FILE__AUDIT_ACCESS : 0,
3043 &denied);
3044 if (likely(!audited))
3045 return rc;
3046
Stephen Smalley626b9742014-04-29 11:29:04 -07003047 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04003048 if (rc2)
3049 return rc2;
3050 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051}
3052
3053static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3054{
David Howells88e67f32008-11-14 10:39:21 +11003055 const struct cred *cred = current_cred();
Stephen Smalleyccb54472017-05-12 12:41:24 -04003056 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003057 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003058 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003060 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3061 if (ia_valid & ATTR_FORCE) {
3062 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3063 ATTR_FORCE);
3064 if (!ia_valid)
3065 return 0;
3066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003068 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3069 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003070 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
Stephen Smalleyccb54472017-05-12 12:41:24 -04003072 if (selinux_policycap_openperm &&
3073 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3074 (ia_valid & ATTR_SIZE) &&
3075 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003076 av |= FILE__OPEN;
3077
3078 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079}
3080
Al Viro3f7036a2015-03-08 19:28:30 -04003081static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082{
Al Viro3f7036a2015-03-08 19:28:30 -04003083 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084}
3085
David Howells8f0cfa52008-04-29 00:59:41 -07003086static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07003087{
David Howells88e67f32008-11-14 10:39:21 +11003088 const struct cred *cred = current_cred();
3089
Serge E. Hallynb5376772007-10-16 23:31:36 -07003090 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3091 sizeof XATTR_SECURITY_PREFIX - 1)) {
3092 if (!strcmp(name, XATTR_NAME_CAPS)) {
3093 if (!capable(CAP_SETFCAP))
3094 return -EPERM;
3095 } else if (!capable(CAP_SYS_ADMIN)) {
3096 /* A different attribute in the security namespace.
3097 Restrict to administrator. */
3098 return -EPERM;
3099 }
3100 }
3101
3102 /* Not an attribute we recognize, so just check the
3103 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04003104 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003105}
3106
Stephen Smalleydb590002017-04-20 11:31:30 -04003107static bool has_cap_mac_admin(bool audit)
3108{
3109 const struct cred *cred = current_cred();
3110 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3111
3112 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3113 return false;
3114 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3115 return false;
3116 return true;
3117}
3118
David Howells8f0cfa52008-04-29 00:59:41 -07003119static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3120 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121{
David Howellsc6f493d2015-03-17 22:26:22 +00003122 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003123 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003125 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003126 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 int rc = 0;
3128
Serge E. Hallynb5376772007-10-16 23:31:36 -07003129 if (strcmp(name, XATTR_NAME_SELINUX))
3130 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003133 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 return -EOPNOTSUPP;
3135
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003136 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 return -EPERM;
3138
Eric Paris50c205f2012-04-04 15:01:43 -04003139 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003140 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141
Paul Moore20cdef82016-04-04 14:14:42 -04003142 isec = backing_inode_security(dentry);
David Howells275bb412008-11-14 10:39:19 +11003143 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 FILE__RELABELFROM, &ad);
3145 if (rc)
3146 return rc;
3147
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003148 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003149 if (rc == -EINVAL) {
Stephen Smalleydb590002017-04-20 11:31:30 -04003150 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003151 struct audit_buffer *ab;
3152 size_t audit_size;
3153 const char *str;
3154
3155 /* We strip a nul only if it is at the end, otherwise the
3156 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003157 if (value) {
3158 str = value;
3159 if (str[size - 1] == '\0')
3160 audit_size = size - 1;
3161 else
3162 audit_size = size;
3163 } else {
3164 str = "";
3165 audit_size = 0;
3166 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003167 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3168 audit_log_format(ab, "op=setxattr invalid_context=");
3169 audit_log_n_untrustedstring(ab, value, audit_size);
3170 audit_log_end(ab);
3171
Stephen Smalley12b29f32008-05-07 13:03:20 -04003172 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003173 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003174 rc = security_context_to_sid_force(value, size, &newsid);
3175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 if (rc)
3177 return rc;
3178
David Howells275bb412008-11-14 10:39:19 +11003179 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 FILE__RELABELTO, &ad);
3181 if (rc)
3182 return rc;
3183
David Howells275bb412008-11-14 10:39:19 +11003184 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003185 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 if (rc)
3187 return rc;
3188
3189 return avc_has_perm(newsid,
3190 sbsec->sid,
3191 SECCLASS_FILESYSTEM,
3192 FILESYSTEM__ASSOCIATE,
3193 &ad);
3194}
3195
David Howells8f0cfa52008-04-29 00:59:41 -07003196static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003197 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003198 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199{
David Howellsc6f493d2015-03-17 22:26:22 +00003200 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003201 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 u32 newsid;
3203 int rc;
3204
3205 if (strcmp(name, XATTR_NAME_SELINUX)) {
3206 /* Not an attribute we recognize, so nothing to do. */
3207 return;
3208 }
3209
Stephen Smalley12b29f32008-05-07 13:03:20 -04003210 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003212 printk(KERN_ERR "SELinux: unable to map context to SID"
3213 "for (%s, %lu), rc=%d\n",
3214 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 return;
3216 }
3217
Paul Moore20cdef82016-04-04 14:14:42 -04003218 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003219 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003220 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003222 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003223 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003224
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 return;
3226}
3227
David Howells8f0cfa52008-04-29 00:59:41 -07003228static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229{
David Howells88e67f32008-11-14 10:39:21 +11003230 const struct cred *cred = current_cred();
3231
Eric Paris2875fa02011-04-28 16:04:24 -04003232 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233}
3234
Eric Paris828dfe12008-04-17 13:17:49 -04003235static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236{
David Howells88e67f32008-11-14 10:39:21 +11003237 const struct cred *cred = current_cred();
3238
Eric Paris2875fa02011-04-28 16:04:24 -04003239 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240}
3241
David Howells8f0cfa52008-04-29 00:59:41 -07003242static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003244 if (strcmp(name, XATTR_NAME_SELINUX))
3245 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
3247 /* No one is allowed to remove a SELinux security label.
3248 You can change the label, but all data must be labeled. */
3249 return -EACCES;
3250}
3251
James Morrisd381d8a2005-10-30 14:59:22 -08003252/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003253 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003254 *
3255 * Permission check is handled by selinux_inode_getxattr hook.
3256 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003257static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258{
David P. Quigley42492592008-02-04 22:29:39 -08003259 u32 size;
3260 int error;
3261 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003262 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003264 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3265 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003267 /*
3268 * If the caller has CAP_MAC_ADMIN, then get the raw context
3269 * value even if it is not defined by current policy; otherwise,
3270 * use the in-core value under current policy.
3271 * Use the non-auditing forms of the permission checks since
3272 * getxattr may be called by unprivileged processes commonly
3273 * and lack of permission just means that we fall back to the
3274 * in-core context value, not a denial.
3275 */
Paul Moore20cdef82016-04-04 14:14:42 -04003276 isec = inode_security(inode);
Stephen Smalleydb590002017-04-20 11:31:30 -04003277 if (has_cap_mac_admin(false))
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003278 error = security_sid_to_context_force(isec->sid, &context,
3279 &size);
3280 else
3281 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003282 if (error)
3283 return error;
3284 error = size;
3285 if (alloc) {
3286 *buffer = context;
3287 goto out_nofree;
3288 }
3289 kfree(context);
3290out_nofree:
3291 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292}
3293
3294static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003295 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296{
Paul Moore2c971652016-04-19 16:36:28 -04003297 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 u32 newsid;
3299 int rc;
3300
3301 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3302 return -EOPNOTSUPP;
3303
3304 if (!value || !size)
3305 return -EACCES;
3306
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003307 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308 if (rc)
3309 return rc;
3310
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003311 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003312 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003314 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003315 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 return 0;
3317}
3318
3319static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3320{
3321 const int len = sizeof(XATTR_NAME_SELINUX);
3322 if (buffer && len <= buffer_size)
3323 memcpy(buffer, XATTR_NAME_SELINUX, len);
3324 return len;
3325}
3326
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003327static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003328{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003329 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003330 *secid = isec->sid;
3331}
3332
Vivek Goyal56909eb2016-07-13 10:44:48 -04003333static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3334{
3335 u32 sid;
3336 struct task_security_struct *tsec;
3337 struct cred *new_creds = *new;
3338
3339 if (new_creds == NULL) {
3340 new_creds = prepare_creds();
3341 if (!new_creds)
3342 return -ENOMEM;
3343 }
3344
3345 tsec = new_creds->security;
3346 /* Get label from overlay inode and set it in create_sid */
3347 selinux_inode_getsecid(d_inode(src), &sid);
3348 tsec->create_sid = sid;
3349 *new = new_creds;
3350 return 0;
3351}
3352
Vivek Goyal19472b62016-07-13 10:44:50 -04003353static int selinux_inode_copy_up_xattr(const char *name)
3354{
3355 /* The copy_up hook above sets the initial context on an inode, but we
3356 * don't then want to overwrite it by blindly copying all the lower
3357 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3358 */
3359 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3360 return 1; /* Discard */
3361 /*
3362 * Any other attribute apart from SELINUX is not claimed, supported
3363 * by selinux.
3364 */
3365 return -EOPNOTSUPP;
3366}
3367
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368/* file security operations */
3369
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003370static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371{
David Howells88e67f32008-11-14 10:39:21 +11003372 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003373 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3376 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3377 mask |= MAY_APPEND;
3378
Paul Moore389fb8002009-03-27 17:10:34 -04003379 return file_has_perm(cred, file,
3380 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381}
3382
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003383static int selinux_file_permission(struct file *file, int mask)
3384{
Al Viro496ad9a2013-01-23 17:07:38 -05003385 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003386 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003387 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003388 u32 sid = current_sid();
3389
Paul Moore389fb8002009-03-27 17:10:34 -04003390 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003391 /* No permission to check. Existence test. */
3392 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003393
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003394 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003395 if (sid == fsec->sid && fsec->isid == isec->sid &&
3396 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003397 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003398 return 0;
3399
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003400 return selinux_revalidate_file_permission(file, mask);
3401}
3402
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403static int selinux_file_alloc_security(struct file *file)
3404{
3405 return file_alloc_security(file);
3406}
3407
3408static void selinux_file_free_security(struct file *file)
3409{
3410 file_free_security(file);
3411}
3412
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003413/*
3414 * Check whether a task has the ioctl permission and cmd
3415 * operation to an inode.
3416 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003417static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003418 u32 requested, u16 cmd)
3419{
3420 struct common_audit_data ad;
3421 struct file_security_struct *fsec = file->f_security;
3422 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003423 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003424 struct lsm_ioctlop_audit ioctl;
3425 u32 ssid = cred_sid(cred);
3426 int rc;
3427 u8 driver = cmd >> 8;
3428 u8 xperm = cmd & 0xff;
3429
3430 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3431 ad.u.op = &ioctl;
3432 ad.u.op->cmd = cmd;
3433 ad.u.op->path = file->f_path;
3434
3435 if (ssid != fsec->sid) {
3436 rc = avc_has_perm(ssid, fsec->sid,
3437 SECCLASS_FD,
3438 FD__USE,
3439 &ad);
3440 if (rc)
3441 goto out;
3442 }
3443
3444 if (unlikely(IS_PRIVATE(inode)))
3445 return 0;
3446
Paul Moore20cdef82016-04-04 14:14:42 -04003447 isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003448 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3449 requested, driver, xperm, &ad);
3450out:
3451 return rc;
3452}
3453
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3455 unsigned long arg)
3456{
David Howells88e67f32008-11-14 10:39:21 +11003457 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003458 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
Eric Paris0b24dcb2011-02-25 15:39:20 -05003460 switch (cmd) {
3461 case FIONREAD:
3462 /* fall through */
3463 case FIBMAP:
3464 /* fall through */
3465 case FIGETBSZ:
3466 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003467 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003468 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003469 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003470 error = file_has_perm(cred, file, FILE__GETATTR);
3471 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472
Al Viro2f99c362012-03-23 16:04:05 -04003473 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003474 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003475 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003476 error = file_has_perm(cred, file, FILE__SETATTR);
3477 break;
3478
3479 /* sys_ioctl() checks */
3480 case FIONBIO:
3481 /* fall through */
3482 case FIOASYNC:
3483 error = file_has_perm(cred, file, 0);
3484 break;
3485
3486 case KDSKBENT:
3487 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003488 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003489 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003490 break;
3491
3492 /* default case assumes that the command will go
3493 * to the file's ioctl() function.
3494 */
3495 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003496 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003497 }
3498 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499}
3500
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003501static int default_noexec;
3502
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3504{
David Howells88e67f32008-11-14 10:39:21 +11003505 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003506 u32 sid = cred_sid(cred);
David Howellsd84f4f92008-11-14 10:39:23 +11003507 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003508
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003509 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003510 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3511 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 /*
3513 * We are making executable an anonymous mapping or a
3514 * private file mapping that will also be writable.
3515 * This has an additional check.
3516 */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003517 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3518 PROCESS__EXECMEM, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003520 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522
3523 if (file) {
3524 /* read access is always possible with a mapping */
3525 u32 av = FILE__READ;
3526
3527 /* write access only matters if the mapping is shared */
3528 if (shared && (prot & PROT_WRITE))
3529 av |= FILE__WRITE;
3530
3531 if (prot & PROT_EXEC)
3532 av |= FILE__EXECUTE;
3533
David Howells88e67f32008-11-14 10:39:21 +11003534 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 }
David Howellsd84f4f92008-11-14 10:39:23 +11003536
3537error:
3538 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539}
3540
Al Viroe5467852012-05-30 13:30:51 -04003541static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003543 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003544
3545 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3546 u32 sid = current_sid();
3547 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3548 MEMPROTECT__MMAP_ZERO, NULL);
3549 }
3550
3551 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003552}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553
Al Viroe5467852012-05-30 13:30:51 -04003554static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3555 unsigned long prot, unsigned long flags)
3556{
Stephen Smalley3ba4bf52017-05-05 09:14:48 -04003557 struct common_audit_data ad;
3558 int rc;
3559
3560 if (file) {
3561 ad.type = LSM_AUDIT_DATA_FILE;
3562 ad.u.file = file;
3563 rc = inode_has_perm(current_cred(), file_inode(file),
3564 FILE__MAP, &ad);
3565 if (rc)
3566 return rc;
3567 }
3568
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 if (selinux_checkreqprot)
3570 prot = reqprot;
3571
3572 return file_map_prot_check(file, prot,
3573 (flags & MAP_TYPE) == MAP_SHARED);
3574}
3575
3576static int selinux_file_mprotect(struct vm_area_struct *vma,
3577 unsigned long reqprot,
3578 unsigned long prot)
3579{
David Howells88e67f32008-11-14 10:39:21 +11003580 const struct cred *cred = current_cred();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003581 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
3583 if (selinux_checkreqprot)
3584 prot = reqprot;
3585
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003586 if (default_noexec &&
3587 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003588 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003589 if (vma->vm_start >= vma->vm_mm->start_brk &&
3590 vma->vm_end <= vma->vm_mm->brk) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003591 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3592 PROCESS__EXECHEAP, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003593 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003594 ((vma->vm_start <= vma->vm_mm->start_stack &&
3595 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003596 vma_is_stack_for_current(vma))) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003597 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
3598 PROCESS__EXECSTACK, NULL);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003599 } else if (vma->vm_file && vma->anon_vma) {
3600 /*
3601 * We are making executable a file mapping that has
3602 * had some COW done. Since pages might have been
3603 * written, check ability to execute the possibly
3604 * modified content. This typically should only
3605 * occur for text relocations.
3606 */
David Howellsd84f4f92008-11-14 10:39:23 +11003607 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003608 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003609 if (rc)
3610 return rc;
3611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
3613 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3614}
3615
3616static int selinux_file_lock(struct file *file, unsigned int cmd)
3617{
David Howells88e67f32008-11-14 10:39:21 +11003618 const struct cred *cred = current_cred();
3619
3620 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621}
3622
3623static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3624 unsigned long arg)
3625{
David Howells88e67f32008-11-14 10:39:21 +11003626 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 int err = 0;
3628
3629 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003630 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003631 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003632 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003634 }
3635 /* fall through */
3636 case F_SETOWN:
3637 case F_SETSIG:
3638 case F_GETFL:
3639 case F_GETOWN:
3640 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003641 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003642 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003643 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003644 break;
3645 case F_GETLK:
3646 case F_SETLK:
3647 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003648 case F_OFD_GETLK:
3649 case F_OFD_SETLK:
3650 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003652 case F_GETLK64:
3653 case F_SETLK64:
3654 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655#endif
David Howells88e67f32008-11-14 10:39:21 +11003656 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003657 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 }
3659
3660 return err;
3661}
3662
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003663static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 struct file_security_struct *fsec;
3666
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003668 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669}
3670
3671static int selinux_file_send_sigiotask(struct task_struct *tsk,
3672 struct fown_struct *fown, int signum)
3673{
Eric Paris828dfe12008-04-17 13:17:49 -04003674 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003675 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 struct file_security_struct *fsec;
3678
3679 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003680 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 fsec = file->f_security;
3683
3684 if (!signum)
3685 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3686 else
3687 perm = signal_to_av(signum);
3688
David Howells275bb412008-11-14 10:39:19 +11003689 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 SECCLASS_PROCESS, perm, NULL);
3691}
3692
3693static int selinux_file_receive(struct file *file)
3694{
David Howells88e67f32008-11-14 10:39:21 +11003695 const struct cred *cred = current_cred();
3696
3697 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698}
3699
Eric Paris83d49852012-04-04 13:45:40 -04003700static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003701{
3702 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003703 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003704
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003705 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003706 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003707 /*
3708 * Save inode label and policy sequence number
3709 * at open-time so that selinux_file_permission
3710 * can determine whether revalidation is necessary.
3711 * Task label is already saved in the file security
3712 * struct as its SID.
3713 */
3714 fsec->isid = isec->sid;
3715 fsec->pseqno = avc_policy_seqno();
3716 /*
3717 * Since the inode label or policy seqno may have changed
3718 * between the selinux_inode_permission check and the saving
3719 * of state above, recheck that access is still permitted.
3720 * Otherwise, access might never be revalidated against the
3721 * new inode label or new policy.
3722 * This check is not redundant - do not remove.
3723 */
David Howells13f8e982013-06-13 23:37:55 +01003724 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003725}
3726
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727/* task security operations */
3728
Tetsuo Handaa79be232017-03-28 23:08:45 +09003729static int selinux_task_alloc(struct task_struct *task,
3730 unsigned long clone_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003732 u32 sid = current_sid();
3733
3734 return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735}
3736
David Howellsf1752ee2008-11-14 10:39:17 +11003737/*
David Howellsee18d642009-09-02 09:14:21 +01003738 * allocate the SELinux part of blank credentials
3739 */
3740static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3741{
3742 struct task_security_struct *tsec;
3743
3744 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3745 if (!tsec)
3746 return -ENOMEM;
3747
3748 cred->security = tsec;
3749 return 0;
3750}
3751
3752/*
David Howellsf1752ee2008-11-14 10:39:17 +11003753 * detach and free the LSM part of a set of credentials
3754 */
3755static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756{
David Howellsf1752ee2008-11-14 10:39:17 +11003757 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003758
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003759 /*
3760 * cred->security == NULL if security_cred_alloc_blank() or
3761 * security_prepare_creds() returned an error.
3762 */
3763 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003764 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003765 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766}
3767
David Howellsd84f4f92008-11-14 10:39:23 +11003768/*
3769 * prepare a new set of credentials for modification
3770 */
3771static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3772 gfp_t gfp)
3773{
3774 const struct task_security_struct *old_tsec;
3775 struct task_security_struct *tsec;
3776
3777 old_tsec = old->security;
3778
3779 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3780 if (!tsec)
3781 return -ENOMEM;
3782
3783 new->security = tsec;
3784 return 0;
3785}
3786
3787/*
David Howellsee18d642009-09-02 09:14:21 +01003788 * transfer the SELinux data to a blank set of creds
3789 */
3790static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3791{
3792 const struct task_security_struct *old_tsec = old->security;
3793 struct task_security_struct *tsec = new->security;
3794
3795 *tsec = *old_tsec;
3796}
3797
3798/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003799 * set the security data for a kernel service
3800 * - all the creation contexts are set to unlabelled
3801 */
3802static int selinux_kernel_act_as(struct cred *new, u32 secid)
3803{
3804 struct task_security_struct *tsec = new->security;
3805 u32 sid = current_sid();
3806 int ret;
3807
3808 ret = avc_has_perm(sid, secid,
3809 SECCLASS_KERNEL_SERVICE,
3810 KERNEL_SERVICE__USE_AS_OVERRIDE,
3811 NULL);
3812 if (ret == 0) {
3813 tsec->sid = secid;
3814 tsec->create_sid = 0;
3815 tsec->keycreate_sid = 0;
3816 tsec->sockcreate_sid = 0;
3817 }
3818 return ret;
3819}
3820
3821/*
3822 * set the file creation context in a security record to the same as the
3823 * objective context of the specified inode
3824 */
3825static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3826{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003827 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003828 struct task_security_struct *tsec = new->security;
3829 u32 sid = current_sid();
3830 int ret;
3831
3832 ret = avc_has_perm(sid, isec->sid,
3833 SECCLASS_KERNEL_SERVICE,
3834 KERNEL_SERVICE__CREATE_FILES_AS,
3835 NULL);
3836
3837 if (ret == 0)
3838 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003839 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003840}
3841
Eric Parisdd8dbf22009-11-03 16:35:32 +11003842static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003843{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003844 struct common_audit_data ad;
3845
Eric Paris50c205f2012-04-04 15:01:43 -04003846 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003847 ad.u.kmod_name = kmod_name;
3848
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003849 return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
Eric Parisdd8dbf22009-11-03 16:35:32 +11003850 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003851}
3852
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003853static int selinux_kernel_module_from_file(struct file *file)
3854{
3855 struct common_audit_data ad;
3856 struct inode_security_struct *isec;
3857 struct file_security_struct *fsec;
3858 u32 sid = current_sid();
3859 int rc;
3860
3861 /* init_module */
3862 if (file == NULL)
3863 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
3864 SYSTEM__MODULE_LOAD, NULL);
3865
3866 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003867
Vivek Goyal43af5de2016-09-09 11:37:49 -04003868 ad.type = LSM_AUDIT_DATA_FILE;
3869 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003870
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003871 fsec = file->f_security;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003872 if (sid != fsec->sid) {
3873 rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
3874 if (rc)
3875 return rc;
3876 }
3877
Paul Moore20cdef82016-04-04 14:14:42 -04003878 isec = inode_security(file_inode(file));
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003879 return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
3880 SYSTEM__MODULE_LOAD, &ad);
3881}
3882
3883static int selinux_kernel_read_file(struct file *file,
3884 enum kernel_read_file_id id)
3885{
3886 int rc = 0;
3887
3888 switch (id) {
3889 case READING_MODULE:
3890 rc = selinux_kernel_module_from_file(file);
3891 break;
3892 default:
3893 break;
3894 }
3895
3896 return rc;
3897}
3898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3900{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003901 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3902 PROCESS__SETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903}
3904
3905static int selinux_task_getpgid(struct task_struct *p)
3906{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003907 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3908 PROCESS__GETPGID, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909}
3910
3911static int selinux_task_getsid(struct task_struct *p)
3912{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003913 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3914 PROCESS__GETSESSION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915}
3916
David Quigleyf9008e4c2006-06-30 01:55:46 -07003917static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3918{
David Howells275bb412008-11-14 10:39:19 +11003919 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003920}
3921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922static int selinux_task_setnice(struct task_struct *p, int nice)
3923{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003924 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3925 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926}
3927
James Morris03e68062006-06-23 02:03:58 -07003928static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3929{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003930 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3931 PROCESS__SETSCHED, NULL);
James Morris03e68062006-06-23 02:03:58 -07003932}
3933
David Quigleya1836a42006-06-30 01:55:49 -07003934static int selinux_task_getioprio(struct task_struct *p)
3935{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003936 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3937 PROCESS__GETSCHED, NULL);
David Quigleya1836a42006-06-30 01:55:49 -07003938}
3939
Stephen Smalley791ec492017-02-17 07:57:00 -05003940int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
3941 unsigned int flags)
3942{
3943 u32 av = 0;
3944
Stephen Smalley84e68852017-02-28 09:35:08 -05003945 if (!flags)
3946 return 0;
Stephen Smalley791ec492017-02-17 07:57:00 -05003947 if (flags & LSM_PRLIMIT_WRITE)
3948 av |= PROCESS__SETRLIMIT;
3949 if (flags & LSM_PRLIMIT_READ)
3950 av |= PROCESS__GETRLIMIT;
3951 return avc_has_perm(cred_sid(cred), cred_sid(tcred),
3952 SECCLASS_PROCESS, av, NULL);
3953}
3954
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003955static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3956 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003958 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
3960 /* Control the ability to change the hard limit (whether
3961 lowering or raising it), so that the hard limit can
3962 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003963 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 if (old_rlim->rlim_max != new_rlim->rlim_max)
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003965 return avc_has_perm(current_sid(), task_sid(p),
3966 SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968 return 0;
3969}
3970
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003971static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003973 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3974 PROCESS__SETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975}
3976
3977static int selinux_task_getscheduler(struct task_struct *p)
3978{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003979 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3980 PROCESS__GETSCHED, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981}
3982
David Quigley35601542006-06-23 02:04:01 -07003983static int selinux_task_movememory(struct task_struct *p)
3984{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003985 return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
3986 PROCESS__SETSCHED, NULL);
David Quigley35601542006-06-23 02:04:01 -07003987}
3988
David Quigleyf9008e4c2006-06-30 01:55:46 -07003989static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3990 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991{
3992 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 if (!sig)
3995 perm = PROCESS__SIGNULL; /* null signal; existence test */
3996 else
3997 perm = signal_to_av(sig);
Stephen Smalleybe0554c2017-01-09 10:07:31 -05003998 if (!secid)
3999 secid = current_sid();
4000 return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001}
4002
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003static void selinux_task_to_inode(struct task_struct *p,
4004 struct inode *inode)
4005{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11004007 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004009 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01004010 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11004011 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004012 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004013 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014}
4015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004017static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004018 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019{
4020 int offset, ihlen, ret = -EINVAL;
4021 struct iphdr _iph, *ih;
4022
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004023 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
4025 if (ih == NULL)
4026 goto out;
4027
4028 ihlen = ih->ihl * 4;
4029 if (ihlen < sizeof(_iph))
4030 goto out;
4031
Eric Paris48c62af2012-04-02 13:15:44 -04004032 ad->u.net->v4info.saddr = ih->saddr;
4033 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 ret = 0;
4035
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004036 if (proto)
4037 *proto = ih->protocol;
4038
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004040 case IPPROTO_TCP: {
4041 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Eric Paris828dfe12008-04-17 13:17:49 -04004043 if (ntohs(ih->frag_off) & IP_OFFSET)
4044 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
4046 offset += ihlen;
4047 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4048 if (th == NULL)
4049 break;
4050
Eric Paris48c62af2012-04-02 13:15:44 -04004051 ad->u.net->sport = th->source;
4052 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
Eric Paris828dfe12008-04-17 13:17:49 -04004056 case IPPROTO_UDP: {
4057 struct udphdr _udph, *uh;
4058
4059 if (ntohs(ih->frag_off) & IP_OFFSET)
4060 break;
4061
4062 offset += ihlen;
4063 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4064 if (uh == NULL)
4065 break;
4066
Eric Paris48c62af2012-04-02 13:15:44 -04004067 ad->u.net->sport = uh->source;
4068 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004069 break;
4070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
James Morris2ee92d42006-11-13 16:09:01 -08004072 case IPPROTO_DCCP: {
4073 struct dccp_hdr _dccph, *dh;
4074
4075 if (ntohs(ih->frag_off) & IP_OFFSET)
4076 break;
4077
4078 offset += ihlen;
4079 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4080 if (dh == NULL)
4081 break;
4082
Eric Paris48c62af2012-04-02 13:15:44 -04004083 ad->u.net->sport = dh->dccph_sport;
4084 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004085 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004086 }
James Morris2ee92d42006-11-13 16:09:01 -08004087
Eric Paris828dfe12008-04-17 13:17:49 -04004088 default:
4089 break;
4090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091out:
4092 return ret;
4093}
4094
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004095#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
4097/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004098static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004099 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100{
4101 u8 nexthdr;
4102 int ret = -EINVAL, offset;
4103 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004104 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004106 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4108 if (ip6 == NULL)
4109 goto out;
4110
Eric Paris48c62af2012-04-02 13:15:44 -04004111 ad->u.net->v6info.saddr = ip6->saddr;
4112 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 ret = 0;
4114
4115 nexthdr = ip6->nexthdr;
4116 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004117 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 if (offset < 0)
4119 goto out;
4120
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004121 if (proto)
4122 *proto = nexthdr;
4123
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 switch (nexthdr) {
4125 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004126 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
4128 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4129 if (th == NULL)
4130 break;
4131
Eric Paris48c62af2012-04-02 13:15:44 -04004132 ad->u.net->sport = th->source;
4133 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 break;
4135 }
4136
4137 case IPPROTO_UDP: {
4138 struct udphdr _udph, *uh;
4139
4140 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4141 if (uh == NULL)
4142 break;
4143
Eric Paris48c62af2012-04-02 13:15:44 -04004144 ad->u.net->sport = uh->source;
4145 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 break;
4147 }
4148
James Morris2ee92d42006-11-13 16:09:01 -08004149 case IPPROTO_DCCP: {
4150 struct dccp_hdr _dccph, *dh;
4151
4152 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4153 if (dh == NULL)
4154 break;
4155
Eric Paris48c62af2012-04-02 13:15:44 -04004156 ad->u.net->sport = dh->dccph_sport;
4157 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004158 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004159 }
James Morris2ee92d42006-11-13 16:09:01 -08004160
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 /* includes fragments */
4162 default:
4163 break;
4164 }
4165out:
4166 return ret;
4167}
4168
4169#endif /* IPV6 */
4170
Thomas Liu2bf49692009-07-14 12:14:09 -04004171static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004172 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173{
David Howellscf9481e2008-07-27 21:31:07 +10004174 char *addrp;
4175 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Eric Paris48c62af2012-04-02 13:15:44 -04004177 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004179 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004180 if (ret)
4181 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004182 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4183 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004184 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004186#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004188 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004189 if (ret)
4190 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004191 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4192 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004193 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194#endif /* IPV6 */
4195 default:
David Howellscf9481e2008-07-27 21:31:07 +10004196 addrp = NULL;
4197 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 }
4199
David Howellscf9481e2008-07-27 21:31:07 +10004200parse_error:
4201 printk(KERN_WARNING
4202 "SELinux: failure in selinux_parse_skb(),"
4203 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004205
4206okay:
4207 if (_addrp)
4208 *_addrp = addrp;
4209 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210}
4211
Paul Moore4f6a9932007-03-01 14:35:22 -05004212/**
Paul Moore220deb92008-01-29 08:38:23 -05004213 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004214 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004215 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004216 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004217 *
4218 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004219 * Check the various different forms of network peer labeling and determine
4220 * the peer label/SID for the packet; most of the magic actually occurs in
4221 * the security server function security_net_peersid_cmp(). The function
4222 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4223 * or -EACCES if @sid is invalid due to inconsistencies with the different
4224 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004225 *
4226 */
Paul Moore220deb92008-01-29 08:38:23 -05004227static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004228{
Paul Moore71f1cb02008-01-29 08:51:16 -05004229 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004230 u32 xfrm_sid;
4231 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004232 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004233
Paul Moore817eff72013-12-10 14:57:54 -05004234 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004235 if (unlikely(err))
4236 return -EACCES;
4237 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4238 if (unlikely(err))
4239 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004240
Paul Moore71f1cb02008-01-29 08:51:16 -05004241 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
4242 if (unlikely(err)) {
4243 printk(KERN_WARNING
4244 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4245 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004246 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004247 }
Paul Moore220deb92008-01-29 08:38:23 -05004248
4249 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004250}
4251
Paul Moore446b8022013-12-04 16:10:51 -05004252/**
4253 * selinux_conn_sid - Determine the child socket label for a connection
4254 * @sk_sid: the parent socket's SID
4255 * @skb_sid: the packet's SID
4256 * @conn_sid: the resulting connection SID
4257 *
4258 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4259 * combined with the MLS information from @skb_sid in order to create
4260 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4261 * of @sk_sid. Returns zero on success, negative values on failure.
4262 *
4263 */
4264static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4265{
4266 int err = 0;
4267
4268 if (skb_sid != SECSID_NULL)
4269 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4270 else
4271 *conn_sid = sk_sid;
4272
4273 return err;
4274}
4275
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004277
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004278static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4279 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004280{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004281 if (tsec->sockcreate_sid > SECSID_NULL) {
4282 *socksid = tsec->sockcreate_sid;
4283 return 0;
4284 }
4285
4286 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4287 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004288}
4289
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004290static int sock_has_perm(struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
Paul Moore253bfae2010-04-22 14:46:19 -04004292 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004293 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004294 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Paul Moore253bfae2010-04-22 14:46:19 -04004296 if (sksec->sid == SECINITSID_KERNEL)
4297 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Eric Paris50c205f2012-04-04 15:01:43 -04004299 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004300 ad.u.net = &net;
4301 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004303 return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
4304 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305}
4306
4307static int selinux_socket_create(int family, int type,
4308 int protocol, int kern)
4309{
Paul Moore5fb49872010-04-22 14:46:19 -04004310 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004311 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004312 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004313 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
4315 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004316 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
David Howells275bb412008-11-14 10:39:19 +11004318 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004319 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4320 if (rc)
4321 return rc;
4322
Paul Moored4f2d972010-04-22 14:46:18 -04004323 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324}
4325
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004326static int selinux_socket_post_create(struct socket *sock, int family,
4327 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328{
Paul Moore5fb49872010-04-22 14:46:19 -04004329 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004330 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004331 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004332 u16 sclass = socket_type_to_security_class(family, type, protocol);
4333 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004334 int err = 0;
4335
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004336 if (!kern) {
4337 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004338 if (err)
4339 return err;
4340 }
David Howells275bb412008-11-14 10:39:19 +11004341
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004342 isec->sclass = sclass;
4343 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004344 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004346 if (sock->sk) {
4347 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004348 sksec->sclass = sclass;
4349 sksec->sid = sid;
Paul Moore389fb8002009-03-27 17:10:34 -04004350 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004351 }
4352
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004353 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354}
4355
4356/* Range of port numbers used to automatically bind.
4357 Need to determine whether we should perform a name_bind
4358 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
4360static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4361{
Paul Moore253bfae2010-04-22 14:46:19 -04004362 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363 u16 family;
4364 int err;
4365
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004366 err = sock_has_perm(sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 if (err)
4368 goto out;
4369
4370 /*
4371 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004372 * Multiple address binding for SCTP is not supported yet: we just
4373 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 */
Paul Moore253bfae2010-04-22 14:46:19 -04004375 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 if (family == PF_INET || family == PF_INET6) {
4377 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004378 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004379 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004380 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 struct sockaddr_in *addr4 = NULL;
4382 struct sockaddr_in6 *addr6 = NULL;
4383 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004384 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 if (family == PF_INET) {
Alexander Potapenkoe2f586b2017-03-06 19:46:14 +01004387 if (addrlen < sizeof(struct sockaddr_in)) {
4388 err = -EINVAL;
4389 goto out;
4390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 addr4 = (struct sockaddr_in *)address;
4392 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 addrp = (char *)&addr4->sin_addr.s_addr;
4394 } else {
Alexander Potapenkoe2f586b2017-03-06 19:46:14 +01004395 if (addrlen < SIN6_LEN_RFC2133) {
4396 err = -EINVAL;
4397 goto out;
4398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 addr6 = (struct sockaddr_in6 *)address;
4400 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 addrp = (char *)&addr6->sin6_addr.s6_addr;
4402 }
4403
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004404 if (snum) {
4405 int low, high;
4406
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004407 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004408
Krister Johansen4548b682017-01-20 17:49:11 -08004409 if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
4410 snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004411 err = sel_netport_sid(sk->sk_protocol,
4412 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004413 if (err)
4414 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004415 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004416 ad.u.net = &net;
4417 ad.u.net->sport = htons(snum);
4418 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004419 err = avc_has_perm(sksec->sid, sid,
4420 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004421 SOCKET__NAME_BIND, &ad);
4422 if (err)
4423 goto out;
4424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 }
Eric Paris828dfe12008-04-17 13:17:49 -04004426
Paul Moore253bfae2010-04-22 14:46:19 -04004427 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004428 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 node_perm = TCP_SOCKET__NODE_BIND;
4430 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004431
James Morris13402582005-09-30 14:24:34 -04004432 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 node_perm = UDP_SOCKET__NODE_BIND;
4434 break;
James Morris2ee92d42006-11-13 16:09:01 -08004435
4436 case SECCLASS_DCCP_SOCKET:
4437 node_perm = DCCP_SOCKET__NODE_BIND;
4438 break;
4439
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 default:
4441 node_perm = RAWIP_SOCKET__NODE_BIND;
4442 break;
4443 }
Eric Paris828dfe12008-04-17 13:17:49 -04004444
Paul Moore224dfbd2008-01-29 08:38:13 -05004445 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 if (err)
4447 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004448
Eric Paris50c205f2012-04-04 15:01:43 -04004449 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004450 ad.u.net = &net;
4451 ad.u.net->sport = htons(snum);
4452 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
4454 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004455 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 else
Eric Paris48c62af2012-04-02 13:15:44 -04004457 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458
Paul Moore253bfae2010-04-22 14:46:19 -04004459 err = avc_has_perm(sksec->sid, sid,
4460 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 if (err)
4462 goto out;
4463 }
4464out:
4465 return err;
4466}
4467
4468static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4469{
Paul Moore014ab192008-10-10 10:16:33 -04004470 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004471 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 int err;
4473
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004474 err = sock_has_perm(sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 if (err)
4476 return err;
4477
4478 /*
James Morris2ee92d42006-11-13 16:09:01 -08004479 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 */
Paul Moore253bfae2010-04-22 14:46:19 -04004481 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4482 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004483 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004484 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 struct sockaddr_in *addr4 = NULL;
4486 struct sockaddr_in6 *addr6 = NULL;
4487 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004488 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489
4490 if (sk->sk_family == PF_INET) {
4491 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004492 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 return -EINVAL;
4494 snum = ntohs(addr4->sin_port);
4495 } else {
4496 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004497 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 return -EINVAL;
4499 snum = ntohs(addr6->sin6_port);
4500 }
4501
Paul Moore3e112172008-04-10 10:48:14 -04004502 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503 if (err)
4504 goto out;
4505
Paul Moore253bfae2010-04-22 14:46:19 -04004506 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004507 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4508
Eric Paris50c205f2012-04-04 15:01:43 -04004509 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004510 ad.u.net = &net;
4511 ad.u.net->dport = htons(snum);
4512 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004513 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 if (err)
4515 goto out;
4516 }
4517
Paul Moore014ab192008-10-10 10:16:33 -04004518 err = selinux_netlbl_socket_connect(sk, address);
4519
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520out:
4521 return err;
4522}
4523
4524static int selinux_socket_listen(struct socket *sock, int backlog)
4525{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004526 return sock_has_perm(sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527}
4528
4529static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4530{
4531 int err;
4532 struct inode_security_struct *isec;
4533 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004534 u16 sclass;
4535 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004537 err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 if (err)
4539 return err;
4540
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004541 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004542 spin_lock(&isec->lock);
4543 sclass = isec->sclass;
4544 sid = isec->sid;
4545 spin_unlock(&isec->lock);
4546
4547 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4548 newisec->sclass = sclass;
4549 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004550 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551
4552 return 0;
4553}
4554
4555static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004556 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004558 return sock_has_perm(sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559}
4560
4561static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4562 int size, int flags)
4563{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004564 return sock_has_perm(sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565}
4566
4567static int selinux_socket_getsockname(struct socket *sock)
4568{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004569 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570}
4571
4572static int selinux_socket_getpeername(struct socket *sock)
4573{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004574 return sock_has_perm(sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575}
4576
Eric Paris828dfe12008-04-17 13:17:49 -04004577static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578{
Paul Mooref8687af2006-10-30 15:22:15 -08004579 int err;
4580
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004581 err = sock_has_perm(sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004582 if (err)
4583 return err;
4584
4585 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586}
4587
4588static int selinux_socket_getsockopt(struct socket *sock, int level,
4589 int optname)
4590{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004591 return sock_has_perm(sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592}
4593
4594static int selinux_socket_shutdown(struct socket *sock, int how)
4595{
Stephen Smalleybe0554c2017-01-09 10:07:31 -05004596 return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597}
4598
David S. Miller3610cda2011-01-05 15:38:53 -08004599static int selinux_socket_unix_stream_connect(struct sock *sock,
4600 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 struct sock *newsk)
4602{
David S. Miller3610cda2011-01-05 15:38:53 -08004603 struct sk_security_struct *sksec_sock = sock->sk_security;
4604 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004605 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004606 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004607 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 int err;
4609
Eric Paris50c205f2012-04-04 15:01:43 -04004610 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004611 ad.u.net = &net;
4612 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613
Paul Moore4d1e2452010-04-22 14:46:18 -04004614 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4615 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4617 if (err)
4618 return err;
4619
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004621 sksec_new->peer_sid = sksec_sock->sid;
4622 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4623 &sksec_new->sid);
4624 if (err)
4625 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004626
Paul Moore4d1e2452010-04-22 14:46:18 -04004627 /* connecting socket */
4628 sksec_sock->peer_sid = sksec_new->sid;
4629
4630 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631}
4632
4633static int selinux_socket_unix_may_send(struct socket *sock,
4634 struct socket *other)
4635{
Paul Moore253bfae2010-04-22 14:46:19 -04004636 struct sk_security_struct *ssec = sock->sk->sk_security;
4637 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004638 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004639 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004640
Eric Paris50c205f2012-04-04 15:01:43 -04004641 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004642 ad.u.net = &net;
4643 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644
Paul Moore253bfae2010-04-22 14:46:19 -04004645 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4646 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647}
4648
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004649static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4650 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004651 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004652{
4653 int err;
4654 u32 if_sid;
4655 u32 node_sid;
4656
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004657 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004658 if (err)
4659 return err;
4660 err = avc_has_perm(peer_sid, if_sid,
4661 SECCLASS_NETIF, NETIF__INGRESS, ad);
4662 if (err)
4663 return err;
4664
4665 err = sel_netnode_sid(addrp, family, &node_sid);
4666 if (err)
4667 return err;
4668 return avc_has_perm(peer_sid, node_sid,
4669 SECCLASS_NODE, NODE__RECVFROM, ad);
4670}
4671
Paul Moore220deb92008-01-29 08:38:23 -05004672static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004673 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004674{
Paul Moore277d3422008-12-31 12:54:11 -05004675 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004676 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004677 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004678 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004679 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004680 char *addrp;
4681
Eric Paris50c205f2012-04-04 15:01:43 -04004682 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004683 ad.u.net = &net;
4684 ad.u.net->netif = skb->skb_iif;
4685 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004686 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4687 if (err)
4688 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004689
Paul Moore58bfbb52009-03-27 17:10:41 -04004690 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004691 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004692 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004693 if (err)
4694 return err;
4695 }
Paul Moore220deb92008-01-29 08:38:23 -05004696
Steffen Klassertb9679a72011-02-23 12:55:21 +01004697 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4698 if (err)
4699 return err;
4700 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004701
James Morris4e5ab4c2006-06-09 00:33:33 -07004702 return err;
4703}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004704
James Morris4e5ab4c2006-06-09 00:33:33 -07004705static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4706{
Paul Moore220deb92008-01-29 08:38:23 -05004707 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004708 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004709 u16 family = sk->sk_family;
4710 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004711 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004712 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004713 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004714 u8 secmark_active;
4715 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004716
James Morris4e5ab4c2006-06-09 00:33:33 -07004717 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004718 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004719
4720 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004721 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004722 family = PF_INET;
4723
Paul Moored8395c82008-10-10 10:16:30 -04004724 /* If any sort of compatibility mode is enabled then handoff processing
4725 * to the selinux_sock_rcv_skb_compat() function to deal with the
4726 * special handling. We do this in an attempt to keep this function
4727 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004728 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004729 return selinux_sock_rcv_skb_compat(sk, skb, family);
4730
4731 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004732 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004733 if (!secmark_active && !peerlbl_active)
4734 return 0;
4735
Eric Paris50c205f2012-04-04 15:01:43 -04004736 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004737 ad.u.net = &net;
4738 ad.u.net->netif = skb->skb_iif;
4739 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004740 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004741 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004742 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004743
Paul Moored8395c82008-10-10 10:16:30 -04004744 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004745 u32 peer_sid;
4746
4747 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4748 if (err)
4749 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004750 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4751 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004752 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004753 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004754 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004755 }
Paul Moored621d352008-01-29 08:43:36 -05004756 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4757 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004758 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004759 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004760 return err;
4761 }
Paul Moored621d352008-01-29 08:43:36 -05004762 }
4763
Paul Moored8395c82008-10-10 10:16:30 -04004764 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004765 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4766 PACKET__RECV, &ad);
4767 if (err)
4768 return err;
4769 }
4770
Paul Moored621d352008-01-29 08:43:36 -05004771 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772}
4773
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004774static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4775 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776{
4777 int err = 0;
4778 char *scontext;
4779 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004780 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004781 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782
Paul Moore253bfae2010-04-22 14:46:19 -04004783 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4784 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004785 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004786 if (peer_sid == SECSID_NULL)
4787 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004789 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004791 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792
4793 if (scontext_len > len) {
4794 err = -ERANGE;
4795 goto out_len;
4796 }
4797
4798 if (copy_to_user(optval, scontext, scontext_len))
4799 err = -EFAULT;
4800
4801out_len:
4802 if (put_user(scontext_len, optlen))
4803 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004805 return err;
4806}
4807
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004808static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004809{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004810 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004811 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004812 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004813
Paul Mooreaa862902008-10-10 10:16:29 -04004814 if (skb && skb->protocol == htons(ETH_P_IP))
4815 family = PF_INET;
4816 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4817 family = PF_INET6;
4818 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004819 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004820 else
4821 goto out;
4822
Paul Moore899134f2016-03-28 15:19:10 -04004823 if (sock && family == PF_UNIX) {
4824 isec = inode_security_novalidate(SOCK_INODE(sock));
4825 peer_secid = isec->sid;
4826 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004827 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004828
Paul Moore75e22912008-01-29 08:38:04 -05004829out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004830 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004831 if (peer_secid == SECSID_NULL)
4832 return -EINVAL;
4833 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004834}
4835
Al Viro7d877f32005-10-21 03:20:43 -04004836static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837{
Paul Moore84914b72010-04-22 14:46:18 -04004838 struct sk_security_struct *sksec;
4839
4840 sksec = kzalloc(sizeof(*sksec), priority);
4841 if (!sksec)
4842 return -ENOMEM;
4843
4844 sksec->peer_sid = SECINITSID_UNLABELED;
4845 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004846 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004847 selinux_netlbl_sk_security_reset(sksec);
4848 sk->sk_security = sksec;
4849
4850 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851}
4852
4853static void selinux_sk_free_security(struct sock *sk)
4854{
Paul Moore84914b72010-04-22 14:46:18 -04004855 struct sk_security_struct *sksec = sk->sk_security;
4856
4857 sk->sk_security = NULL;
4858 selinux_netlbl_sk_security_free(sksec);
4859 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004860}
4861
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004862static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4863{
Eric Parisdd3e7832010-04-07 15:08:46 -04004864 struct sk_security_struct *sksec = sk->sk_security;
4865 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004866
Eric Parisdd3e7832010-04-07 15:08:46 -04004867 newsksec->sid = sksec->sid;
4868 newsksec->peer_sid = sksec->peer_sid;
4869 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004870
Eric Parisdd3e7832010-04-07 15:08:46 -04004871 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004872}
4873
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004874static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004875{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004876 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004877 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004878 else {
4879 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004880
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004881 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004882 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004883}
4884
Eric Paris828dfe12008-04-17 13:17:49 -04004885static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004886{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004887 struct inode_security_struct *isec =
4888 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004889 struct sk_security_struct *sksec = sk->sk_security;
4890
Paul Moore2873ead2014-07-28 10:42:48 -04004891 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4892 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004893 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004894 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004895}
4896
Adrian Bunk9a673e52006-08-15 00:03:53 -07004897static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4898 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004899{
4900 struct sk_security_struct *sksec = sk->sk_security;
4901 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004902 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004903 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004904 u32 peersid;
4905
Paul Mooreaa862902008-10-10 10:16:29 -04004906 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004907 if (err)
4908 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004909 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4910 if (err)
4911 return err;
4912 req->secid = connsid;
4913 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004914
Paul Moore389fb8002009-03-27 17:10:34 -04004915 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004916}
4917
Adrian Bunk9a673e52006-08-15 00:03:53 -07004918static void selinux_inet_csk_clone(struct sock *newsk,
4919 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004920{
4921 struct sk_security_struct *newsksec = newsk->sk_security;
4922
4923 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004924 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004925 /* NOTE: Ideally, we should also get the isec->sid for the
4926 new socket in sync, but we don't have the isec available yet.
4927 So we will wait until sock_graft to do it, by which
4928 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004929
Paul Moore9f2ad662006-11-17 17:38:53 -05004930 /* We don't need to take any sort of lock here as we are the only
4931 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004932 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004933}
4934
Paul Moore014ab192008-10-10 10:16:33 -04004935static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004936{
Paul Mooreaa862902008-10-10 10:16:29 -04004937 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004938 struct sk_security_struct *sksec = sk->sk_security;
4939
Paul Mooreaa862902008-10-10 10:16:29 -04004940 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4941 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4942 family = PF_INET;
4943
4944 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004945}
4946
Eric Paris2606fd12010-10-13 16:24:41 -04004947static int selinux_secmark_relabel_packet(u32 sid)
4948{
4949 const struct task_security_struct *__tsec;
4950 u32 tsid;
4951
4952 __tsec = current_security();
4953 tsid = __tsec->sid;
4954
4955 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4956}
4957
4958static void selinux_secmark_refcount_inc(void)
4959{
4960 atomic_inc(&selinux_secmark_refcount);
4961}
4962
4963static void selinux_secmark_refcount_dec(void)
4964{
4965 atomic_dec(&selinux_secmark_refcount);
4966}
4967
Adrian Bunk9a673e52006-08-15 00:03:53 -07004968static void selinux_req_classify_flow(const struct request_sock *req,
4969 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004970{
David S. Miller1d28f422011-03-12 00:29:39 -05004971 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004972}
4973
Paul Moore5dbbaf22013-01-14 07:12:19 +00004974static int selinux_tun_dev_alloc_security(void **security)
4975{
4976 struct tun_security_struct *tunsec;
4977
4978 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4979 if (!tunsec)
4980 return -ENOMEM;
4981 tunsec->sid = current_sid();
4982
4983 *security = tunsec;
4984 return 0;
4985}
4986
4987static void selinux_tun_dev_free_security(void *security)
4988{
4989 kfree(security);
4990}
4991
Paul Mooreed6d76e2009-08-28 18:12:49 -04004992static int selinux_tun_dev_create(void)
4993{
4994 u32 sid = current_sid();
4995
4996 /* we aren't taking into account the "sockcreate" SID since the socket
4997 * that is being created here is not a socket in the traditional sense,
4998 * instead it is a private sock, accessible only to the kernel, and
4999 * representing a wide range of network traffic spanning multiple
5000 * connections unlike traditional sockets - check the TUN driver to
5001 * get a better understanding of why this socket is special */
5002
5003 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
5004 NULL);
5005}
5006
Paul Moore5dbbaf22013-01-14 07:12:19 +00005007static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005008{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005009 struct tun_security_struct *tunsec = security;
5010
5011 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
5012 TUN_SOCKET__ATTACH_QUEUE, NULL);
5013}
5014
5015static int selinux_tun_dev_attach(struct sock *sk, void *security)
5016{
5017 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005018 struct sk_security_struct *sksec = sk->sk_security;
5019
5020 /* we don't currently perform any NetLabel based labeling here and it
5021 * isn't clear that we would want to do so anyway; while we could apply
5022 * labeling without the support of the TUN user the resulting labeled
5023 * traffic from the other end of the connection would almost certainly
5024 * cause confusion to the TUN user that had no idea network labeling
5025 * protocols were being used */
5026
Paul Moore5dbbaf22013-01-14 07:12:19 +00005027 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005028 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005029
5030 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005031}
5032
Paul Moore5dbbaf22013-01-14 07:12:19 +00005033static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04005034{
Paul Moore5dbbaf22013-01-14 07:12:19 +00005035 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005036 u32 sid = current_sid();
5037 int err;
5038
Paul Moore5dbbaf22013-01-14 07:12:19 +00005039 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005040 TUN_SOCKET__RELABELFROM, NULL);
5041 if (err)
5042 return err;
5043 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
5044 TUN_SOCKET__RELABELTO, NULL);
5045 if (err)
5046 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005047 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005048
5049 return 0;
5050}
5051
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
5053{
5054 int err = 0;
5055 u32 perm;
5056 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005057 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005058
Hong zhi guo77954982013-03-27 06:49:35 +00005059 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 err = -EINVAL;
5061 goto out;
5062 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005063 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005064
Paul Moore253bfae2010-04-22 14:46:19 -04005065 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 if (err) {
5067 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005068 pr_warn_ratelimited("SELinux: unrecognized netlink"
5069 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5070 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005071 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005072 secclass_map[sksec->sclass - 1].name,
5073 task_pid_nr(current), current->comm);
Eric Paris39c9aed2008-11-05 09:34:42 -05005074 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075 err = 0;
5076 }
5077
5078 /* Ignore */
5079 if (err == -ENOENT)
5080 err = 0;
5081 goto out;
5082 }
5083
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005084 err = sock_has_perm(sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085out:
5086 return err;
5087}
5088
5089#ifdef CONFIG_NETFILTER
5090
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005091static unsigned int selinux_ip_forward(struct sk_buff *skb,
5092 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005093 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094{
Paul Mooredfaebe92008-10-10 10:16:31 -04005095 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005096 char *addrp;
5097 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005098 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005099 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005100 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005101 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005102 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005103
Paul Mooreeffad8d2008-01-29 08:49:27 -05005104 if (!selinux_policycap_netpeer)
5105 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005106
Paul Mooreeffad8d2008-01-29 08:49:27 -05005107 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005108 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005109 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005110 if (!secmark_active && !peerlbl_active)
5111 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005112
Paul Moored8395c82008-10-10 10:16:30 -04005113 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5114 return NF_DROP;
5115
Eric Paris50c205f2012-04-04 15:01:43 -04005116 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005117 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005118 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005119 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005120 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5121 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122
Paul Mooredfaebe92008-10-10 10:16:31 -04005123 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005124 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5125 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005126 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005127 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005128 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005129 }
5130 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005131
5132 if (secmark_active)
5133 if (avc_has_perm(peer_sid, skb->secmark,
5134 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5135 return NF_DROP;
5136
Paul Moore948bf852008-10-10 10:16:32 -04005137 if (netlbl_active)
5138 /* we do this in the FORWARD path and not the POST_ROUTING
5139 * path because we want to make sure we apply the necessary
5140 * labeling before IPsec is applied so we can leverage AH
5141 * protection */
5142 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5143 return NF_DROP;
5144
Paul Mooreeffad8d2008-01-29 08:49:27 -05005145 return NF_ACCEPT;
5146}
5147
Eric W. Biederman06198b32015-09-18 14:33:06 -05005148static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005149 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005150 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005151{
David S. Miller238e54c2015-04-03 20:32:56 -04005152 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005153}
5154
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005155#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005156static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005157 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005158 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005159{
David S. Miller238e54c2015-04-03 20:32:56 -04005160 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005161}
5162#endif /* IPV6 */
5163
Paul Moore948bf852008-10-10 10:16:32 -04005164static unsigned int selinux_ip_output(struct sk_buff *skb,
5165 u16 family)
5166{
Paul Moore47180062013-12-04 16:10:45 -05005167 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005168 u32 sid;
5169
5170 if (!netlbl_enabled())
5171 return NF_ACCEPT;
5172
5173 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5174 * because we want to make sure we apply the necessary labeling
5175 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005176 sk = skb->sk;
5177 if (sk) {
5178 struct sk_security_struct *sksec;
5179
Eric Dumazete446f9d2015-10-08 05:01:55 -07005180 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005181 /* if the socket is the listening state then this
5182 * packet is a SYN-ACK packet which means it needs to
5183 * be labeled based on the connection/request_sock and
5184 * not the parent socket. unfortunately, we can't
5185 * lookup the request_sock yet as it isn't queued on
5186 * the parent socket until after the SYN-ACK is sent.
5187 * the "solution" is to simply pass the packet as-is
5188 * as any IP option based labeling should be copied
5189 * from the initial connection request (in the IP
5190 * layer). it is far from ideal, but until we get a
5191 * security label in the packet itself this is the
5192 * best we can do. */
5193 return NF_ACCEPT;
5194
5195 /* standard practice, label using the parent socket */
5196 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005197 sid = sksec->sid;
5198 } else
5199 sid = SECINITSID_KERNEL;
5200 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5201 return NF_DROP;
5202
5203 return NF_ACCEPT;
5204}
5205
Eric W. Biederman06198b32015-09-18 14:33:06 -05005206static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005207 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005208 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005209{
5210 return selinux_ip_output(skb, PF_INET);
5211}
5212
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005213#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005214static unsigned int selinux_ipv6_output(void *priv,
5215 struct sk_buff *skb,
5216 const struct nf_hook_state *state)
5217{
5218 return selinux_ip_output(skb, PF_INET6);
5219}
5220#endif /* IPV6 */
5221
Paul Mooreeffad8d2008-01-29 08:49:27 -05005222static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5223 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005224 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005225{
Eric Dumazet54abc682015-11-08 10:54:07 -08005226 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005227 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005228 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005229 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005230 char *addrp;
5231 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005232
Paul Mooreeffad8d2008-01-29 08:49:27 -05005233 if (sk == NULL)
5234 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005235 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005236
Eric Paris50c205f2012-04-04 15:01:43 -04005237 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005238 ad.u.net = &net;
5239 ad.u.net->netif = ifindex;
5240 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005241 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5242 return NF_DROP;
5243
Paul Moore58bfbb52009-03-27 17:10:41 -04005244 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005245 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005246 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005247 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005248
Steffen Klassertb9679a72011-02-23 12:55:21 +01005249 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5250 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005251
Paul Mooreeffad8d2008-01-29 08:49:27 -05005252 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253}
5254
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005255static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5256 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005257 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005259 u32 secmark_perm;
5260 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005261 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005262 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005263 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005264 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005265 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005266 u8 secmark_active;
5267 u8 peerlbl_active;
5268
Paul Mooreeffad8d2008-01-29 08:49:27 -05005269 /* If any sort of compatibility mode is enabled then handoff processing
5270 * to the selinux_ip_postroute_compat() function to deal with the
5271 * special handling. We do this in an attempt to keep this function
5272 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04005273 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04005274 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005275
Paul Mooreeffad8d2008-01-29 08:49:27 -05005276 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005277 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005278 if (!secmark_active && !peerlbl_active)
5279 return NF_ACCEPT;
5280
Eric Dumazet54abc682015-11-08 10:54:07 -08005281 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005282
Paul Mooreeffad8d2008-01-29 08:49:27 -05005283#ifdef CONFIG_XFRM
5284 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5285 * packet transformation so allow the packet to pass without any checks
5286 * since we'll have another chance to perform access control checks
5287 * when the packet is on it's final way out.
5288 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005289 * is NULL, in this case go ahead and apply access control.
5290 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5291 * TCP listening state we cannot wait until the XFRM processing
5292 * is done as we will miss out on the SA label if we do;
5293 * unfortunately, this means more work, but it is only once per
5294 * connection. */
5295 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005296 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005297 return NF_ACCEPT;
5298#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005299
Paul Moored8395c82008-10-10 10:16:30 -04005300 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005301 /* Without an associated socket the packet is either coming
5302 * from the kernel or it is being forwarded; check the packet
5303 * to determine which and if the packet is being forwarded
5304 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005305 if (skb->skb_iif) {
5306 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005307 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005308 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005309 } else {
5310 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005311 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005312 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005313 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005314 /* Locally generated packet but the associated socket is in the
5315 * listening state which means this is a SYN-ACK packet. In
5316 * this particular case the correct security label is assigned
5317 * to the connection/request_sock but unfortunately we can't
5318 * query the request_sock as it isn't queued on the parent
5319 * socket until after the SYN-ACK packet is sent; the only
5320 * viable choice is to regenerate the label like we do in
5321 * selinux_inet_conn_request(). See also selinux_ip_output()
5322 * for similar problems. */
5323 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005324 struct sk_security_struct *sksec;
5325
Eric Dumazete446f9d2015-10-08 05:01:55 -07005326 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005327 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5328 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005329 /* At this point, if the returned skb peerlbl is SECSID_NULL
5330 * and the packet has been through at least one XFRM
5331 * transformation then we must be dealing with the "final"
5332 * form of labeled IPsec packet; since we've already applied
5333 * all of our access controls on this packet we can safely
5334 * pass the packet. */
5335 if (skb_sid == SECSID_NULL) {
5336 switch (family) {
5337 case PF_INET:
5338 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5339 return NF_ACCEPT;
5340 break;
5341 case PF_INET6:
5342 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5343 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005344 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005345 default:
5346 return NF_DROP_ERR(-ECONNREFUSED);
5347 }
5348 }
Paul Moore446b8022013-12-04 16:10:51 -05005349 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5350 return NF_DROP;
5351 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005352 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005353 /* Locally generated packet, fetch the security label from the
5354 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005355 struct sk_security_struct *sksec = sk->sk_security;
5356 peer_sid = sksec->sid;
5357 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005358 }
5359
Eric Paris50c205f2012-04-04 15:01:43 -04005360 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005361 ad.u.net = &net;
5362 ad.u.net->netif = ifindex;
5363 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005364 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005365 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005366
Paul Mooreeffad8d2008-01-29 08:49:27 -05005367 if (secmark_active)
5368 if (avc_has_perm(peer_sid, skb->secmark,
5369 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005370 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005371
5372 if (peerlbl_active) {
5373 u32 if_sid;
5374 u32 node_sid;
5375
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005376 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005377 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005378 if (avc_has_perm(peer_sid, if_sid,
5379 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005380 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005381
5382 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005383 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005384 if (avc_has_perm(peer_sid, node_sid,
5385 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005386 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005387 }
5388
5389 return NF_ACCEPT;
5390}
5391
Eric W. Biederman06198b32015-09-18 14:33:06 -05005392static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005393 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005394 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005395{
David S. Miller238e54c2015-04-03 20:32:56 -04005396 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397}
5398
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005399#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005400static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005401 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005402 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403{
David S. Miller238e54c2015-04-03 20:32:56 -04005404 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406#endif /* IPV6 */
5407
5408#endif /* CONFIG_NETFILTER */
5409
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5411{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005412 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413}
5414
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005415static int ipc_alloc_security(struct kern_ipc_perm *perm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416 u16 sclass)
5417{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 struct ipc_security_struct *isec;
5419
James Morris89d155e2005-10-30 14:59:21 -08005420 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 if (!isec)
5422 return -ENOMEM;
5423
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424 isec->sclass = sclass;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005425 isec->sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426 perm->security = isec;
5427
5428 return 0;
5429}
5430
5431static void ipc_free_security(struct kern_ipc_perm *perm)
5432{
5433 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 perm->security = NULL;
5435 kfree(isec);
5436}
5437
5438static int msg_msg_alloc_security(struct msg_msg *msg)
5439{
5440 struct msg_security_struct *msec;
5441
James Morris89d155e2005-10-30 14:59:21 -08005442 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443 if (!msec)
5444 return -ENOMEM;
5445
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 msec->sid = SECINITSID_UNLABELED;
5447 msg->security = msec;
5448
5449 return 0;
5450}
5451
5452static void msg_msg_free_security(struct msg_msg *msg)
5453{
5454 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455
5456 msg->security = NULL;
5457 kfree(msec);
5458}
5459
5460static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005461 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005464 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005465 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467 isec = ipc_perms->security;
5468
Eric Paris50c205f2012-04-04 15:01:43 -04005469 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470 ad.u.ipc_id = ipc_perms->key;
5471
David Howells275bb412008-11-14 10:39:19 +11005472 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473}
5474
5475static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5476{
5477 return msg_msg_alloc_security(msg);
5478}
5479
5480static void selinux_msg_msg_free_security(struct msg_msg *msg)
5481{
5482 msg_msg_free_security(msg);
5483}
5484
5485/* message queue security operations */
5486static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5487{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005489 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005490 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491 int rc;
5492
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005493 rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494 if (rc)
5495 return rc;
5496
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497 isec = msq->q_perm.security;
5498
Eric Paris50c205f2012-04-04 15:01:43 -04005499 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005500 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501
David Howells275bb412008-11-14 10:39:19 +11005502 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 MSGQ__CREATE, &ad);
5504 if (rc) {
5505 ipc_free_security(&msq->q_perm);
5506 return rc;
5507 }
5508 return 0;
5509}
5510
5511static void selinux_msg_queue_free_security(struct msg_queue *msq)
5512{
5513 ipc_free_security(&msq->q_perm);
5514}
5515
5516static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5517{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005519 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005520 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522 isec = msq->q_perm.security;
5523
Eric Paris50c205f2012-04-04 15:01:43 -04005524 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 ad.u.ipc_id = msq->q_perm.key;
5526
David Howells275bb412008-11-14 10:39:19 +11005527 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528 MSGQ__ASSOCIATE, &ad);
5529}
5530
5531static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5532{
5533 int err;
5534 int perms;
5535
Eric Paris828dfe12008-04-17 13:17:49 -04005536 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537 case IPC_INFO:
5538 case MSG_INFO:
5539 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005540 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5541 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542 case IPC_STAT:
5543 case MSG_STAT:
5544 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5545 break;
5546 case IPC_SET:
5547 perms = MSGQ__SETATTR;
5548 break;
5549 case IPC_RMID:
5550 perms = MSGQ__DESTROY;
5551 break;
5552 default:
5553 return 0;
5554 }
5555
Stephen Smalley6af963f2005-05-01 08:58:39 -07005556 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 return err;
5558}
5559
5560static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5561{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562 struct ipc_security_struct *isec;
5563 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005564 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005565 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 int rc;
5567
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 isec = msq->q_perm.security;
5569 msec = msg->security;
5570
5571 /*
5572 * First time through, need to assign label to the message
5573 */
5574 if (msec->sid == SECINITSID_UNLABELED) {
5575 /*
5576 * Compute new sid based on current process and
5577 * message queue this message will be stored in
5578 */
David Howells275bb412008-11-14 10:39:19 +11005579 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005580 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581 if (rc)
5582 return rc;
5583 }
5584
Eric Paris50c205f2012-04-04 15:01:43 -04005585 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 ad.u.ipc_id = msq->q_perm.key;
5587
5588 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005589 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590 MSGQ__WRITE, &ad);
5591 if (!rc)
5592 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005593 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5594 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595 if (!rc)
5596 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005597 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5598 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599
5600 return rc;
5601}
5602
5603static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5604 struct task_struct *target,
5605 long type, int mode)
5606{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607 struct ipc_security_struct *isec;
5608 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005609 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005610 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611 int rc;
5612
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 isec = msq->q_perm.security;
5614 msec = msg->security;
5615
Eric Paris50c205f2012-04-04 15:01:43 -04005616 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005617 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618
David Howells275bb412008-11-14 10:39:19 +11005619 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620 SECCLASS_MSGQ, MSGQ__READ, &ad);
5621 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005622 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623 SECCLASS_MSG, MSG__RECEIVE, &ad);
5624 return rc;
5625}
5626
5627/* Shared Memory security operations */
5628static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5629{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005631 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005632 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633 int rc;
5634
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005635 rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636 if (rc)
5637 return rc;
5638
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639 isec = shp->shm_perm.security;
5640
Eric Paris50c205f2012-04-04 15:01:43 -04005641 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005642 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005643
David Howells275bb412008-11-14 10:39:19 +11005644 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645 SHM__CREATE, &ad);
5646 if (rc) {
5647 ipc_free_security(&shp->shm_perm);
5648 return rc;
5649 }
5650 return 0;
5651}
5652
5653static void selinux_shm_free_security(struct shmid_kernel *shp)
5654{
5655 ipc_free_security(&shp->shm_perm);
5656}
5657
5658static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5659{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005661 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005662 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664 isec = shp->shm_perm.security;
5665
Eric Paris50c205f2012-04-04 15:01:43 -04005666 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667 ad.u.ipc_id = shp->shm_perm.key;
5668
David Howells275bb412008-11-14 10:39:19 +11005669 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670 SHM__ASSOCIATE, &ad);
5671}
5672
5673/* Note, at this point, shp is locked down */
5674static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5675{
5676 int perms;
5677 int err;
5678
Eric Paris828dfe12008-04-17 13:17:49 -04005679 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680 case IPC_INFO:
5681 case SHM_INFO:
5682 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005683 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5684 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685 case IPC_STAT:
5686 case SHM_STAT:
5687 perms = SHM__GETATTR | SHM__ASSOCIATE;
5688 break;
5689 case IPC_SET:
5690 perms = SHM__SETATTR;
5691 break;
5692 case SHM_LOCK:
5693 case SHM_UNLOCK:
5694 perms = SHM__LOCK;
5695 break;
5696 case IPC_RMID:
5697 perms = SHM__DESTROY;
5698 break;
5699 default:
5700 return 0;
5701 }
5702
Stephen Smalley6af963f2005-05-01 08:58:39 -07005703 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704 return err;
5705}
5706
5707static int selinux_shm_shmat(struct shmid_kernel *shp,
5708 char __user *shmaddr, int shmflg)
5709{
5710 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
5712 if (shmflg & SHM_RDONLY)
5713 perms = SHM__READ;
5714 else
5715 perms = SHM__READ | SHM__WRITE;
5716
Stephen Smalley6af963f2005-05-01 08:58:39 -07005717 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718}
5719
5720/* Semaphore security operations */
5721static int selinux_sem_alloc_security(struct sem_array *sma)
5722{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005724 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005725 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726 int rc;
5727
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005728 rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 if (rc)
5730 return rc;
5731
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732 isec = sma->sem_perm.security;
5733
Eric Paris50c205f2012-04-04 15:01:43 -04005734 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005735 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736
David Howells275bb412008-11-14 10:39:19 +11005737 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738 SEM__CREATE, &ad);
5739 if (rc) {
5740 ipc_free_security(&sma->sem_perm);
5741 return rc;
5742 }
5743 return 0;
5744}
5745
5746static void selinux_sem_free_security(struct sem_array *sma)
5747{
5748 ipc_free_security(&sma->sem_perm);
5749}
5750
5751static int selinux_sem_associate(struct sem_array *sma, int semflg)
5752{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005754 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005755 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756
Linus Torvalds1da177e2005-04-16 15:20:36 -07005757 isec = sma->sem_perm.security;
5758
Eric Paris50c205f2012-04-04 15:01:43 -04005759 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760 ad.u.ipc_id = sma->sem_perm.key;
5761
David Howells275bb412008-11-14 10:39:19 +11005762 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763 SEM__ASSOCIATE, &ad);
5764}
5765
5766/* Note, at this point, sma is locked down */
5767static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5768{
5769 int err;
5770 u32 perms;
5771
Eric Paris828dfe12008-04-17 13:17:49 -04005772 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005773 case IPC_INFO:
5774 case SEM_INFO:
5775 /* No specific object, just general system-wide information. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005776 return avc_has_perm(current_sid(), SECINITSID_KERNEL,
5777 SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778 case GETPID:
5779 case GETNCNT:
5780 case GETZCNT:
5781 perms = SEM__GETATTR;
5782 break;
5783 case GETVAL:
5784 case GETALL:
5785 perms = SEM__READ;
5786 break;
5787 case SETVAL:
5788 case SETALL:
5789 perms = SEM__WRITE;
5790 break;
5791 case IPC_RMID:
5792 perms = SEM__DESTROY;
5793 break;
5794 case IPC_SET:
5795 perms = SEM__SETATTR;
5796 break;
5797 case IPC_STAT:
5798 case SEM_STAT:
5799 perms = SEM__GETATTR | SEM__ASSOCIATE;
5800 break;
5801 default:
5802 return 0;
5803 }
5804
Stephen Smalley6af963f2005-05-01 08:58:39 -07005805 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806 return err;
5807}
5808
5809static int selinux_sem_semop(struct sem_array *sma,
5810 struct sembuf *sops, unsigned nsops, int alter)
5811{
5812 u32 perms;
5813
5814 if (alter)
5815 perms = SEM__READ | SEM__WRITE;
5816 else
5817 perms = SEM__READ;
5818
Stephen Smalley6af963f2005-05-01 08:58:39 -07005819 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820}
5821
5822static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5823{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 u32 av = 0;
5825
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 av = 0;
5827 if (flag & S_IRUGO)
5828 av |= IPC__UNIX_READ;
5829 if (flag & S_IWUGO)
5830 av |= IPC__UNIX_WRITE;
5831
5832 if (av == 0)
5833 return 0;
5834
Stephen Smalley6af963f2005-05-01 08:58:39 -07005835 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836}
5837
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005838static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5839{
5840 struct ipc_security_struct *isec = ipcp->security;
5841 *secid = isec->sid;
5842}
5843
Eric Paris828dfe12008-04-17 13:17:49 -04005844static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845{
5846 if (inode)
5847 inode_doinit_with_dentry(inode, dentry);
5848}
5849
5850static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005851 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852{
David Howells275bb412008-11-14 10:39:19 +11005853 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005854 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005856 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857
David Howells275bb412008-11-14 10:39:19 +11005858 rcu_read_lock();
5859 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005861 if (current != p) {
5862 error = avc_has_perm(current_sid(), __tsec->sid,
5863 SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
5864 if (error)
5865 goto bad;
5866 }
5867
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005869 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005871 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005873 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005875 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005876 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005877 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005878 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005879 sid = __tsec->sockcreate_sid;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005880 else {
5881 error = -EINVAL;
5882 goto bad;
5883 }
David Howells275bb412008-11-14 10:39:19 +11005884 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885
5886 if (!sid)
5887 return 0;
5888
Al Viro04ff9702007-03-12 16:17:58 +00005889 error = security_sid_to_context(sid, value, &len);
5890 if (error)
5891 return error;
5892 return len;
David Howells275bb412008-11-14 10:39:19 +11005893
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005894bad:
David Howells275bb412008-11-14 10:39:19 +11005895 rcu_read_unlock();
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005896 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897}
5898
Stephen Smalleyb21507e2017-01-09 10:07:31 -05005899static int selinux_setprocattr(const char *name, void *value, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900{
5901 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11005902 struct cred *new;
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005903 u32 mysid = current_sid(), sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904 int error;
5905 char *str = value;
5906
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907 /*
5908 * Basic control over ability to set these attributes at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909 */
5910 if (!strcmp(name, "exec"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005911 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5912 PROCESS__SETEXEC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913 else if (!strcmp(name, "fscreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005914 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5915 PROCESS__SETFSCREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005916 else if (!strcmp(name, "keycreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005917 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5918 PROCESS__SETKEYCREATE, NULL);
Eric Paris42c3e032006-06-26 00:26:03 -07005919 else if (!strcmp(name, "sockcreate"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005920 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5921 PROCESS__SETSOCKCREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922 else if (!strcmp(name, "current"))
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005923 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
5924 PROCESS__SETCURRENT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 else
5926 error = -EINVAL;
5927 if (error)
5928 return error;
5929
5930 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleya050a572017-01-31 11:54:04 -05005931 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932 if (str[size-1] == '\n') {
5933 str[size-1] = 0;
5934 size--;
5935 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005936 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005937 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Stephen Smalleydb590002017-04-20 11:31:30 -04005938 if (!has_cap_mac_admin(true)) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005939 struct audit_buffer *ab;
5940 size_t audit_size;
5941
5942 /* We strip a nul only if it is at the end, otherwise the
5943 * context contains a nul and we should audit that */
5944 if (str[size - 1] == '\0')
5945 audit_size = size - 1;
5946 else
5947 audit_size = size;
5948 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5949 audit_log_format(ab, "op=fscreate invalid_context=");
5950 audit_log_n_untrustedstring(ab, value, audit_size);
5951 audit_log_end(ab);
5952
Stephen Smalley12b29f32008-05-07 13:03:20 -04005953 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005954 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005955 error = security_context_to_sid_force(value, size,
5956 &sid);
5957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958 if (error)
5959 return error;
5960 }
5961
David Howellsd84f4f92008-11-14 10:39:23 +11005962 new = prepare_creds();
5963 if (!new)
5964 return -ENOMEM;
5965
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966 /* Permission checking based on the specified context is
5967 performed during the actual operation (execve,
5968 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005969 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 checks and may_create for the file creation checks. The
5971 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005972 tsec = new->security;
5973 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005975 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005977 } else if (!strcmp(name, "keycreate")) {
Stephen Smalleybe0554c2017-01-09 10:07:31 -05005978 error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE,
5979 NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005980 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005981 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005982 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005983 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005984 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005985 } else if (!strcmp(name, "current")) {
5986 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005988 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005989
David Howellsd84f4f92008-11-14 10:39:23 +11005990 /* Only allow single threaded processes to change context */
5991 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005992 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005993 error = security_bounded_transition(tsec->sid, sid);
5994 if (error)
5995 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997
5998 /* Check permissions for the transition. */
5999 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04006000 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11006002 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003
6004 /* Check for ptracing, and update the task SID if ok.
6005 Otherwise, leave SID unchanged and fail. */
Stephen Smalleybe0554c2017-01-09 10:07:31 -05006006 ptsid = ptrace_parent_sid();
Paul Moore0c6181c2016-03-30 21:41:21 -04006007 if (ptsid != 0) {
David Howellsd84f4f92008-11-14 10:39:23 +11006008 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
6009 PROCESS__PTRACE, NULL);
6010 if (error)
6011 goto abort_change;
6012 }
6013
6014 tsec->sid = sid;
6015 } else {
6016 error = -EINVAL;
6017 goto abort_change;
6018 }
6019
6020 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11006022
6023abort_change:
6024 abort_creds(new);
6025 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026}
6027
David Quigley746df9b2013-05-22 12:50:35 -04006028static int selinux_ismaclabel(const char *name)
6029{
6030 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
6031}
6032
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006033static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
6034{
6035 return security_sid_to_context(secid, secdata, seclen);
6036}
6037
David Howells7bf570d2008-04-29 20:52:51 +01006038static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00006039{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01006040 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00006041}
6042
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006043static void selinux_release_secctx(char *secdata, u32 seclen)
6044{
Paul Moore088999e2007-08-01 11:12:58 -04006045 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006046}
6047
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006048static void selinux_inode_invalidate_secctx(struct inode *inode)
6049{
6050 struct inode_security_struct *isec = inode->i_security;
6051
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006052 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006053 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006054 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006055}
6056
David P. Quigley1ee65e32009-09-03 14:25:57 -04006057/*
6058 * called with inode->i_mutex locked
6059 */
6060static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6061{
6062 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6063}
6064
6065/*
6066 * called with inode->i_mutex locked
6067 */
6068static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6069{
6070 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6071}
6072
6073static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6074{
6075 int len = 0;
6076 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6077 ctx, true);
6078 if (len < 0)
6079 return len;
6080 *ctxlen = len;
6081 return 0;
6082}
Michael LeMayd7200242006-06-22 14:47:17 -07006083#ifdef CONFIG_KEYS
6084
David Howellsd84f4f92008-11-14 10:39:23 +11006085static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006086 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006087{
David Howellsd84f4f92008-11-14 10:39:23 +11006088 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006089 struct key_security_struct *ksec;
6090
6091 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6092 if (!ksec)
6093 return -ENOMEM;
6094
David Howellsd84f4f92008-11-14 10:39:23 +11006095 tsec = cred->security;
6096 if (tsec->keycreate_sid)
6097 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006098 else
David Howellsd84f4f92008-11-14 10:39:23 +11006099 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006100
David Howells275bb412008-11-14 10:39:19 +11006101 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006102 return 0;
6103}
6104
6105static void selinux_key_free(struct key *k)
6106{
6107 struct key_security_struct *ksec = k->security;
6108
6109 k->security = NULL;
6110 kfree(ksec);
6111}
6112
6113static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006114 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006115 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006116{
6117 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006118 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006119 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006120
6121 /* if no specific permissions are requested, we skip the
6122 permission check. No serious, additional covert channels
6123 appear to be created. */
6124 if (perm == 0)
6125 return 0;
6126
David Howellsd84f4f92008-11-14 10:39:23 +11006127 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006128
6129 key = key_ref_to_ptr(key_ref);
6130 ksec = key->security;
6131
6132 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006133}
6134
David Howells70a5bb72008-04-29 01:01:26 -07006135static int selinux_key_getsecurity(struct key *key, char **_buffer)
6136{
6137 struct key_security_struct *ksec = key->security;
6138 char *context = NULL;
6139 unsigned len;
6140 int rc;
6141
6142 rc = security_sid_to_context(ksec->sid, &context, &len);
6143 if (!rc)
6144 rc = len;
6145 *_buffer = context;
6146 return rc;
6147}
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006148#endif
David Howells70a5bb72008-04-29 01:01:26 -07006149
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006150#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006151static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6152{
6153 struct common_audit_data ad;
6154 int err;
6155 u32 sid = 0;
6156 struct ib_security_struct *sec = ib_sec;
6157 struct lsm_ibpkey_audit ibpkey;
6158
6159 err = security_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
6160 if (err)
6161 return err;
6162
6163 ad.type = LSM_AUDIT_DATA_IBPKEY;
6164 ibpkey.subnet_prefix = subnet_prefix;
6165 ibpkey.pkey = pkey_val;
6166 ad.u.ibpkey = &ibpkey;
6167 return avc_has_perm(sec->sid, sid,
6168 SECCLASS_INFINIBAND_PKEY,
6169 INFINIBAND_PKEY__ACCESS, &ad);
6170}
6171
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006172static int selinux_ib_alloc_security(void **ib_sec)
6173{
6174 struct ib_security_struct *sec;
6175
6176 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6177 if (!sec)
6178 return -ENOMEM;
6179 sec->sid = current_sid();
6180
6181 *ib_sec = sec;
6182 return 0;
6183}
6184
6185static void selinux_ib_free_security(void *ib_sec)
6186{
6187 kfree(ib_sec);
6188}
Michael LeMayd7200242006-06-22 14:47:17 -07006189#endif
6190
James Morrisca97d932017-02-15 00:18:51 +11006191static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006192 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6193 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6194 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6195 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006196
Casey Schauflere20b0432015-05-02 15:11:36 -07006197 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6198 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6199 LSM_HOOK_INIT(capget, selinux_capget),
6200 LSM_HOOK_INIT(capset, selinux_capset),
6201 LSM_HOOK_INIT(capable, selinux_capable),
6202 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6203 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6204 LSM_HOOK_INIT(syslog, selinux_syslog),
6205 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006206
Casey Schauflere20b0432015-05-02 15:11:36 -07006207 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208
Casey Schauflere20b0432015-05-02 15:11:36 -07006209 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6210 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6211 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
6212 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213
Casey Schauflere20b0432015-05-02 15:11:36 -07006214 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6215 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
6216 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
6217 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6218 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6219 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6220 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6221 LSM_HOOK_INIT(sb_mount, selinux_mount),
6222 LSM_HOOK_INIT(sb_umount, selinux_umount),
6223 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6224 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
6225 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226
Casey Schauflere20b0432015-05-02 15:11:36 -07006227 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006228 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006229
Casey Schauflere20b0432015-05-02 15:11:36 -07006230 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6231 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6232 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6233 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6234 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6235 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6236 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6237 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6238 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6239 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6240 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6241 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6242 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6243 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6244 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6245 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6246 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6247 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6248 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6249 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6250 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6251 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6252 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6253 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6254 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006255 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006256 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006257
Casey Schauflere20b0432015-05-02 15:11:36 -07006258 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6259 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6260 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6261 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6262 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6263 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6264 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6265 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6266 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6267 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6268 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6269 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270
Casey Schauflere20b0432015-05-02 15:11:36 -07006271 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272
Tetsuo Handaa79be232017-03-28 23:08:45 +09006273 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
Casey Schauflere20b0432015-05-02 15:11:36 -07006274 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6275 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6276 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6277 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
6278 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6279 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6280 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006281 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006282 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6283 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6284 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6285 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6286 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6287 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6288 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
Stephen Smalley791ec492017-02-17 07:57:00 -05006289 LSM_HOOK_INIT(task_prlimit, selinux_task_prlimit),
Casey Schauflere20b0432015-05-02 15:11:36 -07006290 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6291 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6292 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6293 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6294 LSM_HOOK_INIT(task_kill, selinux_task_kill),
Casey Schauflere20b0432015-05-02 15:11:36 -07006295 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006296
Casey Schauflere20b0432015-05-02 15:11:36 -07006297 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6298 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Casey Schauflere20b0432015-05-02 15:11:36 -07006300 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6301 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302
Casey Schauflere20b0432015-05-02 15:11:36 -07006303 LSM_HOOK_INIT(msg_queue_alloc_security,
6304 selinux_msg_queue_alloc_security),
6305 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6306 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6307 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6308 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6309 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310
Casey Schauflere20b0432015-05-02 15:11:36 -07006311 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6312 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6313 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6314 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6315 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316
Casey Schauflere20b0432015-05-02 15:11:36 -07006317 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6318 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6319 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6320 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6321 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006322
Casey Schauflere20b0432015-05-02 15:11:36 -07006323 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006324
Casey Schauflere20b0432015-05-02 15:11:36 -07006325 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6326 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006327
Casey Schauflere20b0432015-05-02 15:11:36 -07006328 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6329 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6330 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6331 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006332 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006333 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6334 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6335 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336
Casey Schauflere20b0432015-05-02 15:11:36 -07006337 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6338 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006339
Casey Schauflere20b0432015-05-02 15:11:36 -07006340 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6341 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6342 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6343 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6344 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6345 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6346 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6347 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6348 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6349 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6350 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6351 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6352 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6353 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6354 LSM_HOOK_INIT(socket_getpeersec_stream,
6355 selinux_socket_getpeersec_stream),
6356 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6357 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6358 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6359 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6360 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6361 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6362 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6363 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6364 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6365 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6366 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6367 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6368 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6369 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6370 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6371 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6372 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6373 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6374 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006375#ifdef CONFIG_SECURITY_INFINIBAND
Daniel Jurgenscfc4d882017-05-19 15:48:57 +03006376 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
Daniel Jurgens3a976fa2017-05-19 15:48:56 +03006377 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6378 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6379#endif
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006380#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006381 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6382 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6383 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6384 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6385 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6386 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6387 selinux_xfrm_state_alloc_acquire),
6388 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6389 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6390 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6391 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6392 selinux_xfrm_state_pol_flow_match),
6393 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006394#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006395
6396#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006397 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6398 LSM_HOOK_INIT(key_free, selinux_key_free),
6399 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6400 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006401#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006402
6403#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006404 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6405 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6406 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6407 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006408#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006409};
6410
6411static __init int selinux_init(void)
6412{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006413 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006414 selinux_enabled = 0;
6415 return 0;
6416 }
6417
Linus Torvalds1da177e2005-04-16 15:20:36 -07006418 if (!selinux_enabled) {
6419 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6420 return 0;
6421 }
6422
6423 printk(KERN_INFO "SELinux: Initializing.\n");
6424
6425 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006426 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006427
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006428 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6429
James Morris7cae7e22006-03-22 00:09:22 -08006430 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6431 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006432 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006433 file_security_cache = kmem_cache_create("selinux_file_security",
6434 sizeof(struct file_security_struct),
6435 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436 avc_init();
6437
Casey Schauflerd69dece52017-01-18 17:09:05 -08006438 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439
Paul Moore615e51f2014-06-26 14:33:56 -04006440 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6441 panic("SELinux: Unable to register AVC netcache callback\n");
6442
Daniel Jurgens8f408ab2017-05-19 15:48:53 +03006443 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6444 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6445
Eric Paris828dfe12008-04-17 13:17:49 -04006446 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006447 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006448 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006449 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006450
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451 return 0;
6452}
6453
Al Viroe8c26252010-03-23 06:36:54 -04006454static void delayed_superblock_init(struct super_block *sb, void *unused)
6455{
6456 superblock_doinit(sb, NULL);
6457}
6458
Linus Torvalds1da177e2005-04-16 15:20:36 -07006459void selinux_complete_init(void)
6460{
Eric Parisfadcdb42007-02-22 18:11:31 -05006461 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006462
6463 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006464 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006465 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006466}
6467
6468/* SELinux requires early initialization in order to label
6469 all processes and objects when they are created. */
6470security_initcall(selinux_init);
6471
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006472#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473
Jiri Pirko25db6be2014-09-03 17:42:13 +02006474static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006475 {
6476 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006477 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006478 .hooknum = NF_INET_POST_ROUTING,
6479 .priority = NF_IP_PRI_SELINUX_LAST,
6480 },
6481 {
6482 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006483 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006484 .hooknum = NF_INET_FORWARD,
6485 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006486 },
6487 {
6488 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006489 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006490 .hooknum = NF_INET_LOCAL_OUT,
6491 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006492 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04006493#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006494 {
6495 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006496 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006497 .hooknum = NF_INET_POST_ROUTING,
6498 .priority = NF_IP6_PRI_SELINUX_LAST,
6499 },
6500 {
6501 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006502 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006503 .hooknum = NF_INET_FORWARD,
6504 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006505 },
Huw Davies2917f572016-06-27 15:06:15 -04006506 {
6507 .hook = selinux_ipv6_output,
6508 .pf = NFPROTO_IPV6,
6509 .hooknum = NF_INET_LOCAL_OUT,
6510 .priority = NF_IP6_PRI_SELINUX_FIRST,
6511 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006513};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514
6515static int __init selinux_nf_ip_init(void)
6516{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006517 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006518
6519 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006520 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006521
6522 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6523
Jiri Pirko25db6be2014-09-03 17:42:13 +02006524 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006525 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006526 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
Jiri Pirko25db6be2014-09-03 17:42:13 +02006528 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006529}
6530
6531__initcall(selinux_nf_ip_init);
6532
6533#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6534static void selinux_nf_ip_exit(void)
6535{
Eric Parisfadcdb42007-02-22 18:11:31 -05006536 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006537
Jiri Pirko25db6be2014-09-03 17:42:13 +02006538 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006539}
6540#endif
6541
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006542#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543
6544#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6545#define selinux_nf_ip_exit()
6546#endif
6547
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006548#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006549
6550#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006551static int selinux_disabled;
6552
Linus Torvalds1da177e2005-04-16 15:20:36 -07006553int selinux_disable(void)
6554{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555 if (ss_initialized) {
6556 /* Not permitted after initial policy load. */
6557 return -EINVAL;
6558 }
6559
6560 if (selinux_disabled) {
6561 /* Only do this once. */
6562 return -EINVAL;
6563 }
6564
6565 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6566
6567 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006568 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006570 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006571
Eric Parisaf8ff042009-09-20 21:23:01 -04006572 /* Try to destroy the avc node cache */
6573 avc_disable();
6574
Linus Torvalds1da177e2005-04-16 15:20:36 -07006575 /* Unregister netfilter hooks. */
6576 selinux_nf_ip_exit();
6577
6578 /* Unregister selinuxfs. */
6579 exit_sel_fs();
6580
6581 return 0;
6582}
6583#endif