blob: 469f5c75bd4b238742673e3aab30270cb0c63999 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e1121722008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400129static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800130
Paul Moored621d352008-01-29 08:43:36 -0500131/**
132 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
133 *
134 * Description:
135 * This function checks the SECMARK reference counter to see if any SECMARK
136 * targets are currently configured, if the reference counter is greater than
137 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400138 * enabled, false (0) if SECMARK is disabled. If the always_check_network
139 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500140 *
141 */
142static int selinux_secmark_enabled(void)
143{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400144 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
145}
146
147/**
148 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
149 *
150 * Description:
151 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
152 * (1) if any are enabled or false (0) if neither are enabled. If the
153 * always_check_network policy capability is enabled, peer labeling
154 * is always considered enabled.
155 *
156 */
157static int selinux_peerlbl_enabled(void)
158{
159 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500160}
161
Paul Moore615e51f2014-06-26 14:33:56 -0400162static int selinux_netcache_avc_callback(u32 event)
163{
164 if (event == AVC_CALLBACK_RESET) {
165 sel_netif_flush();
166 sel_netnode_flush();
167 sel_netport_flush();
168 synchronize_net();
169 }
170 return 0;
171}
172
David Howellsd84f4f92008-11-14 10:39:23 +1100173/*
174 * initialise the security for the init task
175 */
176static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
David Howells3b11a1d2008-11-14 10:39:26 +1100178 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 struct task_security_struct *tsec;
180
James Morris89d155e2005-10-30 14:59:21 -0800181 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100183 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
David Howellsd84f4f92008-11-14 10:39:23 +1100185 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100186 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
David Howells275bb412008-11-14 10:39:19 +1100189/*
David Howells88e67f32008-11-14 10:39:21 +1100190 * get the security ID of a set of credentials
191 */
192static inline u32 cred_sid(const struct cred *cred)
193{
194 const struct task_security_struct *tsec;
195
196 tsec = cred->security;
197 return tsec->sid;
198}
199
200/*
David Howells3b11a1d2008-11-14 10:39:26 +1100201 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100202 */
203static inline u32 task_sid(const struct task_struct *task)
204{
David Howells275bb412008-11-14 10:39:19 +1100205 u32 sid;
206
207 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100208 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100209 rcu_read_unlock();
210 return sid;
211}
212
213/*
David Howells3b11a1d2008-11-14 10:39:26 +1100214 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100215 */
216static inline u32 current_sid(void)
217{
Paul Moore5fb49872010-04-22 14:46:19 -0400218 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100219
220 return tsec->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
Eric Paris23970742006-09-25 23:32:01 -0700234 mutex_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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 inode->i_security = isec;
241
242 return 0;
243}
244
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500245static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
246
247/*
248 * Try reloading inode security labels that have been marked as invalid. The
249 * @may_sleep parameter indicates when sleeping and thus reloading labels is
250 * allowed; when set to false, returns ERR_PTR(-ECHILD) when the label is
251 * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
252 * when no dentry is available, set it to NULL instead.
253 */
254static int __inode_security_revalidate(struct inode *inode,
255 struct dentry *opt_dentry,
256 bool may_sleep)
257{
258 struct inode_security_struct *isec = inode->i_security;
259
260 might_sleep_if(may_sleep);
261
262 if (isec->initialized == LABEL_INVALID) {
263 if (!may_sleep)
264 return -ECHILD;
265
266 /*
267 * Try reloading the inode security label. This will fail if
268 * @opt_dentry is NULL and no dentry for this inode can be
269 * found; in that case, continue using the old label.
270 */
271 inode_doinit_with_dentry(inode, opt_dentry);
272 }
273 return 0;
274}
275
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500276static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
277{
278 return inode->i_security;
279}
280
281static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
282{
283 int error;
284
285 error = __inode_security_revalidate(inode, NULL, !rcu);
286 if (error)
287 return ERR_PTR(error);
288 return inode->i_security;
289}
290
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500291/*
292 * Get the security label of an inode.
293 */
294static struct inode_security_struct *inode_security(struct inode *inode)
295{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500296 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500297 return inode->i_security;
298}
299
300/*
301 * Get the security label of a dentry's backing inode.
302 */
303static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
304{
305 struct inode *inode = d_backing_inode(dentry);
306
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500307 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500308 return inode->i_security;
309}
310
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500311static void inode_free_rcu(struct rcu_head *head)
312{
313 struct inode_security_struct *isec;
314
315 isec = container_of(head, struct inode_security_struct, rcu);
316 kmem_cache_free(sel_inode_cache, isec);
317}
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319static void inode_free_security(struct inode *inode)
320{
321 struct inode_security_struct *isec = inode->i_security;
322 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
323
Waiman Long9629d042015-07-10 17:19:56 -0400324 /*
325 * As not all inode security structures are in a list, we check for
326 * empty list outside of the lock to make sure that we won't waste
327 * time taking a lock doing nothing.
328 *
329 * The list_del_init() function can be safely called more than once.
330 * It should not be possible for this function to be called with
331 * concurrent list_add(), but for better safety against future changes
332 * in the code, we use list_empty_careful() here.
333 */
334 if (!list_empty_careful(&isec->list)) {
335 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400337 spin_unlock(&sbsec->isec_lock);
338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500340 /*
341 * The inode may still be referenced in a path walk and
342 * a call to selinux_inode_permission() can be made
343 * after inode_free_security() is called. Ideally, the VFS
344 * wouldn't do this, but fixing that is a much harder
345 * job. For now, simply free the i_security via RCU, and
346 * leave the current inode->i_security pointer intact.
347 * The inode will be freed after the RCU grace period too.
348 */
349 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351
352static int file_alloc_security(struct file *file)
353{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100355 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Sangwoo63205652015-10-21 17:44:30 -0400357 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 if (!fsec)
359 return -ENOMEM;
360
David Howells275bb412008-11-14 10:39:19 +1100361 fsec->sid = sid;
362 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 file->f_security = fsec;
364
365 return 0;
366}
367
368static void file_free_security(struct file *file)
369{
370 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400372 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373}
374
375static int superblock_alloc_security(struct super_block *sb)
376{
377 struct superblock_security_struct *sbsec;
378
James Morris89d155e2005-10-30 14:59:21 -0800379 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (!sbsec)
381 return -ENOMEM;
382
Eric Parisbc7e9822006-09-25 23:32:02 -0700383 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 INIT_LIST_HEAD(&sbsec->isec_head);
385 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 sbsec->sb = sb;
387 sbsec->sid = SECINITSID_UNLABELED;
388 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700389 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 sb->s_security = sbsec;
391
392 return 0;
393}
394
395static void superblock_free_security(struct super_block *sb)
396{
397 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 sb->s_security = NULL;
399 kfree(sbsec);
400}
401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402/* The file system's label must be initialized prior to use. */
403
David Quigleyeb9ae682013-05-22 12:50:37 -0400404static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 "uses xattr",
406 "uses transition SIDs",
407 "uses task SIDs",
408 "uses genfs_contexts",
409 "not configured for labeling",
410 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400411 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412};
413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414static inline int inode_doinit(struct inode *inode)
415{
416 return inode_doinit_with_dentry(inode, NULL);
417}
418
419enum {
Eric Paris31e87932007-09-19 17:19:12 -0400420 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 Opt_context = 1,
422 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500423 Opt_defcontext = 3,
424 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500425 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400426 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427};
428
Eric Parisd355987f2012-08-24 15:58:53 -0400429#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
430
Steven Whitehousea447c092008-10-13 10:46:57 +0100431static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400432 {Opt_context, CONTEXT_STR "%s"},
433 {Opt_fscontext, FSCONTEXT_STR "%s"},
434 {Opt_defcontext, DEFCONTEXT_STR "%s"},
435 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500436 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400437 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438};
439
440#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
441
Eric Parisc312feb2006-07-10 04:43:53 -0700442static int may_context_mount_sb_relabel(u32 sid,
443 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100444 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700445{
David Howells275bb412008-11-14 10:39:19 +1100446 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700447 int rc;
448
449 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
450 FILESYSTEM__RELABELFROM, NULL);
451 if (rc)
452 return rc;
453
454 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
455 FILESYSTEM__RELABELTO, NULL);
456 return rc;
457}
458
Eric Paris08089252006-07-10 04:43:55 -0700459static int may_context_mount_inode_relabel(u32 sid,
460 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100461 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700462{
David Howells275bb412008-11-14 10:39:19 +1100463 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700464 int rc;
465 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
466 FILESYSTEM__RELABELFROM, NULL);
467 if (rc)
468 return rc;
469
470 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
471 FILESYSTEM__ASSOCIATE, NULL);
472 return rc;
473}
474
Eric Parisb43e7252012-10-10 14:27:35 -0400475static int selinux_is_sblabel_mnt(struct super_block *sb)
476{
477 struct superblock_security_struct *sbsec = sb->s_security;
478
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500479 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
480 sbsec->behavior == SECURITY_FS_USE_TRANS ||
481 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400482 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500483 /* Special handling. Genfs but also in-core setxattr handler */
484 !strcmp(sb->s_type->name, "sysfs") ||
485 !strcmp(sb->s_type->name, "pstore") ||
486 !strcmp(sb->s_type->name, "debugfs") ||
487 !strcmp(sb->s_type->name, "rootfs");
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. */
Eric Parisc9180a52007-11-30 13:00:35 -0500503 if (!root_inode->i_op->getxattr) {
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 }
Al Viroce23e642016-04-11 00:48:00 -0400509 rc = root_inode->i_op->getxattr(root, root_inode,
510 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 Parisc9180a52007-11-30 13:00:35 -0500524 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800525 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
526 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Eric Pariseadcabc2012-08-24 15:59:14 -0400528 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400529 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400530 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400531
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500533 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
535 /* Initialize any other inodes associated with the superblock, e.g.
536 inodes created prior to initial policy load or inodes created
537 during get_sb by a pseudo filesystem that directly
538 populates itself. */
539 spin_lock(&sbsec->isec_lock);
540next_inode:
541 if (!list_empty(&sbsec->isec_head)) {
542 struct inode_security_struct *isec =
543 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500544 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400546 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 spin_unlock(&sbsec->isec_lock);
548 inode = igrab(inode);
549 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500550 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 inode_doinit(inode);
552 iput(inode);
553 }
554 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 goto next_inode;
556 }
557 spin_unlock(&sbsec->isec_lock);
558out:
Eric Parisc9180a52007-11-30 13:00:35 -0500559 return rc;
560}
561
562/*
563 * This function should allow an FS to ask what it's mount security
564 * options were so it can use those later for submounts, displaying
565 * mount options, or whatever.
566 */
567static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500568 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500569{
570 int rc = 0, i;
571 struct superblock_security_struct *sbsec = sb->s_security;
572 char *context = NULL;
573 u32 len;
574 char tmp;
575
Eric Parise0007522008-03-05 10:31:54 -0500576 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500577
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500578 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500579 return -EINVAL;
580
581 if (!ss_initialized)
582 return -EINVAL;
583
Eric Parisaf8e50c2012-08-24 15:59:00 -0400584 /* make sure we always check enough bits to cover the mask */
585 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
586
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500587 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500588 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400589 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500590 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500591 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500592 tmp >>= 1;
593 }
David P. Quigley11689d42009-01-16 09:22:03 -0500594 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400595 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500596 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500597
Eric Parise0007522008-03-05 10:31:54 -0500598 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
599 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500600 rc = -ENOMEM;
601 goto out_free;
602 }
603
Eric Parise0007522008-03-05 10:31:54 -0500604 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
605 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500606 rc = -ENOMEM;
607 goto out_free;
608 }
609
610 i = 0;
611 if (sbsec->flags & FSCONTEXT_MNT) {
612 rc = security_sid_to_context(sbsec->sid, &context, &len);
613 if (rc)
614 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500615 opts->mnt_opts[i] = context;
616 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500617 }
618 if (sbsec->flags & CONTEXT_MNT) {
619 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
620 if (rc)
621 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500622 opts->mnt_opts[i] = context;
623 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500624 }
625 if (sbsec->flags & DEFCONTEXT_MNT) {
626 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
627 if (rc)
628 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500629 opts->mnt_opts[i] = context;
630 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500631 }
632 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500633 struct dentry *root = sbsec->sb->s_root;
634 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500635
636 rc = security_sid_to_context(isec->sid, &context, &len);
637 if (rc)
638 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500639 opts->mnt_opts[i] = context;
640 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500641 }
Eric Paris12f348b2012-10-09 10:56:25 -0400642 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500643 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400644 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500645 }
Eric Parisc9180a52007-11-30 13:00:35 -0500646
Eric Parise0007522008-03-05 10:31:54 -0500647 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500648
649 return 0;
650
651out_free:
Eric Parise0007522008-03-05 10:31:54 -0500652 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500653 return rc;
654}
655
656static int bad_option(struct superblock_security_struct *sbsec, char flag,
657 u32 old_sid, u32 new_sid)
658{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500659 char mnt_flags = sbsec->flags & SE_MNTMASK;
660
Eric Parisc9180a52007-11-30 13:00:35 -0500661 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500662 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500663 if (!(sbsec->flags & flag) ||
664 (old_sid != new_sid))
665 return 1;
666
667 /* check if we were passed the same options twice,
668 * aka someone passed context=a,context=b
669 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500670 if (!(sbsec->flags & SE_SBINITIALIZED))
671 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500672 return 1;
673 return 0;
674}
Eric Parise0007522008-03-05 10:31:54 -0500675
Eric Parisc9180a52007-11-30 13:00:35 -0500676/*
677 * Allow filesystems with binary mount data to explicitly set mount point
678 * labeling information.
679 */
Eric Parise0007522008-03-05 10:31:54 -0500680static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400681 struct security_mnt_opts *opts,
682 unsigned long kern_flags,
683 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500684{
David Howells275bb412008-11-14 10:39:19 +1100685 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500686 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500687 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800688 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500689 struct dentry *root = sbsec->sb->s_root;
690 struct inode_security_struct *root_isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500691 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
692 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500693 char **mount_options = opts->mnt_opts;
694 int *flags = opts->mnt_opts_flags;
695 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500696
697 mutex_lock(&sbsec->lock);
698
699 if (!ss_initialized) {
700 if (!num_opts) {
701 /* Defer initialization until selinux_complete_init,
702 after the initial policy is loaded and the security
703 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500704 goto out;
705 }
706 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400707 printk(KERN_WARNING "SELinux: Unable to set superblock options "
708 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500709 goto out;
710 }
David Quigley649f6e72013-05-22 12:50:36 -0400711 if (kern_flags && !set_kern_flags) {
712 /* Specifying internal flags without providing a place to
713 * place the results is not allowed */
714 rc = -EINVAL;
715 goto out;
716 }
Eric Parisc9180a52007-11-30 13:00:35 -0500717
718 /*
Eric Parise0007522008-03-05 10:31:54 -0500719 * Binary mount data FS will come through this function twice. Once
720 * from an explicit call and once from the generic calls from the vfs.
721 * Since the generic VFS calls will not contain any security mount data
722 * we need to skip the double mount verification.
723 *
724 * This does open a hole in which we will not notice if the first
725 * mount using this sb set explict options and a second mount using
726 * this sb does not set any security options. (The first options
727 * will be used for both mounts)
728 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500729 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500730 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400731 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500732
733 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500734 * parse the mount options, check if they are valid sids.
735 * also check if someone is trying to mount the same sb more
736 * than once with different security options.
737 */
738 for (i = 0; i < num_opts; i++) {
739 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500740
Eric Paris12f348b2012-10-09 10:56:25 -0400741 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500742 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400743 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500744 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400745 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800746 "(%s) failed for (dev %s, type %s) errno=%d\n",
747 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500748 goto out;
749 }
750 switch (flags[i]) {
751 case FSCONTEXT_MNT:
752 fscontext_sid = sid;
753
754 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
755 fscontext_sid))
756 goto out_double_mount;
757
758 sbsec->flags |= FSCONTEXT_MNT;
759 break;
760 case CONTEXT_MNT:
761 context_sid = sid;
762
763 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
764 context_sid))
765 goto out_double_mount;
766
767 sbsec->flags |= CONTEXT_MNT;
768 break;
769 case ROOTCONTEXT_MNT:
770 rootcontext_sid = sid;
771
772 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
773 rootcontext_sid))
774 goto out_double_mount;
775
776 sbsec->flags |= ROOTCONTEXT_MNT;
777
778 break;
779 case DEFCONTEXT_MNT:
780 defcontext_sid = sid;
781
782 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
783 defcontext_sid))
784 goto out_double_mount;
785
786 sbsec->flags |= DEFCONTEXT_MNT;
787
788 break;
789 default:
790 rc = -EINVAL;
791 goto out;
792 }
793 }
794
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500795 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500796 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500797 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500798 goto out_double_mount;
799 rc = 0;
800 goto out;
801 }
802
James Morris089be432008-07-15 18:32:49 +1000803 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400804 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
805
Stephen Smalley8e014722015-06-04 16:22:17 -0400806 if (!strcmp(sb->s_type->name, "debugfs") ||
807 !strcmp(sb->s_type->name, "sysfs") ||
808 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400809 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500810
David Quigleyeb9ae682013-05-22 12:50:37 -0400811 if (!sbsec->behavior) {
812 /*
813 * Determine the labeling behavior to use for this
814 * filesystem type.
815 */
Paul Moore98f700f2013-09-18 13:52:20 -0400816 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400817 if (rc) {
818 printk(KERN_WARNING
819 "%s: security_fs_use(%s) returned %d\n",
820 __func__, sb->s_type->name, rc);
821 goto out;
822 }
Eric Parisc9180a52007-11-30 13:00:35 -0500823 }
Eric Parisc9180a52007-11-30 13:00:35 -0500824 /* sets the context of the superblock for the fs being mounted. */
825 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100826 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500827 if (rc)
828 goto out;
829
830 sbsec->sid = fscontext_sid;
831 }
832
833 /*
834 * Switch to using mount point labeling behavior.
835 * sets the label used on all file below the mountpoint, and will set
836 * the superblock context if not already set.
837 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400838 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
839 sbsec->behavior = SECURITY_FS_USE_NATIVE;
840 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
841 }
842
Eric Parisc9180a52007-11-30 13:00:35 -0500843 if (context_sid) {
844 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100845 rc = may_context_mount_sb_relabel(context_sid, sbsec,
846 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500847 if (rc)
848 goto out;
849 sbsec->sid = context_sid;
850 } else {
David Howells275bb412008-11-14 10:39:19 +1100851 rc = may_context_mount_inode_relabel(context_sid, sbsec,
852 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500853 if (rc)
854 goto out;
855 }
856 if (!rootcontext_sid)
857 rootcontext_sid = context_sid;
858
859 sbsec->mntpoint_sid = context_sid;
860 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
861 }
862
863 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100864 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
865 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500866 if (rc)
867 goto out;
868
869 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500870 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500871 }
872
873 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400874 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
875 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500876 rc = -EINVAL;
877 printk(KERN_WARNING "SELinux: defcontext option is "
878 "invalid for this filesystem type\n");
879 goto out;
880 }
881
882 if (defcontext_sid != sbsec->def_sid) {
883 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100884 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500885 if (rc)
886 goto out;
887 }
888
889 sbsec->def_sid = defcontext_sid;
890 }
891
892 rc = sb_finish_set_opts(sb);
893out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700894 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500896out_double_mount:
897 rc = -EINVAL;
898 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800899 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500900 goto out;
901}
902
Jeff Layton094f7b62013-04-01 08:14:24 -0400903static int selinux_cmp_sb_context(const struct super_block *oldsb,
904 const struct super_block *newsb)
905{
906 struct superblock_security_struct *old = oldsb->s_security;
907 struct superblock_security_struct *new = newsb->s_security;
908 char oldflags = old->flags & SE_MNTMASK;
909 char newflags = new->flags & SE_MNTMASK;
910
911 if (oldflags != newflags)
912 goto mismatch;
913 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
914 goto mismatch;
915 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
916 goto mismatch;
917 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
918 goto mismatch;
919 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500920 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
921 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400922 if (oldroot->sid != newroot->sid)
923 goto mismatch;
924 }
925 return 0;
926mismatch:
927 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
928 "different security settings for (dev %s, "
929 "type %s)\n", newsb->s_id, newsb->s_type->name);
930 return -EBUSY;
931}
932
933static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500934 struct super_block *newsb)
935{
936 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
937 struct superblock_security_struct *newsbsec = newsb->s_security;
938
939 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
940 int set_context = (oldsbsec->flags & CONTEXT_MNT);
941 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
942
Eric Paris0f5e6422008-04-21 16:24:11 -0400943 /*
944 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400945 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400946 */
Al Viroe8c26252010-03-23 06:36:54 -0400947 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400948 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500949
Eric Parisc9180a52007-11-30 13:00:35 -0500950 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500951 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500952
Jeff Layton094f7b62013-04-01 08:14:24 -0400953 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500954 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400955 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400956
Eric Parisc9180a52007-11-30 13:00:35 -0500957 mutex_lock(&newsbsec->lock);
958
959 newsbsec->flags = oldsbsec->flags;
960
961 newsbsec->sid = oldsbsec->sid;
962 newsbsec->def_sid = oldsbsec->def_sid;
963 newsbsec->behavior = oldsbsec->behavior;
964
965 if (set_context) {
966 u32 sid = oldsbsec->mntpoint_sid;
967
968 if (!set_fscontext)
969 newsbsec->sid = sid;
970 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500971 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500972 newisec->sid = sid;
973 }
974 newsbsec->mntpoint_sid = sid;
975 }
976 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500977 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
978 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500979
980 newisec->sid = oldisec->sid;
981 }
982
983 sb_finish_set_opts(newsb);
984 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400985 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500986}
987
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200988static int selinux_parse_opts_str(char *options,
989 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500990{
Eric Parise0007522008-03-05 10:31:54 -0500991 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500992 char *context = NULL, *defcontext = NULL;
993 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500994 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500995
Eric Parise0007522008-03-05 10:31:54 -0500996 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500997
998 /* Standard string-based options. */
999 while ((p = strsep(&options, "|")) != NULL) {
1000 int token;
1001 substring_t args[MAX_OPT_ARGS];
1002
1003 if (!*p)
1004 continue;
1005
1006 token = match_token(p, tokens, args);
1007
1008 switch (token) {
1009 case Opt_context:
1010 if (context || defcontext) {
1011 rc = -EINVAL;
1012 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1013 goto out_err;
1014 }
1015 context = match_strdup(&args[0]);
1016 if (!context) {
1017 rc = -ENOMEM;
1018 goto out_err;
1019 }
1020 break;
1021
1022 case Opt_fscontext:
1023 if (fscontext) {
1024 rc = -EINVAL;
1025 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1026 goto out_err;
1027 }
1028 fscontext = match_strdup(&args[0]);
1029 if (!fscontext) {
1030 rc = -ENOMEM;
1031 goto out_err;
1032 }
1033 break;
1034
1035 case Opt_rootcontext:
1036 if (rootcontext) {
1037 rc = -EINVAL;
1038 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1039 goto out_err;
1040 }
1041 rootcontext = match_strdup(&args[0]);
1042 if (!rootcontext) {
1043 rc = -ENOMEM;
1044 goto out_err;
1045 }
1046 break;
1047
1048 case Opt_defcontext:
1049 if (context || defcontext) {
1050 rc = -EINVAL;
1051 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1052 goto out_err;
1053 }
1054 defcontext = match_strdup(&args[0]);
1055 if (!defcontext) {
1056 rc = -ENOMEM;
1057 goto out_err;
1058 }
1059 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001060 case Opt_labelsupport:
1061 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001062 default:
1063 rc = -EINVAL;
1064 printk(KERN_WARNING "SELinux: unknown mount option\n");
1065 goto out_err;
1066
1067 }
1068 }
1069
Eric Parise0007522008-03-05 10:31:54 -05001070 rc = -ENOMEM;
1071 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1072 if (!opts->mnt_opts)
1073 goto out_err;
1074
1075 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1076 if (!opts->mnt_opts_flags) {
1077 kfree(opts->mnt_opts);
1078 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001079 }
1080
Eric Parise0007522008-03-05 10:31:54 -05001081 if (fscontext) {
1082 opts->mnt_opts[num_mnt_opts] = fscontext;
1083 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1084 }
1085 if (context) {
1086 opts->mnt_opts[num_mnt_opts] = context;
1087 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1088 }
1089 if (rootcontext) {
1090 opts->mnt_opts[num_mnt_opts] = rootcontext;
1091 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1092 }
1093 if (defcontext) {
1094 opts->mnt_opts[num_mnt_opts] = defcontext;
1095 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1096 }
1097
1098 opts->num_mnt_opts = num_mnt_opts;
1099 return 0;
1100
Eric Parisc9180a52007-11-30 13:00:35 -05001101out_err:
1102 kfree(context);
1103 kfree(defcontext);
1104 kfree(fscontext);
1105 kfree(rootcontext);
1106 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
Eric Parise0007522008-03-05 10:31:54 -05001108/*
1109 * string mount options parsing and call set the sbsec
1110 */
1111static int superblock_doinit(struct super_block *sb, void *data)
1112{
1113 int rc = 0;
1114 char *options = data;
1115 struct security_mnt_opts opts;
1116
1117 security_init_mnt_opts(&opts);
1118
1119 if (!data)
1120 goto out;
1121
1122 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1123
1124 rc = selinux_parse_opts_str(options, &opts);
1125 if (rc)
1126 goto out_err;
1127
1128out:
David Quigley649f6e72013-05-22 12:50:36 -04001129 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001130
1131out_err:
1132 security_free_mnt_opts(&opts);
1133 return rc;
1134}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Adrian Bunk3583a712008-07-22 20:21:23 +03001136static void selinux_write_opts(struct seq_file *m,
1137 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001138{
1139 int i;
1140 char *prefix;
1141
1142 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001143 char *has_comma;
1144
1145 if (opts->mnt_opts[i])
1146 has_comma = strchr(opts->mnt_opts[i], ',');
1147 else
1148 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001149
1150 switch (opts->mnt_opts_flags[i]) {
1151 case CONTEXT_MNT:
1152 prefix = CONTEXT_STR;
1153 break;
1154 case FSCONTEXT_MNT:
1155 prefix = FSCONTEXT_STR;
1156 break;
1157 case ROOTCONTEXT_MNT:
1158 prefix = ROOTCONTEXT_STR;
1159 break;
1160 case DEFCONTEXT_MNT:
1161 prefix = DEFCONTEXT_STR;
1162 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001163 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001164 seq_putc(m, ',');
1165 seq_puts(m, LABELSUPP_STR);
1166 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001167 default:
1168 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001169 return;
Eric Paris2069f452008-07-04 09:47:13 +10001170 };
1171 /* we need a comma before each option */
1172 seq_putc(m, ',');
1173 seq_puts(m, prefix);
1174 if (has_comma)
1175 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001176 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001177 if (has_comma)
1178 seq_putc(m, '\"');
1179 }
1180}
1181
1182static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1183{
1184 struct security_mnt_opts opts;
1185 int rc;
1186
1187 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001188 if (rc) {
1189 /* before policy load we may get EINVAL, don't show anything */
1190 if (rc == -EINVAL)
1191 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001192 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001193 }
Eric Paris2069f452008-07-04 09:47:13 +10001194
1195 selinux_write_opts(m, &opts);
1196
1197 security_free_mnt_opts(&opts);
1198
1199 return rc;
1200}
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202static inline u16 inode_mode_to_security_class(umode_t mode)
1203{
1204 switch (mode & S_IFMT) {
1205 case S_IFSOCK:
1206 return SECCLASS_SOCK_FILE;
1207 case S_IFLNK:
1208 return SECCLASS_LNK_FILE;
1209 case S_IFREG:
1210 return SECCLASS_FILE;
1211 case S_IFBLK:
1212 return SECCLASS_BLK_FILE;
1213 case S_IFDIR:
1214 return SECCLASS_DIR;
1215 case S_IFCHR:
1216 return SECCLASS_CHR_FILE;
1217 case S_IFIFO:
1218 return SECCLASS_FIFO_FILE;
1219
1220 }
1221
1222 return SECCLASS_FILE;
1223}
1224
James Morris13402582005-09-30 14:24:34 -04001225static inline int default_protocol_stream(int protocol)
1226{
1227 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1228}
1229
1230static inline int default_protocol_dgram(int protocol)
1231{
1232 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1233}
1234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1236{
1237 switch (family) {
1238 case PF_UNIX:
1239 switch (type) {
1240 case SOCK_STREAM:
1241 case SOCK_SEQPACKET:
1242 return SECCLASS_UNIX_STREAM_SOCKET;
1243 case SOCK_DGRAM:
1244 return SECCLASS_UNIX_DGRAM_SOCKET;
1245 }
1246 break;
1247 case PF_INET:
1248 case PF_INET6:
1249 switch (type) {
1250 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001251 if (default_protocol_stream(protocol))
1252 return SECCLASS_TCP_SOCKET;
1253 else
1254 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001256 if (default_protocol_dgram(protocol))
1257 return SECCLASS_UDP_SOCKET;
1258 else
1259 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001260 case SOCK_DCCP:
1261 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001262 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 return SECCLASS_RAWIP_SOCKET;
1264 }
1265 break;
1266 case PF_NETLINK:
1267 switch (protocol) {
1268 case NETLINK_ROUTE:
1269 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001270 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1272 case NETLINK_NFLOG:
1273 return SECCLASS_NETLINK_NFLOG_SOCKET;
1274 case NETLINK_XFRM:
1275 return SECCLASS_NETLINK_XFRM_SOCKET;
1276 case NETLINK_SELINUX:
1277 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001278 case NETLINK_ISCSI:
1279 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 case NETLINK_AUDIT:
1281 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001282 case NETLINK_FIB_LOOKUP:
1283 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1284 case NETLINK_CONNECTOR:
1285 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1286 case NETLINK_NETFILTER:
1287 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 case NETLINK_DNRTMSG:
1289 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001290 case NETLINK_KOBJECT_UEVENT:
1291 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001292 case NETLINK_GENERIC:
1293 return SECCLASS_NETLINK_GENERIC_SOCKET;
1294 case NETLINK_SCSITRANSPORT:
1295 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1296 case NETLINK_RDMA:
1297 return SECCLASS_NETLINK_RDMA_SOCKET;
1298 case NETLINK_CRYPTO:
1299 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 default:
1301 return SECCLASS_NETLINK_SOCKET;
1302 }
1303 case PF_PACKET:
1304 return SECCLASS_PACKET_SOCKET;
1305 case PF_KEY:
1306 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001307 case PF_APPLETALK:
1308 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 }
1310
1311 return SECCLASS_SOCKET;
1312}
1313
Stephen Smalley134509d2015-06-04 16:22:17 -04001314static int selinux_genfs_get_sid(struct dentry *dentry,
1315 u16 tclass,
1316 u16 flags,
1317 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001319 int rc;
Al Virofc640052016-04-10 01:33:30 -04001320 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001321 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Eric Paris828dfe12008-04-17 13:17:49 -04001323 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (!buffer)
1325 return -ENOMEM;
1326
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001327 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1328 if (IS_ERR(path))
1329 rc = PTR_ERR(path);
1330 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001331 if (flags & SE_SBPROC) {
1332 /* each process gets a /proc/PID/ entry. Strip off the
1333 * PID part to get a valid selinux labeling.
1334 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1335 while (path[1] >= '0' && path[1] <= '9') {
1336 path[1] = '/';
1337 path++;
1338 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001339 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001340 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 free_page((unsigned long)buffer);
1343 return rc;
1344}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
1346/* The inode's security attributes must be initialized before first use. */
1347static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1348{
1349 struct superblock_security_struct *sbsec = NULL;
1350 struct inode_security_struct *isec = inode->i_security;
1351 u32 sid;
1352 struct dentry *dentry;
1353#define INITCONTEXTLEN 255
1354 char *context = NULL;
1355 unsigned len = 0;
1356 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001358 if (isec->initialized == LABEL_INITIALIZED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 goto out;
1360
Eric Paris23970742006-09-25 23:32:01 -07001361 mutex_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001362 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001363 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001366 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 /* Defer initialization until selinux_complete_init,
1368 after the initial policy is loaded and the security
1369 server is ready to handle calls. */
1370 spin_lock(&sbsec->isec_lock);
1371 if (list_empty(&isec->list))
1372 list_add(&isec->list, &sbsec->isec_head);
1373 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001374 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
1376
1377 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001378 case SECURITY_FS_USE_NATIVE:
1379 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 case SECURITY_FS_USE_XATTR:
1381 if (!inode->i_op->getxattr) {
1382 isec->sid = sbsec->def_sid;
1383 break;
1384 }
1385
1386 /* Need a dentry, since the xattr API requires one.
1387 Life would be simpler if we could just pass the inode. */
1388 if (opt_dentry) {
1389 /* Called from d_instantiate or d_splice_alias. */
1390 dentry = dget(opt_dentry);
1391 } else {
1392 /* Called from selinux_complete_init, try to find a dentry. */
1393 dentry = d_find_alias(inode);
1394 }
1395 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001396 /*
1397 * this is can be hit on boot when a file is accessed
1398 * before the policy is loaded. When we load policy we
1399 * may find inodes that have no dentry on the
1400 * sbsec->isec_head list. No reason to complain as these
1401 * will get fixed up the next time we go through
1402 * inode_doinit with a dentry, before these inodes could
1403 * be used again by userspace.
1404 */
Eric Paris23970742006-09-25 23:32:01 -07001405 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 }
1407
1408 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001409 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (!context) {
1411 rc = -ENOMEM;
1412 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001413 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001415 context[len] = '\0';
Al Viroce23e642016-04-11 00:48:00 -04001416 rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 context, len);
1418 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001419 kfree(context);
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 /* Need a larger buffer. Query for the right size. */
Al Viroce23e642016-04-11 00:48:00 -04001422 rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 NULL, 0);
1424 if (rc < 0) {
1425 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001426 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001429 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 if (!context) {
1431 rc = -ENOMEM;
1432 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001433 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001435 context[len] = '\0';
Al Viroce23e642016-04-11 00:48:00 -04001436 rc = inode->i_op->getxattr(dentry, inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 XATTR_NAME_SELINUX,
1438 context, len);
1439 }
1440 dput(dentry);
1441 if (rc < 0) {
1442 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001443 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001444 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 -rc, inode->i_sb->s_id, inode->i_ino);
1446 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001447 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 }
1449 /* Map ENODATA to the default file SID */
1450 sid = sbsec->def_sid;
1451 rc = 0;
1452 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001453 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001454 sbsec->def_sid,
1455 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001457 char *dev = inode->i_sb->s_id;
1458 unsigned long ino = inode->i_ino;
1459
1460 if (rc == -EINVAL) {
1461 if (printk_ratelimit())
1462 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1463 "context=%s. This indicates you may need to relabel the inode or the "
1464 "filesystem in question.\n", ino, dev, context);
1465 } else {
1466 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1467 "returned %d for dev=%s ino=%ld\n",
1468 __func__, context, -rc, dev, ino);
1469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 kfree(context);
1471 /* Leave with the unlabeled SID */
1472 rc = 0;
1473 break;
1474 }
1475 }
1476 kfree(context);
1477 isec->sid = sid;
1478 break;
1479 case SECURITY_FS_USE_TASK:
1480 isec->sid = isec->task_sid;
1481 break;
1482 case SECURITY_FS_USE_TRANS:
1483 /* Default to the fs SID. */
1484 isec->sid = sbsec->sid;
1485
1486 /* Try to obtain a transition SID. */
1487 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001488 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1489 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001491 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 isec->sid = sid;
1493 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001494 case SECURITY_FS_USE_MNTPOINT:
1495 isec->sid = sbsec->mntpoint_sid;
1496 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001498 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 isec->sid = sbsec->sid;
1500
Stephen Smalley134509d2015-06-04 16:22:17 -04001501 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001502 /* We must have a dentry to determine the label on
1503 * procfs inodes */
1504 if (opt_dentry)
1505 /* Called from d_instantiate or
1506 * d_splice_alias. */
1507 dentry = dget(opt_dentry);
1508 else
1509 /* Called from selinux_complete_init, try to
1510 * find a dentry. */
1511 dentry = d_find_alias(inode);
1512 /*
1513 * This can be hit on boot when a file is accessed
1514 * before the policy is loaded. When we load policy we
1515 * may find inodes that have no dentry on the
1516 * sbsec->isec_head list. No reason to complain as
1517 * these will get fixed up the next time we go through
1518 * inode_doinit() with a dentry, before these inodes
1519 * could be used again by userspace.
1520 */
1521 if (!dentry)
1522 goto out_unlock;
1523 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001524 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1525 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001526 dput(dentry);
1527 if (rc)
1528 goto out_unlock;
1529 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 }
1531 break;
1532 }
1533
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001534 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Eric Paris23970742006-09-25 23:32:01 -07001536out_unlock:
1537 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538out:
1539 if (isec->sclass == SECCLASS_FILE)
1540 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 return rc;
1542}
1543
1544/* Convert a Linux signal to an access vector. */
1545static inline u32 signal_to_av(int sig)
1546{
1547 u32 perm = 0;
1548
1549 switch (sig) {
1550 case SIGCHLD:
1551 /* Commonly granted from child to parent. */
1552 perm = PROCESS__SIGCHLD;
1553 break;
1554 case SIGKILL:
1555 /* Cannot be caught or ignored */
1556 perm = PROCESS__SIGKILL;
1557 break;
1558 case SIGSTOP:
1559 /* Cannot be caught or ignored */
1560 perm = PROCESS__SIGSTOP;
1561 break;
1562 default:
1563 /* All other signals. */
1564 perm = PROCESS__SIGNAL;
1565 break;
1566 }
1567
1568 return perm;
1569}
1570
David Howells275bb412008-11-14 10:39:19 +11001571/*
David Howellsd84f4f92008-11-14 10:39:23 +11001572 * Check permission between a pair of credentials
1573 * fork check, ptrace check, etc.
1574 */
1575static int cred_has_perm(const struct cred *actor,
1576 const struct cred *target,
1577 u32 perms)
1578{
1579 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1580
1581 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1582}
1583
1584/*
David Howells88e67f32008-11-14 10:39:21 +11001585 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001586 * fork check, ptrace check, etc.
1587 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001588 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001589 */
1590static int task_has_perm(const struct task_struct *tsk1,
1591 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 u32 perms)
1593{
David Howells275bb412008-11-14 10:39:19 +11001594 const struct task_security_struct *__tsec1, *__tsec2;
1595 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
David Howells275bb412008-11-14 10:39:19 +11001597 rcu_read_lock();
1598 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1599 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1600 rcu_read_unlock();
1601 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602}
1603
David Howells3b11a1d2008-11-14 10:39:26 +11001604/*
1605 * Check permission between current and another task, e.g. signal checks,
1606 * fork check, ptrace check, etc.
1607 * current is the actor and tsk2 is the target
1608 * - this uses current's subjective creds
1609 */
1610static int current_has_perm(const struct task_struct *tsk,
1611 u32 perms)
1612{
1613 u32 sid, tsid;
1614
1615 sid = current_sid();
1616 tsid = task_sid(tsk);
1617 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1618}
1619
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001620#if CAP_LAST_CAP > 63
1621#error Fix SELinux to handle capabilities > 63.
1622#endif
1623
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001625static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001626 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627{
Thomas Liu2bf49692009-07-14 12:14:09 -04001628 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001629 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001630 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001631 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001632 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001633 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
Eric Paris50c205f2012-04-04 15:01:43 -04001635 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 ad.u.cap = cap;
1637
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001638 switch (CAP_TO_INDEX(cap)) {
1639 case 0:
1640 sclass = SECCLASS_CAPABILITY;
1641 break;
1642 case 1:
1643 sclass = SECCLASS_CAPABILITY2;
1644 break;
1645 default:
1646 printk(KERN_ERR
1647 "SELinux: out of range capability %d\n", cap);
1648 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001649 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001650 }
Eric Paris06112162008-11-11 22:02:50 +11001651
David Howells275bb412008-11-14 10:39:19 +11001652 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001653 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001654 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001655 if (rc2)
1656 return rc2;
1657 }
Eric Paris06112162008-11-11 22:02:50 +11001658 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659}
1660
1661/* Check whether a task is allowed to use a system operation. */
1662static int task_has_system(struct task_struct *tsk,
1663 u32 perms)
1664{
David Howells275bb412008-11-14 10:39:19 +11001665 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
David Howells275bb412008-11-14 10:39:19 +11001667 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 SECCLASS_SYSTEM, perms, NULL);
1669}
1670
1671/* Check whether a task has a particular permission to an inode.
1672 The 'adp' parameter is optional and allows other audit
1673 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001674static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 struct inode *inode,
1676 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001677 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001680 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
David Howellse0e81732009-09-02 09:13:40 +01001682 validate_creds(cred);
1683
Eric Paris828dfe12008-04-17 13:17:49 -04001684 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001685 return 0;
1686
David Howells88e67f32008-11-14 10:39:21 +11001687 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 isec = inode->i_security;
1689
Linus Torvalds19e49832013-10-04 12:54:11 -07001690 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691}
1692
1693/* Same as inode_has_perm, but pass explicit audit data containing
1694 the dentry to help the auditing code to more easily generate the
1695 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001696static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 struct dentry *dentry,
1698 u32 av)
1699{
David Howellsc6f493d2015-03-17 22:26:22 +00001700 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001701 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001702
Eric Paris50c205f2012-04-04 15:01:43 -04001703 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001704 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001705 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001706 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001707}
1708
1709/* Same as inode_has_perm, but pass explicit audit data containing
1710 the path to help the auditing code to more easily generate the
1711 pathname if needed. */
1712static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001713 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001714 u32 av)
1715{
David Howellsc6f493d2015-03-17 22:26:22 +00001716 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001717 struct common_audit_data ad;
1718
Eric Paris50c205f2012-04-04 15:01:43 -04001719 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001720 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001721 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001722 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
1724
David Howells13f8e982013-06-13 23:37:55 +01001725/* Same as path_has_perm, but uses the inode from the file struct. */
1726static inline int file_path_has_perm(const struct cred *cred,
1727 struct file *file,
1728 u32 av)
1729{
1730 struct common_audit_data ad;
1731
1732 ad.type = LSM_AUDIT_DATA_PATH;
1733 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001734 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001735}
1736
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737/* Check whether a task can use an open file descriptor to
1738 access an inode in a given way. Check access to the
1739 descriptor itself, and then use dentry_has_perm to
1740 check a particular permission to the file.
1741 Access to the descriptor is implicitly granted if it
1742 has the same SID as the process. If av is zero, then
1743 access to the file is not checked, e.g. for cases
1744 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001745static int file_has_perm(const struct cred *cred,
1746 struct file *file,
1747 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001750 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001751 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001752 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 int rc;
1754
Eric Paris50c205f2012-04-04 15:01:43 -04001755 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001756 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
David Howells275bb412008-11-14 10:39:19 +11001758 if (sid != fsec->sid) {
1759 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 SECCLASS_FD,
1761 FD__USE,
1762 &ad);
1763 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001764 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 }
1766
1767 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001768 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001770 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
David Howells88e67f32008-11-14 10:39:21 +11001772out:
1773 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774}
1775
David Howellsc3c188b2015-07-10 17:19:58 -04001776/*
1777 * Determine the label for an inode that might be unioned.
1778 */
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001779static int selinux_determine_inode_label(struct inode *dir,
David Howellsc3c188b2015-07-10 17:19:58 -04001780 const struct qstr *name,
1781 u16 tclass,
1782 u32 *_new_isid)
1783{
1784 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001785 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001786 const struct task_security_struct *tsec = current_security();
1787
1788 if ((sbsec->flags & SE_SBINITIALIZED) &&
1789 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1790 *_new_isid = sbsec->mntpoint_sid;
1791 } else if ((sbsec->flags & SBLABEL_MNT) &&
1792 tsec->create_sid) {
1793 *_new_isid = tsec->create_sid;
1794 } else {
1795 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1796 name, _new_isid);
1797 }
1798
1799 return 0;
1800}
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802/* Check whether a task can create a file. */
1803static int may_create(struct inode *dir,
1804 struct dentry *dentry,
1805 u16 tclass)
1806{
Paul Moore5fb49872010-04-22 14:46:19 -04001807 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 struct inode_security_struct *dsec;
1809 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001810 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001811 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 int rc;
1813
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001814 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 sbsec = dir->i_sb->s_security;
1816
David Howells275bb412008-11-14 10:39:19 +11001817 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001818
Eric Paris50c205f2012-04-04 15:01:43 -04001819 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001820 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
David Howells275bb412008-11-14 10:39:19 +11001822 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 DIR__ADD_NAME | DIR__SEARCH,
1824 &ad);
1825 if (rc)
1826 return rc;
1827
David Howellsc3c188b2015-07-10 17:19:58 -04001828 rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
1829 &newsid);
1830 if (rc)
1831 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
David Howells275bb412008-11-14 10:39:19 +11001833 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 if (rc)
1835 return rc;
1836
1837 return avc_has_perm(newsid, sbsec->sid,
1838 SECCLASS_FILESYSTEM,
1839 FILESYSTEM__ASSOCIATE, &ad);
1840}
1841
Michael LeMay4eb582c2006-06-26 00:24:57 -07001842/* Check whether a task can create a key. */
1843static int may_create_key(u32 ksid,
1844 struct task_struct *ctx)
1845{
David Howells275bb412008-11-14 10:39:19 +11001846 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001847
David Howells275bb412008-11-14 10:39:19 +11001848 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001849}
1850
Eric Paris828dfe12008-04-17 13:17:49 -04001851#define MAY_LINK 0
1852#define MAY_UNLINK 1
1853#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
1855/* Check whether a task can link, unlink, or rmdir a file/directory. */
1856static int may_link(struct inode *dir,
1857 struct dentry *dentry,
1858 int kind)
1859
1860{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001862 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001863 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 u32 av;
1865 int rc;
1866
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001867 dsec = inode_security(dir);
1868 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Eric Paris50c205f2012-04-04 15:01:43 -04001870 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001871 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 av = DIR__SEARCH;
1874 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001875 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 if (rc)
1877 return rc;
1878
1879 switch (kind) {
1880 case MAY_LINK:
1881 av = FILE__LINK;
1882 break;
1883 case MAY_UNLINK:
1884 av = FILE__UNLINK;
1885 break;
1886 case MAY_RMDIR:
1887 av = DIR__RMDIR;
1888 break;
1889 default:
Eric Paris744ba352008-04-17 11:52:44 -04001890 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1891 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return 0;
1893 }
1894
David Howells275bb412008-11-14 10:39:19 +11001895 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return rc;
1897}
1898
1899static inline int may_rename(struct inode *old_dir,
1900 struct dentry *old_dentry,
1901 struct inode *new_dir,
1902 struct dentry *new_dentry)
1903{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001905 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001906 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 u32 av;
1908 int old_is_dir, new_is_dir;
1909 int rc;
1910
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001911 old_dsec = inode_security(old_dir);
1912 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001913 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001914 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
Eric Paris50c205f2012-04-04 15:01:43 -04001916 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Eric Parisa2694342011-04-25 13:10:27 -04001918 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001919 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1921 if (rc)
1922 return rc;
David Howells275bb412008-11-14 10:39:19 +11001923 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 old_isec->sclass, FILE__RENAME, &ad);
1925 if (rc)
1926 return rc;
1927 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001928 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 old_isec->sclass, DIR__REPARENT, &ad);
1930 if (rc)
1931 return rc;
1932 }
1933
Eric Parisa2694342011-04-25 13:10:27 -04001934 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001936 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001938 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 if (rc)
1940 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001941 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001942 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001943 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001944 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 new_isec->sclass,
1946 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1947 if (rc)
1948 return rc;
1949 }
1950
1951 return 0;
1952}
1953
1954/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001955static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 struct super_block *sb,
1957 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001958 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001961 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001964 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965}
1966
1967/* Convert a Linux mode and permission mask to an access vector. */
1968static inline u32 file_mask_to_av(int mode, int mask)
1969{
1970 u32 av = 0;
1971
Al Virodba19c62011-07-25 20:49:29 -04001972 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 if (mask & MAY_EXEC)
1974 av |= FILE__EXECUTE;
1975 if (mask & MAY_READ)
1976 av |= FILE__READ;
1977
1978 if (mask & MAY_APPEND)
1979 av |= FILE__APPEND;
1980 else if (mask & MAY_WRITE)
1981 av |= FILE__WRITE;
1982
1983 } else {
1984 if (mask & MAY_EXEC)
1985 av |= DIR__SEARCH;
1986 if (mask & MAY_WRITE)
1987 av |= DIR__WRITE;
1988 if (mask & MAY_READ)
1989 av |= DIR__READ;
1990 }
1991
1992 return av;
1993}
1994
1995/* Convert a Linux file to an access vector. */
1996static inline u32 file_to_av(struct file *file)
1997{
1998 u32 av = 0;
1999
2000 if (file->f_mode & FMODE_READ)
2001 av |= FILE__READ;
2002 if (file->f_mode & FMODE_WRITE) {
2003 if (file->f_flags & O_APPEND)
2004 av |= FILE__APPEND;
2005 else
2006 av |= FILE__WRITE;
2007 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002008 if (!av) {
2009 /*
2010 * Special file opened with flags 3 for ioctl-only use.
2011 */
2012 av = FILE__IOCTL;
2013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
2015 return av;
2016}
2017
Eric Paris8b6a5a32008-10-29 17:06:46 -04002018/*
2019 * Convert a file to an access vector and include the correct open
2020 * open permission.
2021 */
2022static inline u32 open_file_to_av(struct file *file)
2023{
2024 u32 av = file_to_av(file);
2025
Eric Paris49b7b8d2010-07-23 11:44:09 -04002026 if (selinux_policycap_openperm)
2027 av |= FILE__OPEN;
2028
Eric Paris8b6a5a32008-10-29 17:06:46 -04002029 return av;
2030}
2031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032/* Hook functions begin here. */
2033
Stephen Smalley79af7302015-01-21 10:54:10 -05002034static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2035{
2036 u32 mysid = current_sid();
2037 u32 mgrsid = task_sid(mgr);
2038
2039 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
2040 BINDER__SET_CONTEXT_MGR, NULL);
2041}
2042
2043static int selinux_binder_transaction(struct task_struct *from,
2044 struct task_struct *to)
2045{
2046 u32 mysid = current_sid();
2047 u32 fromsid = task_sid(from);
2048 u32 tosid = task_sid(to);
2049 int rc;
2050
2051 if (mysid != fromsid) {
2052 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2053 BINDER__IMPERSONATE, NULL);
2054 if (rc)
2055 return rc;
2056 }
2057
2058 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2059 NULL);
2060}
2061
2062static int selinux_binder_transfer_binder(struct task_struct *from,
2063 struct task_struct *to)
2064{
2065 u32 fromsid = task_sid(from);
2066 u32 tosid = task_sid(to);
2067
2068 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2069 NULL);
2070}
2071
2072static int selinux_binder_transfer_file(struct task_struct *from,
2073 struct task_struct *to,
2074 struct file *file)
2075{
2076 u32 sid = task_sid(to);
2077 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002078 struct dentry *dentry = file->f_path.dentry;
2079 struct inode_security_struct *isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002080 struct common_audit_data ad;
2081 int rc;
2082
2083 ad.type = LSM_AUDIT_DATA_PATH;
2084 ad.u.path = file->f_path;
2085
2086 if (sid != fsec->sid) {
2087 rc = avc_has_perm(sid, fsec->sid,
2088 SECCLASS_FD,
2089 FD__USE,
2090 &ad);
2091 if (rc)
2092 return rc;
2093 }
2094
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002095 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002096 return 0;
2097
2098 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2099 &ad);
2100}
2101
Ingo Molnar9e488582009-05-07 19:26:19 +10002102static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002103 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104{
Eric Paris69f594a2012-01-03 12:25:15 -05002105 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002106 u32 sid = current_sid();
2107 u32 csid = task_sid(child);
2108 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002109 }
2110
David Howells3b11a1d2008-11-14 10:39:26 +11002111 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002112}
2113
2114static int selinux_ptrace_traceme(struct task_struct *parent)
2115{
David Howells5cd9c582008-08-14 11:37:28 +01002116 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117}
2118
2119static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002120 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002122 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123}
2124
David Howellsd84f4f92008-11-14 10:39:23 +11002125static int selinux_capset(struct cred *new, const struct cred *old,
2126 const kernel_cap_t *effective,
2127 const kernel_cap_t *inheritable,
2128 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129{
David Howellsd84f4f92008-11-14 10:39:23 +11002130 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131}
2132
James Morris5626d3e2009-01-30 10:05:06 +11002133/*
2134 * (This comment used to live with the selinux_task_setuid hook,
2135 * which was removed).
2136 *
2137 * Since setuid only affects the current process, and since the SELinux
2138 * controls are not based on the Linux identity attributes, SELinux does not
2139 * need to control this operation. However, SELinux does control the use of
2140 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2141 */
2142
Eric Paris6a9de492012-01-03 12:25:14 -05002143static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2144 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145{
Eric Paris6a9de492012-01-03 12:25:14 -05002146 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147}
2148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2150{
David Howells88e67f32008-11-14 10:39:21 +11002151 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 int rc = 0;
2153
2154 if (!sb)
2155 return 0;
2156
2157 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002158 case Q_SYNC:
2159 case Q_QUOTAON:
2160 case Q_QUOTAOFF:
2161 case Q_SETINFO:
2162 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002163 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002164 break;
2165 case Q_GETFMT:
2166 case Q_GETINFO:
2167 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002168 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002169 break;
2170 default:
2171 rc = 0; /* let the kernel handle invalid cmds */
2172 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 }
2174 return rc;
2175}
2176
2177static int selinux_quota_on(struct dentry *dentry)
2178{
David Howells88e67f32008-11-14 10:39:21 +11002179 const struct cred *cred = current_cred();
2180
Eric Paris2875fa02011-04-28 16:04:24 -04002181 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182}
2183
Eric Paris12b30522010-11-15 18:36:29 -05002184static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
2186 int rc;
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002189 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2190 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002191 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2192 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002193 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2194 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2195 /* Set level of messages printed to console */
2196 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002197 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2198 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002199 case SYSLOG_ACTION_CLOSE: /* Close log */
2200 case SYSLOG_ACTION_OPEN: /* Open log */
2201 case SYSLOG_ACTION_READ: /* Read from log */
2202 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2203 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002204 default:
2205 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2206 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 }
2208 return rc;
2209}
2210
2211/*
2212 * Check that a process has enough memory to allocate a new virtual
2213 * mapping. 0 means there is enough memory for the allocation to
2214 * succeed and -ENOMEM implies there is not.
2215 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 * Do not audit the selinux permission check, as this is applied to all
2217 * processes that allocate mappings.
2218 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002219static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220{
2221 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002223 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2224 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 if (rc == 0)
2226 cap_sys_admin = 1;
2227
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002228 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229}
2230
2231/* binprm security operations */
2232
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002233static int check_nnp_nosuid(const struct linux_binprm *bprm,
2234 const struct task_security_struct *old_tsec,
2235 const struct task_security_struct *new_tsec)
2236{
2237 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2238 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2239 int rc;
2240
2241 if (!nnp && !nosuid)
2242 return 0; /* neither NNP nor nosuid */
2243
2244 if (new_tsec->sid == old_tsec->sid)
2245 return 0; /* No change in credentials */
2246
2247 /*
2248 * The only transitions we permit under NNP or nosuid
2249 * are transitions to bounded SIDs, i.e. SIDs that are
2250 * guaranteed to only be allowed a subset of the permissions
2251 * of the current SID.
2252 */
2253 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2254 if (rc) {
2255 /*
2256 * On failure, preserve the errno values for NNP vs nosuid.
2257 * NNP: Operation not permitted for caller.
2258 * nosuid: Permission denied to file.
2259 */
2260 if (nnp)
2261 return -EPERM;
2262 else
2263 return -EACCES;
2264 }
2265 return 0;
2266}
2267
David Howellsa6f76f22008-11-14 10:39:24 +11002268static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269{
David Howellsa6f76f22008-11-14 10:39:24 +11002270 const struct task_security_struct *old_tsec;
2271 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002273 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002274 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 int rc;
2276
David Howellsa6f76f22008-11-14 10:39:24 +11002277 /* SELinux context only depends on initial program or script and not
2278 * the script interpreter */
2279 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return 0;
2281
David Howellsa6f76f22008-11-14 10:39:24 +11002282 old_tsec = current_security();
2283 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002284 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
2286 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002287 new_tsec->sid = old_tsec->sid;
2288 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Michael LeMay28eba5b2006-06-27 02:53:42 -07002290 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002291 new_tsec->create_sid = 0;
2292 new_tsec->keycreate_sid = 0;
2293 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
David Howellsa6f76f22008-11-14 10:39:24 +11002295 if (old_tsec->exec_sid) {
2296 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002298 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002299
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002300 /* Fail on NNP or nosuid if not an allowed transition. */
2301 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2302 if (rc)
2303 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 } else {
2305 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002306 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002307 SECCLASS_PROCESS, NULL,
2308 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 if (rc)
2310 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002311
2312 /*
2313 * Fallback to old SID on NNP or nosuid if not an allowed
2314 * transition.
2315 */
2316 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2317 if (rc)
2318 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 }
2320
Eric Paris50c205f2012-04-04 15:01:43 -04002321 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002322 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
David Howellsa6f76f22008-11-14 10:39:24 +11002324 if (new_tsec->sid == old_tsec->sid) {
2325 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2327 if (rc)
2328 return rc;
2329 } else {
2330 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002331 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2333 if (rc)
2334 return rc;
2335
David Howellsa6f76f22008-11-14 10:39:24 +11002336 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2338 if (rc)
2339 return rc;
2340
David Howellsa6f76f22008-11-14 10:39:24 +11002341 /* Check for shared state */
2342 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2343 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2344 SECCLASS_PROCESS, PROCESS__SHARE,
2345 NULL);
2346 if (rc)
2347 return -EPERM;
2348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
David Howellsa6f76f22008-11-14 10:39:24 +11002350 /* Make sure that anyone attempting to ptrace over a task that
2351 * changes its SID has the appropriate permit */
2352 if (bprm->unsafe &
2353 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2354 struct task_struct *tracer;
2355 struct task_security_struct *sec;
2356 u32 ptsid = 0;
2357
2358 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002359 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002360 if (likely(tracer != NULL)) {
2361 sec = __task_cred(tracer)->security;
2362 ptsid = sec->sid;
2363 }
2364 rcu_read_unlock();
2365
2366 if (ptsid != 0) {
2367 rc = avc_has_perm(ptsid, new_tsec->sid,
2368 SECCLASS_PROCESS,
2369 PROCESS__PTRACE, NULL);
2370 if (rc)
2371 return -EPERM;
2372 }
2373 }
2374
2375 /* Clear any possibly unsafe personality bits on exec: */
2376 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 }
2378
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 return 0;
2380}
2381
Eric Paris828dfe12008-04-17 13:17:49 -04002382static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383{
Paul Moore5fb49872010-04-22 14:46:19 -04002384 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002385 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 int atsecure = 0;
2387
David Howells275bb412008-11-14 10:39:19 +11002388 sid = tsec->sid;
2389 osid = tsec->osid;
2390
2391 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 /* Enable secure mode for SIDs transitions unless
2393 the noatsecure permission is granted between
2394 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002395 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002396 SECCLASS_PROCESS,
2397 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
2399
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002400 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401}
2402
Al Viroc3c073f2012-08-21 22:32:06 -04002403static int match_file(const void *p, struct file *file, unsigned fd)
2404{
2405 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2406}
2407
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002409static inline void flush_unauthorized_files(const struct cred *cred,
2410 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002413 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002414 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002415 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002417 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002419 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002420 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002421 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002422
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002424 Use file_path_has_perm on the tty path directly
2425 rather than using file_has_perm, as this particular
2426 open file may belong to another process and we are
2427 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002428 file_priv = list_first_entry(&tty->tty_files,
2429 struct tty_file_private, list);
2430 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002431 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002432 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 }
Peter Hurley4a510962016-01-09 21:35:23 -08002434 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002435 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002437 /* Reset controlling tty. */
2438 if (drop_tty)
2439 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002442 n = iterate_fd(files, 0, match_file, cred);
2443 if (!n) /* none found? */
2444 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445
Al Viroc3c073f2012-08-21 22:32:06 -04002446 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002447 if (IS_ERR(devnull))
2448 devnull = NULL;
2449 /* replace all the matching ones with this */
2450 do {
2451 replace_fd(n - 1, devnull, 0);
2452 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2453 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002454 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455}
2456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457/*
David Howellsa6f76f22008-11-14 10:39:24 +11002458 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 */
David Howellsa6f76f22008-11-14 10:39:24 +11002460static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461{
David Howellsa6f76f22008-11-14 10:39:24 +11002462 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 int rc, i;
2465
David Howellsa6f76f22008-11-14 10:39:24 +11002466 new_tsec = bprm->cred->security;
2467 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 return;
2469
2470 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002471 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
David Howellsa6f76f22008-11-14 10:39:24 +11002473 /* Always clear parent death signal on SID transitions. */
2474 current->pdeath_signal = 0;
2475
2476 /* Check whether the new SID can inherit resource limits from the old
2477 * SID. If not, reset all soft limits to the lower of the current
2478 * task's hard limit and the init task's soft limit.
2479 *
2480 * Note that the setting of hard limits (even to lower them) can be
2481 * controlled by the setrlimit check. The inclusion of the init task's
2482 * soft limit into the computation is to avoid resetting soft limits
2483 * higher than the default soft limit for cases where the default is
2484 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2485 */
2486 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2487 PROCESS__RLIMITINH, NULL);
2488 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002489 /* protect against do_prlimit() */
2490 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002491 for (i = 0; i < RLIM_NLIMITS; i++) {
2492 rlim = current->signal->rlim + i;
2493 initrlim = init_task.signal->rlim + i;
2494 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2495 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002496 task_unlock(current);
2497 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002498 }
2499}
2500
2501/*
2502 * Clean up the process immediately after the installation of new credentials
2503 * due to exec
2504 */
2505static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2506{
2507 const struct task_security_struct *tsec = current_security();
2508 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002509 u32 osid, sid;
2510 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002511
David Howellsa6f76f22008-11-14 10:39:24 +11002512 osid = tsec->osid;
2513 sid = tsec->sid;
2514
2515 if (sid == osid)
2516 return;
2517
2518 /* Check whether the new SID can inherit signal state from the old SID.
2519 * If not, clear itimers to avoid subsequent signal generation and
2520 * flush and unblock signals.
2521 *
2522 * This must occur _after_ the task SID has been updated so that any
2523 * kill done after the flush will be checked against the new SID.
2524 */
2525 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 if (rc) {
2527 memset(&itimer, 0, sizeof itimer);
2528 for (i = 0; i < 3; i++)
2529 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002531 if (!fatal_signal_pending(current)) {
2532 flush_sigqueue(&current->pending);
2533 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002534 flush_signal_handlers(current, 1);
2535 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002536 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 spin_unlock_irq(&current->sighand->siglock);
2539 }
2540
David Howellsa6f76f22008-11-14 10:39:24 +11002541 /* Wake up the parent if it is waiting so that it can recheck
2542 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002543 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002544 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002545 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546}
2547
2548/* superblock security operations */
2549
2550static int selinux_sb_alloc_security(struct super_block *sb)
2551{
2552 return superblock_alloc_security(sb);
2553}
2554
2555static void selinux_sb_free_security(struct super_block *sb)
2556{
2557 superblock_free_security(sb);
2558}
2559
2560static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2561{
2562 if (plen > olen)
2563 return 0;
2564
2565 return !memcmp(prefix, option, plen);
2566}
2567
2568static inline int selinux_option(char *option, int len)
2569{
Eric Paris832cbd92008-04-01 13:24:09 -04002570 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2571 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2572 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002573 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2574 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575}
2576
2577static inline void take_option(char **to, char *from, int *first, int len)
2578{
2579 if (!*first) {
2580 **to = ',';
2581 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002582 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 *first = 0;
2584 memcpy(*to, from, len);
2585 *to += len;
2586}
2587
Eric Paris828dfe12008-04-17 13:17:49 -04002588static inline void take_selinux_option(char **to, char *from, int *first,
2589 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002590{
2591 int current_size = 0;
2592
2593 if (!*first) {
2594 **to = '|';
2595 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002596 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002597 *first = 0;
2598
2599 while (current_size < len) {
2600 if (*from != '"') {
2601 **to = *from;
2602 *to += 1;
2603 }
2604 from += 1;
2605 current_size += 1;
2606 }
2607}
2608
Eric Parise0007522008-03-05 10:31:54 -05002609static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610{
2611 int fnosec, fsec, rc = 0;
2612 char *in_save, *in_curr, *in_end;
2613 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002614 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
2616 in_curr = orig;
2617 sec_curr = copy;
2618
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2620 if (!nosec) {
2621 rc = -ENOMEM;
2622 goto out;
2623 }
2624
2625 nosec_save = nosec;
2626 fnosec = fsec = 1;
2627 in_save = in_end = orig;
2628
2629 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002630 if (*in_end == '"')
2631 open_quote = !open_quote;
2632 if ((*in_end == ',' && open_quote == 0) ||
2633 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 int len = in_end - in_curr;
2635
2636 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002637 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 else
2639 take_option(&nosec, in_curr, &fnosec, len);
2640
2641 in_curr = in_end + 1;
2642 }
2643 } while (*in_end++);
2644
Eric Paris6931dfc2005-06-30 02:58:51 -07002645 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002646 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647out:
2648 return rc;
2649}
2650
Eric Paris026eb162011-03-03 16:09:14 -05002651static int selinux_sb_remount(struct super_block *sb, void *data)
2652{
2653 int rc, i, *flags;
2654 struct security_mnt_opts opts;
2655 char *secdata, **mount_options;
2656 struct superblock_security_struct *sbsec = sb->s_security;
2657
2658 if (!(sbsec->flags & SE_SBINITIALIZED))
2659 return 0;
2660
2661 if (!data)
2662 return 0;
2663
2664 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2665 return 0;
2666
2667 security_init_mnt_opts(&opts);
2668 secdata = alloc_secdata();
2669 if (!secdata)
2670 return -ENOMEM;
2671 rc = selinux_sb_copy_data(data, secdata);
2672 if (rc)
2673 goto out_free_secdata;
2674
2675 rc = selinux_parse_opts_str(secdata, &opts);
2676 if (rc)
2677 goto out_free_secdata;
2678
2679 mount_options = opts.mnt_opts;
2680 flags = opts.mnt_opts_flags;
2681
2682 for (i = 0; i < opts.num_mnt_opts; i++) {
2683 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002684
Eric Paris12f348b2012-10-09 10:56:25 -04002685 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002686 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002687 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002688 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002689 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002690 "(%s) failed for (dev %s, type %s) errno=%d\n",
2691 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002692 goto out_free_opts;
2693 }
2694 rc = -EINVAL;
2695 switch (flags[i]) {
2696 case FSCONTEXT_MNT:
2697 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2698 goto out_bad_option;
2699 break;
2700 case CONTEXT_MNT:
2701 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2702 goto out_bad_option;
2703 break;
2704 case ROOTCONTEXT_MNT: {
2705 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002706 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002707
2708 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2709 goto out_bad_option;
2710 break;
2711 }
2712 case DEFCONTEXT_MNT:
2713 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2714 goto out_bad_option;
2715 break;
2716 default:
2717 goto out_free_opts;
2718 }
2719 }
2720
2721 rc = 0;
2722out_free_opts:
2723 security_free_mnt_opts(&opts);
2724out_free_secdata:
2725 free_secdata(secdata);
2726 return rc;
2727out_bad_option:
2728 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002729 "during remount (dev %s, type=%s)\n", sb->s_id,
2730 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002731 goto out_free_opts;
2732}
2733
James Morris12204e22008-12-19 10:44:42 +11002734static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735{
David Howells88e67f32008-11-14 10:39:21 +11002736 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002737 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 int rc;
2739
2740 rc = superblock_doinit(sb, data);
2741 if (rc)
2742 return rc;
2743
James Morris74192242008-12-19 11:41:10 +11002744 /* Allow all mounts performed by the kernel */
2745 if (flags & MS_KERNMOUNT)
2746 return 0;
2747
Eric Paris50c205f2012-04-04 15:01:43 -04002748 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002749 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002750 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751}
2752
David Howells726c3342006-06-23 02:02:58 -07002753static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754{
David Howells88e67f32008-11-14 10:39:21 +11002755 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002756 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Eric Paris50c205f2012-04-04 15:01:43 -04002758 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002759 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002760 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761}
2762
Al Viro808d4e32012-10-11 11:42:01 -04002763static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002764 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002765 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002766 unsigned long flags,
2767 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768{
David Howells88e67f32008-11-14 10:39:21 +11002769 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770
2771 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002772 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002773 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 else
Eric Paris2875fa02011-04-28 16:04:24 -04002775 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776}
2777
2778static int selinux_umount(struct vfsmount *mnt, int flags)
2779{
David Howells88e67f32008-11-14 10:39:21 +11002780 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781
David Howells88e67f32008-11-14 10:39:21 +11002782 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002783 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784}
2785
2786/* inode security operations */
2787
2788static int selinux_inode_alloc_security(struct inode *inode)
2789{
2790 return inode_alloc_security(inode);
2791}
2792
2793static void selinux_inode_free_security(struct inode *inode)
2794{
2795 inode_free_security(inode);
2796}
2797
David Quigleyd47be3d2013-05-22 12:50:34 -04002798static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2799 struct qstr *name, void **ctx,
2800 u32 *ctxlen)
2801{
David Quigleyd47be3d2013-05-22 12:50:34 -04002802 u32 newsid;
2803 int rc;
2804
David Howellsc3c188b2015-07-10 17:19:58 -04002805 rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
2806 inode_mode_to_security_class(mode),
2807 &newsid);
2808 if (rc)
2809 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002810
2811 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2812}
2813
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002814static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002815 const struct qstr *qstr,
2816 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002817 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002818{
Paul Moore5fb49872010-04-22 14:46:19 -04002819 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002820 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002821 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002822 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002823 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002824
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002825 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002826
David Howells275bb412008-11-14 10:39:19 +11002827 sid = tsec->sid;
2828 newsid = tsec->create_sid;
2829
David Howellsc3c188b2015-07-10 17:19:58 -04002830 rc = selinux_determine_inode_label(
2831 dir, qstr,
2832 inode_mode_to_security_class(inode->i_mode),
2833 &newsid);
2834 if (rc)
2835 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002836
Eric Paris296fddf2006-09-25 23:32:00 -07002837 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002838 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002839 struct inode_security_struct *isec = inode->i_security;
2840 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2841 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002842 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002843 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002844
Eric Paris12f348b2012-10-09 10:56:25 -04002845 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002846 return -EOPNOTSUPP;
2847
Tetsuo Handa95489062013-07-25 05:44:02 +09002848 if (name)
2849 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002850
2851 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002852 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002853 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002854 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002855 *value = context;
2856 *len = clen;
2857 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002858
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002859 return 0;
2860}
2861
Al Viro4acdaf22011-07-26 01:42:34 -04002862static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863{
2864 return may_create(dir, dentry, SECCLASS_FILE);
2865}
2866
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2868{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 return may_link(dir, old_dentry, MAY_LINK);
2870}
2871
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2873{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 return may_link(dir, dentry, MAY_UNLINK);
2875}
2876
2877static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2878{
2879 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2880}
2881
Al Viro18bb1db2011-07-26 01:41:39 -04002882static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883{
2884 return may_create(dir, dentry, SECCLASS_DIR);
2885}
2886
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2888{
2889 return may_link(dir, dentry, MAY_RMDIR);
2890}
2891
Al Viro1a67aaf2011-07-26 01:52:52 -04002892static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2895}
2896
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002898 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
2900 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2901}
2902
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903static int selinux_inode_readlink(struct dentry *dentry)
2904{
David Howells88e67f32008-11-14 10:39:21 +11002905 const struct cred *cred = current_cred();
2906
Eric Paris2875fa02011-04-28 16:04:24 -04002907 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908}
2909
NeilBrownbda0be72015-03-23 13:37:39 +11002910static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2911 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912{
David Howells88e67f32008-11-14 10:39:21 +11002913 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002914 struct common_audit_data ad;
2915 struct inode_security_struct *isec;
2916 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
NeilBrownbda0be72015-03-23 13:37:39 +11002918 validate_creds(cred);
2919
2920 ad.type = LSM_AUDIT_DATA_DENTRY;
2921 ad.u.dentry = dentry;
2922 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002923 isec = inode_security_rcu(inode, rcu);
2924 if (IS_ERR(isec))
2925 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002926
2927 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2928 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929}
2930
Eric Parisd4cf970d2012-04-04 15:01:42 -04002931static noinline int audit_inode_permission(struct inode *inode,
2932 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002933 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002934 unsigned flags)
2935{
2936 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002937 struct inode_security_struct *isec = inode->i_security;
2938 int rc;
2939
Eric Paris50c205f2012-04-04 15:01:43 -04002940 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002941 ad.u.inode = inode;
2942
2943 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002944 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002945 if (rc)
2946 return rc;
2947 return 0;
2948}
2949
Al Viroe74f71e2011-06-20 19:38:15 -04002950static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
David Howells88e67f32008-11-14 10:39:21 +11002952 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002953 u32 perms;
2954 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002955 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002956 struct inode_security_struct *isec;
2957 u32 sid;
2958 struct av_decision avd;
2959 int rc, rc2;
2960 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Eric Parisb782e0a2010-07-23 11:44:03 -04002962 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002963 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2964
Eric Parisb782e0a2010-07-23 11:44:03 -04002965 /* No permission to check. Existence test. */
2966 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Eric Paris2e334052012-04-04 15:01:42 -04002969 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002970
Eric Paris2e334052012-04-04 15:01:42 -04002971 if (unlikely(IS_PRIVATE(inode)))
2972 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002973
2974 perms = file_mask_to_av(inode->i_mode, mask);
2975
Eric Paris2e334052012-04-04 15:01:42 -04002976 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002977 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
2978 if (IS_ERR(isec))
2979 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04002980
2981 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2982 audited = avc_audit_required(perms, &avd, rc,
2983 from_access ? FILE__AUDIT_ACCESS : 0,
2984 &denied);
2985 if (likely(!audited))
2986 return rc;
2987
Stephen Smalley626b9742014-04-29 11:29:04 -07002988 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002989 if (rc2)
2990 return rc2;
2991 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992}
2993
2994static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2995{
David Howells88e67f32008-11-14 10:39:21 +11002996 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002997 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002998 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003000 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3001 if (ia_valid & ATTR_FORCE) {
3002 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3003 ATTR_FORCE);
3004 if (!ia_valid)
3005 return 0;
3006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003008 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3009 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003010 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Jeff Vander Stoep44d37ad2015-10-21 17:44:25 -04003012 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
3013 && !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003014 av |= FILE__OPEN;
3015
3016 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017}
3018
Al Viro3f7036a2015-03-08 19:28:30 -04003019static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020{
Al Viro3f7036a2015-03-08 19:28:30 -04003021 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022}
3023
David Howells8f0cfa52008-04-29 00:59:41 -07003024static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07003025{
David Howells88e67f32008-11-14 10:39:21 +11003026 const struct cred *cred = current_cred();
3027
Serge E. Hallynb5376772007-10-16 23:31:36 -07003028 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3029 sizeof XATTR_SECURITY_PREFIX - 1)) {
3030 if (!strcmp(name, XATTR_NAME_CAPS)) {
3031 if (!capable(CAP_SETFCAP))
3032 return -EPERM;
3033 } else if (!capable(CAP_SYS_ADMIN)) {
3034 /* A different attribute in the security namespace.
3035 Restrict to administrator. */
3036 return -EPERM;
3037 }
3038 }
3039
3040 /* Not an attribute we recognize, so just check the
3041 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04003042 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003043}
3044
David Howells8f0cfa52008-04-29 00:59:41 -07003045static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3046 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
David Howellsc6f493d2015-03-17 22:26:22 +00003048 struct inode *inode = d_backing_inode(dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003049 struct inode_security_struct *isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003051 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003052 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 int rc = 0;
3054
Serge E. Hallynb5376772007-10-16 23:31:36 -07003055 if (strcmp(name, XATTR_NAME_SELINUX))
3056 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
3058 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003059 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 return -EOPNOTSUPP;
3061
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003062 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 return -EPERM;
3064
Eric Paris50c205f2012-04-04 15:01:43 -04003065 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003066 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
David Howells275bb412008-11-14 10:39:19 +11003068 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 FILE__RELABELFROM, &ad);
3070 if (rc)
3071 return rc;
3072
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003073 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003074 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003075 if (!capable(CAP_MAC_ADMIN)) {
3076 struct audit_buffer *ab;
3077 size_t audit_size;
3078 const char *str;
3079
3080 /* We strip a nul only if it is at the end, otherwise the
3081 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003082 if (value) {
3083 str = value;
3084 if (str[size - 1] == '\0')
3085 audit_size = size - 1;
3086 else
3087 audit_size = size;
3088 } else {
3089 str = "";
3090 audit_size = 0;
3091 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003092 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3093 audit_log_format(ab, "op=setxattr invalid_context=");
3094 audit_log_n_untrustedstring(ab, value, audit_size);
3095 audit_log_end(ab);
3096
Stephen Smalley12b29f32008-05-07 13:03:20 -04003097 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003098 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003099 rc = security_context_to_sid_force(value, size, &newsid);
3100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 if (rc)
3102 return rc;
3103
David Howells275bb412008-11-14 10:39:19 +11003104 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 FILE__RELABELTO, &ad);
3106 if (rc)
3107 return rc;
3108
David Howells275bb412008-11-14 10:39:19 +11003109 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003110 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 if (rc)
3112 return rc;
3113
3114 return avc_has_perm(newsid,
3115 sbsec->sid,
3116 SECCLASS_FILESYSTEM,
3117 FILESYSTEM__ASSOCIATE,
3118 &ad);
3119}
3120
David Howells8f0cfa52008-04-29 00:59:41 -07003121static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003122 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003123 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124{
David Howellsc6f493d2015-03-17 22:26:22 +00003125 struct inode *inode = d_backing_inode(dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003126 struct inode_security_struct *isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 u32 newsid;
3128 int rc;
3129
3130 if (strcmp(name, XATTR_NAME_SELINUX)) {
3131 /* Not an attribute we recognize, so nothing to do. */
3132 return;
3133 }
3134
Stephen Smalley12b29f32008-05-07 13:03:20 -04003135 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003137 printk(KERN_ERR "SELinux: unable to map context to SID"
3138 "for (%s, %lu), rc=%d\n",
3139 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 return;
3141 }
3142
David Quigleyaa9c2662013-05-22 12:50:44 -04003143 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003145 isec->initialized = LABEL_INITIALIZED;
David Quigleyaa9c2662013-05-22 12:50:44 -04003146
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 return;
3148}
3149
David Howells8f0cfa52008-04-29 00:59:41 -07003150static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151{
David Howells88e67f32008-11-14 10:39:21 +11003152 const struct cred *cred = current_cred();
3153
Eric Paris2875fa02011-04-28 16:04:24 -04003154 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155}
3156
Eric Paris828dfe12008-04-17 13:17:49 -04003157static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158{
David Howells88e67f32008-11-14 10:39:21 +11003159 const struct cred *cred = current_cred();
3160
Eric Paris2875fa02011-04-28 16:04:24 -04003161 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162}
3163
David Howells8f0cfa52008-04-29 00:59:41 -07003164static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003166 if (strcmp(name, XATTR_NAME_SELINUX))
3167 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
3169 /* No one is allowed to remove a SELinux security label.
3170 You can change the label, but all data must be labeled. */
3171 return -EACCES;
3172}
3173
James Morrisd381d8a2005-10-30 14:59:22 -08003174/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003175 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003176 *
3177 * Permission check is handled by selinux_inode_getxattr hook.
3178 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003179static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180{
David P. Quigley42492592008-02-04 22:29:39 -08003181 u32 size;
3182 int error;
3183 char *context = NULL;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003184 struct inode_security_struct *isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003186 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3187 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003189 /*
3190 * If the caller has CAP_MAC_ADMIN, then get the raw context
3191 * value even if it is not defined by current policy; otherwise,
3192 * use the in-core value under current policy.
3193 * Use the non-auditing forms of the permission checks since
3194 * getxattr may be called by unprivileged processes commonly
3195 * and lack of permission just means that we fall back to the
3196 * in-core context value, not a denial.
3197 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003198 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3199 SECURITY_CAP_NOAUDIT);
3200 if (!error)
3201 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3202 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003203 if (!error)
3204 error = security_sid_to_context_force(isec->sid, &context,
3205 &size);
3206 else
3207 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003208 if (error)
3209 return error;
3210 error = size;
3211 if (alloc) {
3212 *buffer = context;
3213 goto out_nofree;
3214 }
3215 kfree(context);
3216out_nofree:
3217 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218}
3219
3220static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003221 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003223 struct inode_security_struct *isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 u32 newsid;
3225 int rc;
3226
3227 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3228 return -EOPNOTSUPP;
3229
3230 if (!value || !size)
3231 return -EACCES;
3232
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003233 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 if (rc)
3235 return rc;
3236
David Quigleyaa9c2662013-05-22 12:50:44 -04003237 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003239 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 return 0;
3241}
3242
3243static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3244{
3245 const int len = sizeof(XATTR_NAME_SELINUX);
3246 if (buffer && len <= buffer_size)
3247 memcpy(buffer, XATTR_NAME_SELINUX, len);
3248 return len;
3249}
3250
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003251static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003252{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003253 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003254 *secid = isec->sid;
3255}
3256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257/* file security operations */
3258
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003259static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260{
David Howells88e67f32008-11-14 10:39:21 +11003261 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003262 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3265 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3266 mask |= MAY_APPEND;
3267
Paul Moore389fb8002009-03-27 17:10:34 -04003268 return file_has_perm(cred, file,
3269 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270}
3271
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003272static int selinux_file_permission(struct file *file, int mask)
3273{
Al Viro496ad9a2013-01-23 17:07:38 -05003274 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003275 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003276 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003277 u32 sid = current_sid();
3278
Paul Moore389fb8002009-03-27 17:10:34 -04003279 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003280 /* No permission to check. Existence test. */
3281 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003282
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003283 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003284 if (sid == fsec->sid && fsec->isid == isec->sid &&
3285 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003286 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003287 return 0;
3288
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003289 return selinux_revalidate_file_permission(file, mask);
3290}
3291
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292static int selinux_file_alloc_security(struct file *file)
3293{
3294 return file_alloc_security(file);
3295}
3296
3297static void selinux_file_free_security(struct file *file)
3298{
3299 file_free_security(file);
3300}
3301
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003302/*
3303 * Check whether a task has the ioctl permission and cmd
3304 * operation to an inode.
3305 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003306static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003307 u32 requested, u16 cmd)
3308{
3309 struct common_audit_data ad;
3310 struct file_security_struct *fsec = file->f_security;
3311 struct inode *inode = file_inode(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003312 struct inode_security_struct *isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003313 struct lsm_ioctlop_audit ioctl;
3314 u32 ssid = cred_sid(cred);
3315 int rc;
3316 u8 driver = cmd >> 8;
3317 u8 xperm = cmd & 0xff;
3318
3319 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3320 ad.u.op = &ioctl;
3321 ad.u.op->cmd = cmd;
3322 ad.u.op->path = file->f_path;
3323
3324 if (ssid != fsec->sid) {
3325 rc = avc_has_perm(ssid, fsec->sid,
3326 SECCLASS_FD,
3327 FD__USE,
3328 &ad);
3329 if (rc)
3330 goto out;
3331 }
3332
3333 if (unlikely(IS_PRIVATE(inode)))
3334 return 0;
3335
3336 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3337 requested, driver, xperm, &ad);
3338out:
3339 return rc;
3340}
3341
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3343 unsigned long arg)
3344{
David Howells88e67f32008-11-14 10:39:21 +11003345 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003346 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347
Eric Paris0b24dcb2011-02-25 15:39:20 -05003348 switch (cmd) {
3349 case FIONREAD:
3350 /* fall through */
3351 case FIBMAP:
3352 /* fall through */
3353 case FIGETBSZ:
3354 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003355 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003356 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003357 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003358 error = file_has_perm(cred, file, FILE__GETATTR);
3359 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Al Viro2f99c362012-03-23 16:04:05 -04003361 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003362 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003363 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003364 error = file_has_perm(cred, file, FILE__SETATTR);
3365 break;
3366
3367 /* sys_ioctl() checks */
3368 case FIONBIO:
3369 /* fall through */
3370 case FIOASYNC:
3371 error = file_has_perm(cred, file, 0);
3372 break;
3373
3374 case KDSKBENT:
3375 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003376 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3377 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003378 break;
3379
3380 /* default case assumes that the command will go
3381 * to the file's ioctl() function.
3382 */
3383 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003384 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003385 }
3386 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387}
3388
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003389static int default_noexec;
3390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3392{
David Howells88e67f32008-11-14 10:39:21 +11003393 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003394 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003395
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003396 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003397 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3398 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 /*
3400 * We are making executable an anonymous mapping or a
3401 * private file mapping that will also be writable.
3402 * This has an additional check.
3403 */
David Howellsd84f4f92008-11-14 10:39:23 +11003404 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003406 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
3409 if (file) {
3410 /* read access is always possible with a mapping */
3411 u32 av = FILE__READ;
3412
3413 /* write access only matters if the mapping is shared */
3414 if (shared && (prot & PROT_WRITE))
3415 av |= FILE__WRITE;
3416
3417 if (prot & PROT_EXEC)
3418 av |= FILE__EXECUTE;
3419
David Howells88e67f32008-11-14 10:39:21 +11003420 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 }
David Howellsd84f4f92008-11-14 10:39:23 +11003422
3423error:
3424 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425}
3426
Al Viroe5467852012-05-30 13:30:51 -04003427static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003429 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003430
3431 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3432 u32 sid = current_sid();
3433 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3434 MEMPROTECT__MMAP_ZERO, NULL);
3435 }
3436
3437 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003438}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
Al Viroe5467852012-05-30 13:30:51 -04003440static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3441 unsigned long prot, unsigned long flags)
3442{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 if (selinux_checkreqprot)
3444 prot = reqprot;
3445
3446 return file_map_prot_check(file, prot,
3447 (flags & MAP_TYPE) == MAP_SHARED);
3448}
3449
3450static int selinux_file_mprotect(struct vm_area_struct *vma,
3451 unsigned long reqprot,
3452 unsigned long prot)
3453{
David Howells88e67f32008-11-14 10:39:21 +11003454 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
3456 if (selinux_checkreqprot)
3457 prot = reqprot;
3458
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003459 if (default_noexec &&
3460 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003461 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003462 if (vma->vm_start >= vma->vm_mm->start_brk &&
3463 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003464 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003465 } else if (!vma->vm_file &&
3466 vma->vm_start <= vma->vm_mm->start_stack &&
3467 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003468 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003469 } else if (vma->vm_file && vma->anon_vma) {
3470 /*
3471 * We are making executable a file mapping that has
3472 * had some COW done. Since pages might have been
3473 * written, check ability to execute the possibly
3474 * modified content. This typically should only
3475 * occur for text relocations.
3476 */
David Howellsd84f4f92008-11-14 10:39:23 +11003477 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003478 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003479 if (rc)
3480 return rc;
3481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482
3483 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3484}
3485
3486static int selinux_file_lock(struct file *file, unsigned int cmd)
3487{
David Howells88e67f32008-11-14 10:39:21 +11003488 const struct cred *cred = current_cred();
3489
3490 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491}
3492
3493static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3494 unsigned long arg)
3495{
David Howells88e67f32008-11-14 10:39:21 +11003496 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 int err = 0;
3498
3499 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003500 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003501 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003502 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003504 }
3505 /* fall through */
3506 case F_SETOWN:
3507 case F_SETSIG:
3508 case F_GETFL:
3509 case F_GETOWN:
3510 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003511 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003512 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003513 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003514 break;
3515 case F_GETLK:
3516 case F_SETLK:
3517 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003518 case F_OFD_GETLK:
3519 case F_OFD_SETLK:
3520 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003522 case F_GETLK64:
3523 case F_SETLK64:
3524 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525#endif
David Howells88e67f32008-11-14 10:39:21 +11003526 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003527 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 }
3529
3530 return err;
3531}
3532
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003533static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 struct file_security_struct *fsec;
3536
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003538 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539}
3540
3541static int selinux_file_send_sigiotask(struct task_struct *tsk,
3542 struct fown_struct *fown, int signum)
3543{
Eric Paris828dfe12008-04-17 13:17:49 -04003544 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003545 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 struct file_security_struct *fsec;
3548
3549 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003550 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 fsec = file->f_security;
3553
3554 if (!signum)
3555 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3556 else
3557 perm = signal_to_av(signum);
3558
David Howells275bb412008-11-14 10:39:19 +11003559 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 SECCLASS_PROCESS, perm, NULL);
3561}
3562
3563static int selinux_file_receive(struct file *file)
3564{
David Howells88e67f32008-11-14 10:39:21 +11003565 const struct cred *cred = current_cred();
3566
3567 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568}
3569
Eric Paris83d49852012-04-04 13:45:40 -04003570static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003571{
3572 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003573 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003574
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003575 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003576 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003577 /*
3578 * Save inode label and policy sequence number
3579 * at open-time so that selinux_file_permission
3580 * can determine whether revalidation is necessary.
3581 * Task label is already saved in the file security
3582 * struct as its SID.
3583 */
3584 fsec->isid = isec->sid;
3585 fsec->pseqno = avc_policy_seqno();
3586 /*
3587 * Since the inode label or policy seqno may have changed
3588 * between the selinux_inode_permission check and the saving
3589 * of state above, recheck that access is still permitted.
3590 * Otherwise, access might never be revalidated against the
3591 * new inode label or new policy.
3592 * This check is not redundant - do not remove.
3593 */
David Howells13f8e982013-06-13 23:37:55 +01003594 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003595}
3596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597/* task security operations */
3598
3599static int selinux_task_create(unsigned long clone_flags)
3600{
David Howells3b11a1d2008-11-14 10:39:26 +11003601 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602}
3603
David Howellsf1752ee2008-11-14 10:39:17 +11003604/*
David Howellsee18d642009-09-02 09:14:21 +01003605 * allocate the SELinux part of blank credentials
3606 */
3607static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3608{
3609 struct task_security_struct *tsec;
3610
3611 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3612 if (!tsec)
3613 return -ENOMEM;
3614
3615 cred->security = tsec;
3616 return 0;
3617}
3618
3619/*
David Howellsf1752ee2008-11-14 10:39:17 +11003620 * detach and free the LSM part of a set of credentials
3621 */
3622static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623{
David Howellsf1752ee2008-11-14 10:39:17 +11003624 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003625
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003626 /*
3627 * cred->security == NULL if security_cred_alloc_blank() or
3628 * security_prepare_creds() returned an error.
3629 */
3630 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003631 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003632 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633}
3634
David Howellsd84f4f92008-11-14 10:39:23 +11003635/*
3636 * prepare a new set of credentials for modification
3637 */
3638static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3639 gfp_t gfp)
3640{
3641 const struct task_security_struct *old_tsec;
3642 struct task_security_struct *tsec;
3643
3644 old_tsec = old->security;
3645
3646 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3647 if (!tsec)
3648 return -ENOMEM;
3649
3650 new->security = tsec;
3651 return 0;
3652}
3653
3654/*
David Howellsee18d642009-09-02 09:14:21 +01003655 * transfer the SELinux data to a blank set of creds
3656 */
3657static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3658{
3659 const struct task_security_struct *old_tsec = old->security;
3660 struct task_security_struct *tsec = new->security;
3661
3662 *tsec = *old_tsec;
3663}
3664
3665/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003666 * set the security data for a kernel service
3667 * - all the creation contexts are set to unlabelled
3668 */
3669static int selinux_kernel_act_as(struct cred *new, u32 secid)
3670{
3671 struct task_security_struct *tsec = new->security;
3672 u32 sid = current_sid();
3673 int ret;
3674
3675 ret = avc_has_perm(sid, secid,
3676 SECCLASS_KERNEL_SERVICE,
3677 KERNEL_SERVICE__USE_AS_OVERRIDE,
3678 NULL);
3679 if (ret == 0) {
3680 tsec->sid = secid;
3681 tsec->create_sid = 0;
3682 tsec->keycreate_sid = 0;
3683 tsec->sockcreate_sid = 0;
3684 }
3685 return ret;
3686}
3687
3688/*
3689 * set the file creation context in a security record to the same as the
3690 * objective context of the specified inode
3691 */
3692static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3693{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003694 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003695 struct task_security_struct *tsec = new->security;
3696 u32 sid = current_sid();
3697 int ret;
3698
3699 ret = avc_has_perm(sid, isec->sid,
3700 SECCLASS_KERNEL_SERVICE,
3701 KERNEL_SERVICE__CREATE_FILES_AS,
3702 NULL);
3703
3704 if (ret == 0)
3705 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003706 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003707}
3708
Eric Parisdd8dbf22009-11-03 16:35:32 +11003709static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003710{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003711 u32 sid;
3712 struct common_audit_data ad;
3713
3714 sid = task_sid(current);
3715
Eric Paris50c205f2012-04-04 15:01:43 -04003716 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003717 ad.u.kmod_name = kmod_name;
3718
3719 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3720 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003721}
3722
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3724{
David Howells3b11a1d2008-11-14 10:39:26 +11003725 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726}
3727
3728static int selinux_task_getpgid(struct task_struct *p)
3729{
David Howells3b11a1d2008-11-14 10:39:26 +11003730 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731}
3732
3733static int selinux_task_getsid(struct task_struct *p)
3734{
David Howells3b11a1d2008-11-14 10:39:26 +11003735 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736}
3737
David Quigleyf9008e4c2006-06-30 01:55:46 -07003738static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3739{
David Howells275bb412008-11-14 10:39:19 +11003740 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003741}
3742
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743static int selinux_task_setnice(struct task_struct *p, int nice)
3744{
David Howells3b11a1d2008-11-14 10:39:26 +11003745 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746}
3747
James Morris03e68062006-06-23 02:03:58 -07003748static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3749{
David Howells3b11a1d2008-11-14 10:39:26 +11003750 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003751}
3752
David Quigleya1836a42006-06-30 01:55:49 -07003753static int selinux_task_getioprio(struct task_struct *p)
3754{
David Howells3b11a1d2008-11-14 10:39:26 +11003755 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003756}
3757
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003758static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3759 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003761 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762
3763 /* Control the ability to change the hard limit (whether
3764 lowering or raising it), so that the hard limit can
3765 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003766 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003768 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
3770 return 0;
3771}
3772
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003773static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774{
David Howells3b11a1d2008-11-14 10:39:26 +11003775 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776}
3777
3778static int selinux_task_getscheduler(struct task_struct *p)
3779{
David Howells3b11a1d2008-11-14 10:39:26 +11003780 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781}
3782
David Quigley35601542006-06-23 02:04:01 -07003783static int selinux_task_movememory(struct task_struct *p)
3784{
David Howells3b11a1d2008-11-14 10:39:26 +11003785 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003786}
3787
David Quigleyf9008e4c2006-06-30 01:55:46 -07003788static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3789 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790{
3791 u32 perm;
3792 int rc;
3793
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 if (!sig)
3795 perm = PROCESS__SIGNULL; /* null signal; existence test */
3796 else
3797 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003798 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003799 rc = avc_has_perm(secid, task_sid(p),
3800 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003801 else
David Howells3b11a1d2008-11-14 10:39:26 +11003802 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003803 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804}
3805
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806static int selinux_task_wait(struct task_struct *p)
3807{
Eric Paris8a535142007-10-22 16:10:31 -04003808 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809}
3810
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811static void selinux_task_to_inode(struct task_struct *p,
3812 struct inode *inode)
3813{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003815 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
David Howells275bb412008-11-14 10:39:19 +11003817 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003818 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819}
3820
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003822static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003823 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824{
3825 int offset, ihlen, ret = -EINVAL;
3826 struct iphdr _iph, *ih;
3827
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003828 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3830 if (ih == NULL)
3831 goto out;
3832
3833 ihlen = ih->ihl * 4;
3834 if (ihlen < sizeof(_iph))
3835 goto out;
3836
Eric Paris48c62af2012-04-02 13:15:44 -04003837 ad->u.net->v4info.saddr = ih->saddr;
3838 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 ret = 0;
3840
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003841 if (proto)
3842 *proto = ih->protocol;
3843
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003845 case IPPROTO_TCP: {
3846 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847
Eric Paris828dfe12008-04-17 13:17:49 -04003848 if (ntohs(ih->frag_off) & IP_OFFSET)
3849 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
3851 offset += ihlen;
3852 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3853 if (th == NULL)
3854 break;
3855
Eric Paris48c62af2012-04-02 13:15:44 -04003856 ad->u.net->sport = th->source;
3857 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860
Eric Paris828dfe12008-04-17 13:17:49 -04003861 case IPPROTO_UDP: {
3862 struct udphdr _udph, *uh;
3863
3864 if (ntohs(ih->frag_off) & IP_OFFSET)
3865 break;
3866
3867 offset += ihlen;
3868 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3869 if (uh == NULL)
3870 break;
3871
Eric Paris48c62af2012-04-02 13:15:44 -04003872 ad->u.net->sport = uh->source;
3873 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003874 break;
3875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
James Morris2ee92d42006-11-13 16:09:01 -08003877 case IPPROTO_DCCP: {
3878 struct dccp_hdr _dccph, *dh;
3879
3880 if (ntohs(ih->frag_off) & IP_OFFSET)
3881 break;
3882
3883 offset += ihlen;
3884 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3885 if (dh == NULL)
3886 break;
3887
Eric Paris48c62af2012-04-02 13:15:44 -04003888 ad->u.net->sport = dh->dccph_sport;
3889 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003890 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003891 }
James Morris2ee92d42006-11-13 16:09:01 -08003892
Eric Paris828dfe12008-04-17 13:17:49 -04003893 default:
3894 break;
3895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896out:
3897 return ret;
3898}
3899
3900#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3901
3902/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003903static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003904 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905{
3906 u8 nexthdr;
3907 int ret = -EINVAL, offset;
3908 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003909 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003911 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3913 if (ip6 == NULL)
3914 goto out;
3915
Eric Paris48c62af2012-04-02 13:15:44 -04003916 ad->u.net->v6info.saddr = ip6->saddr;
3917 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 ret = 0;
3919
3920 nexthdr = ip6->nexthdr;
3921 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003922 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 if (offset < 0)
3924 goto out;
3925
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003926 if (proto)
3927 *proto = nexthdr;
3928
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 switch (nexthdr) {
3930 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003931 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932
3933 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3934 if (th == NULL)
3935 break;
3936
Eric Paris48c62af2012-04-02 13:15:44 -04003937 ad->u.net->sport = th->source;
3938 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 break;
3940 }
3941
3942 case IPPROTO_UDP: {
3943 struct udphdr _udph, *uh;
3944
3945 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3946 if (uh == NULL)
3947 break;
3948
Eric Paris48c62af2012-04-02 13:15:44 -04003949 ad->u.net->sport = uh->source;
3950 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 break;
3952 }
3953
James Morris2ee92d42006-11-13 16:09:01 -08003954 case IPPROTO_DCCP: {
3955 struct dccp_hdr _dccph, *dh;
3956
3957 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3958 if (dh == NULL)
3959 break;
3960
Eric Paris48c62af2012-04-02 13:15:44 -04003961 ad->u.net->sport = dh->dccph_sport;
3962 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003963 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003964 }
James Morris2ee92d42006-11-13 16:09:01 -08003965
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 /* includes fragments */
3967 default:
3968 break;
3969 }
3970out:
3971 return ret;
3972}
3973
3974#endif /* IPV6 */
3975
Thomas Liu2bf49692009-07-14 12:14:09 -04003976static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003977 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978{
David Howellscf9481e2008-07-27 21:31:07 +10003979 char *addrp;
3980 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Eric Paris48c62af2012-04-02 13:15:44 -04003982 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003984 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003985 if (ret)
3986 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003987 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3988 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003989 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
3991#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3992 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003993 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003994 if (ret)
3995 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003996 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3997 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003998 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999#endif /* IPV6 */
4000 default:
David Howellscf9481e2008-07-27 21:31:07 +10004001 addrp = NULL;
4002 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 }
4004
David Howellscf9481e2008-07-27 21:31:07 +10004005parse_error:
4006 printk(KERN_WARNING
4007 "SELinux: failure in selinux_parse_skb(),"
4008 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004010
4011okay:
4012 if (_addrp)
4013 *_addrp = addrp;
4014 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015}
4016
Paul Moore4f6a9932007-03-01 14:35:22 -05004017/**
Paul Moore220deb92008-01-29 08:38:23 -05004018 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004019 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004020 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004021 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004022 *
4023 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004024 * Check the various different forms of network peer labeling and determine
4025 * the peer label/SID for the packet; most of the magic actually occurs in
4026 * the security server function security_net_peersid_cmp(). The function
4027 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4028 * or -EACCES if @sid is invalid due to inconsistencies with the different
4029 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004030 *
4031 */
Paul Moore220deb92008-01-29 08:38:23 -05004032static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004033{
Paul Moore71f1cb02008-01-29 08:51:16 -05004034 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004035 u32 xfrm_sid;
4036 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004037 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004038
Paul Moore817eff72013-12-10 14:57:54 -05004039 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004040 if (unlikely(err))
4041 return -EACCES;
4042 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4043 if (unlikely(err))
4044 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004045
Paul Moore71f1cb02008-01-29 08:51:16 -05004046 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
4047 if (unlikely(err)) {
4048 printk(KERN_WARNING
4049 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4050 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004051 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004052 }
Paul Moore220deb92008-01-29 08:38:23 -05004053
4054 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004055}
4056
Paul Moore446b8022013-12-04 16:10:51 -05004057/**
4058 * selinux_conn_sid - Determine the child socket label for a connection
4059 * @sk_sid: the parent socket's SID
4060 * @skb_sid: the packet's SID
4061 * @conn_sid: the resulting connection SID
4062 *
4063 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4064 * combined with the MLS information from @skb_sid in order to create
4065 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4066 * of @sk_sid. Returns zero on success, negative values on failure.
4067 *
4068 */
4069static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4070{
4071 int err = 0;
4072
4073 if (skb_sid != SECSID_NULL)
4074 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4075 else
4076 *conn_sid = sk_sid;
4077
4078 return err;
4079}
4080
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004082
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004083static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4084 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004085{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004086 if (tsec->sockcreate_sid > SECSID_NULL) {
4087 *socksid = tsec->sockcreate_sid;
4088 return 0;
4089 }
4090
4091 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4092 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004093}
4094
Paul Moore253bfae2010-04-22 14:46:19 -04004095static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096{
Paul Moore253bfae2010-04-22 14:46:19 -04004097 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004098 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004099 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004100 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Paul Moore253bfae2010-04-22 14:46:19 -04004102 if (sksec->sid == SECINITSID_KERNEL)
4103 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Eric Paris50c205f2012-04-04 15:01:43 -04004105 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004106 ad.u.net = &net;
4107 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Paul Moore253bfae2010-04-22 14:46:19 -04004109 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110}
4111
4112static int selinux_socket_create(int family, int type,
4113 int protocol, int kern)
4114{
Paul Moore5fb49872010-04-22 14:46:19 -04004115 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004116 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004117 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004118 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
4120 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004121 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
David Howells275bb412008-11-14 10:39:19 +11004123 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004124 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4125 if (rc)
4126 return rc;
4127
Paul Moored4f2d972010-04-22 14:46:18 -04004128 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129}
4130
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004131static int selinux_socket_post_create(struct socket *sock, int family,
4132 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133{
Paul Moore5fb49872010-04-22 14:46:19 -04004134 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004135 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004136 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004137 int err = 0;
4138
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004139 isec->sclass = socket_type_to_security_class(family, type, protocol);
4140
David Howells275bb412008-11-14 10:39:19 +11004141 if (kern)
4142 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004143 else {
4144 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4145 if (err)
4146 return err;
4147 }
David Howells275bb412008-11-14 10:39:19 +11004148
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004149 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004151 if (sock->sk) {
4152 sksec = sock->sk->sk_security;
4153 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004154 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004155 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004156 }
4157
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004158 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159}
4160
4161/* Range of port numbers used to automatically bind.
4162 Need to determine whether we should perform a name_bind
4163 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
4165static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4166{
Paul Moore253bfae2010-04-22 14:46:19 -04004167 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 u16 family;
4169 int err;
4170
Paul Moore253bfae2010-04-22 14:46:19 -04004171 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 if (err)
4173 goto out;
4174
4175 /*
4176 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004177 * Multiple address binding for SCTP is not supported yet: we just
4178 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 */
Paul Moore253bfae2010-04-22 14:46:19 -04004180 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 if (family == PF_INET || family == PF_INET6) {
4182 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004183 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004184 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004185 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 struct sockaddr_in *addr4 = NULL;
4187 struct sockaddr_in6 *addr6 = NULL;
4188 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004189 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 if (family == PF_INET) {
4192 addr4 = (struct sockaddr_in *)address;
4193 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 addrp = (char *)&addr4->sin_addr.s_addr;
4195 } else {
4196 addr6 = (struct sockaddr_in6 *)address;
4197 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 addrp = (char *)&addr6->sin6_addr.s6_addr;
4199 }
4200
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004201 if (snum) {
4202 int low, high;
4203
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004204 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004205
4206 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004207 err = sel_netport_sid(sk->sk_protocol,
4208 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004209 if (err)
4210 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004211 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004212 ad.u.net = &net;
4213 ad.u.net->sport = htons(snum);
4214 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004215 err = avc_has_perm(sksec->sid, sid,
4216 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004217 SOCKET__NAME_BIND, &ad);
4218 if (err)
4219 goto out;
4220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 }
Eric Paris828dfe12008-04-17 13:17:49 -04004222
Paul Moore253bfae2010-04-22 14:46:19 -04004223 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004224 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 node_perm = TCP_SOCKET__NODE_BIND;
4226 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004227
James Morris13402582005-09-30 14:24:34 -04004228 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 node_perm = UDP_SOCKET__NODE_BIND;
4230 break;
James Morris2ee92d42006-11-13 16:09:01 -08004231
4232 case SECCLASS_DCCP_SOCKET:
4233 node_perm = DCCP_SOCKET__NODE_BIND;
4234 break;
4235
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 default:
4237 node_perm = RAWIP_SOCKET__NODE_BIND;
4238 break;
4239 }
Eric Paris828dfe12008-04-17 13:17:49 -04004240
Paul Moore224dfbd2008-01-29 08:38:13 -05004241 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 if (err)
4243 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004244
Eric Paris50c205f2012-04-04 15:01:43 -04004245 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004246 ad.u.net = &net;
4247 ad.u.net->sport = htons(snum);
4248 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
4250 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004251 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 else
Eric Paris48c62af2012-04-02 13:15:44 -04004253 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Paul Moore253bfae2010-04-22 14:46:19 -04004255 err = avc_has_perm(sksec->sid, sid,
4256 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 if (err)
4258 goto out;
4259 }
4260out:
4261 return err;
4262}
4263
4264static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4265{
Paul Moore014ab192008-10-10 10:16:33 -04004266 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004267 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 int err;
4269
Paul Moore253bfae2010-04-22 14:46:19 -04004270 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 if (err)
4272 return err;
4273
4274 /*
James Morris2ee92d42006-11-13 16:09:01 -08004275 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 */
Paul Moore253bfae2010-04-22 14:46:19 -04004277 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4278 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004279 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004280 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 struct sockaddr_in *addr4 = NULL;
4282 struct sockaddr_in6 *addr6 = NULL;
4283 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004284 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285
4286 if (sk->sk_family == PF_INET) {
4287 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004288 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 return -EINVAL;
4290 snum = ntohs(addr4->sin_port);
4291 } else {
4292 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004293 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 return -EINVAL;
4295 snum = ntohs(addr6->sin6_port);
4296 }
4297
Paul Moore3e1121722008-04-10 10:48:14 -04004298 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 if (err)
4300 goto out;
4301
Paul Moore253bfae2010-04-22 14:46:19 -04004302 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004303 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4304
Eric Paris50c205f2012-04-04 15:01:43 -04004305 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004306 ad.u.net = &net;
4307 ad.u.net->dport = htons(snum);
4308 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004309 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 if (err)
4311 goto out;
4312 }
4313
Paul Moore014ab192008-10-10 10:16:33 -04004314 err = selinux_netlbl_socket_connect(sk, address);
4315
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316out:
4317 return err;
4318}
4319
4320static int selinux_socket_listen(struct socket *sock, int backlog)
4321{
Paul Moore253bfae2010-04-22 14:46:19 -04004322 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4326{
4327 int err;
4328 struct inode_security_struct *isec;
4329 struct inode_security_struct *newisec;
4330
Paul Moore253bfae2010-04-22 14:46:19 -04004331 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 if (err)
4333 return err;
4334
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004335 newisec = inode_security_novalidate(SOCK_INODE(newsock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004337 isec = inode_security_novalidate(SOCK_INODE(sock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 newisec->sclass = isec->sclass;
4339 newisec->sid = isec->sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004340 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
4342 return 0;
4343}
4344
4345static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004346 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347{
Paul Moore253bfae2010-04-22 14:46:19 -04004348 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349}
4350
4351static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4352 int size, int flags)
4353{
Paul Moore253bfae2010-04-22 14:46:19 -04004354 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355}
4356
4357static int selinux_socket_getsockname(struct socket *sock)
4358{
Paul Moore253bfae2010-04-22 14:46:19 -04004359 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360}
4361
4362static int selinux_socket_getpeername(struct socket *sock)
4363{
Paul Moore253bfae2010-04-22 14:46:19 -04004364 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365}
4366
Eric Paris828dfe12008-04-17 13:17:49 -04004367static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368{
Paul Mooref8687af2006-10-30 15:22:15 -08004369 int err;
4370
Paul Moore253bfae2010-04-22 14:46:19 -04004371 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004372 if (err)
4373 return err;
4374
4375 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376}
4377
4378static int selinux_socket_getsockopt(struct socket *sock, int level,
4379 int optname)
4380{
Paul Moore253bfae2010-04-22 14:46:19 -04004381 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382}
4383
4384static int selinux_socket_shutdown(struct socket *sock, int how)
4385{
Paul Moore253bfae2010-04-22 14:46:19 -04004386 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387}
4388
David S. Miller3610cda2011-01-05 15:38:53 -08004389static int selinux_socket_unix_stream_connect(struct sock *sock,
4390 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 struct sock *newsk)
4392{
David S. Miller3610cda2011-01-05 15:38:53 -08004393 struct sk_security_struct *sksec_sock = sock->sk_security;
4394 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004395 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004396 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004397 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 int err;
4399
Eric Paris50c205f2012-04-04 15:01:43 -04004400 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004401 ad.u.net = &net;
4402 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Paul Moore4d1e2452010-04-22 14:46:18 -04004404 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4405 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4407 if (err)
4408 return err;
4409
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004411 sksec_new->peer_sid = sksec_sock->sid;
4412 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4413 &sksec_new->sid);
4414 if (err)
4415 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004416
Paul Moore4d1e2452010-04-22 14:46:18 -04004417 /* connecting socket */
4418 sksec_sock->peer_sid = sksec_new->sid;
4419
4420 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421}
4422
4423static int selinux_socket_unix_may_send(struct socket *sock,
4424 struct socket *other)
4425{
Paul Moore253bfae2010-04-22 14:46:19 -04004426 struct sk_security_struct *ssec = sock->sk->sk_security;
4427 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004428 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004429 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430
Eric Paris50c205f2012-04-04 15:01:43 -04004431 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004432 ad.u.net = &net;
4433 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Paul Moore253bfae2010-04-22 14:46:19 -04004435 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4436 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437}
4438
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004439static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4440 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004441 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004442{
4443 int err;
4444 u32 if_sid;
4445 u32 node_sid;
4446
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004447 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004448 if (err)
4449 return err;
4450 err = avc_has_perm(peer_sid, if_sid,
4451 SECCLASS_NETIF, NETIF__INGRESS, ad);
4452 if (err)
4453 return err;
4454
4455 err = sel_netnode_sid(addrp, family, &node_sid);
4456 if (err)
4457 return err;
4458 return avc_has_perm(peer_sid, node_sid,
4459 SECCLASS_NODE, NODE__RECVFROM, ad);
4460}
4461
Paul Moore220deb92008-01-29 08:38:23 -05004462static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004463 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004464{
Paul Moore277d3422008-12-31 12:54:11 -05004465 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004466 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004467 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004468 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004469 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004470 char *addrp;
4471
Eric Paris50c205f2012-04-04 15:01:43 -04004472 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004473 ad.u.net = &net;
4474 ad.u.net->netif = skb->skb_iif;
4475 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004476 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4477 if (err)
4478 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004479
Paul Moore58bfbb52009-03-27 17:10:41 -04004480 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004481 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004482 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004483 if (err)
4484 return err;
4485 }
Paul Moore220deb92008-01-29 08:38:23 -05004486
Steffen Klassertb9679a72011-02-23 12:55:21 +01004487 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4488 if (err)
4489 return err;
4490 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004491
James Morris4e5ab4c2006-06-09 00:33:33 -07004492 return err;
4493}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004494
James Morris4e5ab4c2006-06-09 00:33:33 -07004495static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4496{
Paul Moore220deb92008-01-29 08:38:23 -05004497 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004498 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004499 u16 family = sk->sk_family;
4500 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004501 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004502 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004503 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004504 u8 secmark_active;
4505 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004506
James Morris4e5ab4c2006-06-09 00:33:33 -07004507 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004508 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004509
4510 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004511 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004512 family = PF_INET;
4513
Paul Moored8395c82008-10-10 10:16:30 -04004514 /* If any sort of compatibility mode is enabled then handoff processing
4515 * to the selinux_sock_rcv_skb_compat() function to deal with the
4516 * special handling. We do this in an attempt to keep this function
4517 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004518 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004519 return selinux_sock_rcv_skb_compat(sk, skb, family);
4520
4521 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004522 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004523 if (!secmark_active && !peerlbl_active)
4524 return 0;
4525
Eric Paris50c205f2012-04-04 15:01:43 -04004526 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004527 ad.u.net = &net;
4528 ad.u.net->netif = skb->skb_iif;
4529 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004530 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004531 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004532 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004533
Paul Moored8395c82008-10-10 10:16:30 -04004534 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004535 u32 peer_sid;
4536
4537 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4538 if (err)
4539 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004540 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4541 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004542 if (err) {
4543 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004544 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004545 }
Paul Moored621d352008-01-29 08:43:36 -05004546 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4547 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004548 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004549 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004550 return err;
4551 }
Paul Moored621d352008-01-29 08:43:36 -05004552 }
4553
Paul Moored8395c82008-10-10 10:16:30 -04004554 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004555 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4556 PACKET__RECV, &ad);
4557 if (err)
4558 return err;
4559 }
4560
Paul Moored621d352008-01-29 08:43:36 -05004561 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562}
4563
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004564static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4565 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566{
4567 int err = 0;
4568 char *scontext;
4569 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004570 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004571 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572
Paul Moore253bfae2010-04-22 14:46:19 -04004573 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4574 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004575 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004576 if (peer_sid == SECSID_NULL)
4577 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004579 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004581 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582
4583 if (scontext_len > len) {
4584 err = -ERANGE;
4585 goto out_len;
4586 }
4587
4588 if (copy_to_user(optval, scontext, scontext_len))
4589 err = -EFAULT;
4590
4591out_len:
4592 if (put_user(scontext_len, optlen))
4593 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 return err;
4596}
4597
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004598static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004599{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004600 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004601 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004602
Paul Mooreaa862902008-10-10 10:16:29 -04004603 if (skb && skb->protocol == htons(ETH_P_IP))
4604 family = PF_INET;
4605 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4606 family = PF_INET6;
4607 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004608 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004609 else
4610 goto out;
4611
4612 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004613 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004614 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004615 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004616
Paul Moore75e22912008-01-29 08:38:04 -05004617out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004618 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004619 if (peer_secid == SECSID_NULL)
4620 return -EINVAL;
4621 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004622}
4623
Al Viro7d877f32005-10-21 03:20:43 -04004624static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625{
Paul Moore84914b72010-04-22 14:46:18 -04004626 struct sk_security_struct *sksec;
4627
4628 sksec = kzalloc(sizeof(*sksec), priority);
4629 if (!sksec)
4630 return -ENOMEM;
4631
4632 sksec->peer_sid = SECINITSID_UNLABELED;
4633 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004634 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004635 selinux_netlbl_sk_security_reset(sksec);
4636 sk->sk_security = sksec;
4637
4638 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639}
4640
4641static void selinux_sk_free_security(struct sock *sk)
4642{
Paul Moore84914b72010-04-22 14:46:18 -04004643 struct sk_security_struct *sksec = sk->sk_security;
4644
4645 sk->sk_security = NULL;
4646 selinux_netlbl_sk_security_free(sksec);
4647 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648}
4649
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004650static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4651{
Eric Parisdd3e7832010-04-07 15:08:46 -04004652 struct sk_security_struct *sksec = sk->sk_security;
4653 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004654
Eric Parisdd3e7832010-04-07 15:08:46 -04004655 newsksec->sid = sksec->sid;
4656 newsksec->peer_sid = sksec->peer_sid;
4657 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004658
Eric Parisdd3e7832010-04-07 15:08:46 -04004659 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004660}
4661
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004662static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004663{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004664 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004665 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004666 else {
4667 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004668
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004669 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004670 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004671}
4672
Eric Paris828dfe12008-04-17 13:17:49 -04004673static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004674{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004675 struct inode_security_struct *isec =
4676 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004677 struct sk_security_struct *sksec = sk->sk_security;
4678
Paul Moore2873ead2014-07-28 10:42:48 -04004679 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4680 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004681 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004682 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004683}
4684
Adrian Bunk9a673e52006-08-15 00:03:53 -07004685static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4686 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004687{
4688 struct sk_security_struct *sksec = sk->sk_security;
4689 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004690 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004691 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004692 u32 peersid;
4693
Paul Mooreaa862902008-10-10 10:16:29 -04004694 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004695 if (err)
4696 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004697 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4698 if (err)
4699 return err;
4700 req->secid = connsid;
4701 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004702
Paul Moore389fb8002009-03-27 17:10:34 -04004703 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004704}
4705
Adrian Bunk9a673e52006-08-15 00:03:53 -07004706static void selinux_inet_csk_clone(struct sock *newsk,
4707 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004708{
4709 struct sk_security_struct *newsksec = newsk->sk_security;
4710
4711 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004712 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004713 /* NOTE: Ideally, we should also get the isec->sid for the
4714 new socket in sync, but we don't have the isec available yet.
4715 So we will wait until sock_graft to do it, by which
4716 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004717
Paul Moore9f2ad662006-11-17 17:38:53 -05004718 /* We don't need to take any sort of lock here as we are the only
4719 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004720 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004721}
4722
Paul Moore014ab192008-10-10 10:16:33 -04004723static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004724{
Paul Mooreaa862902008-10-10 10:16:29 -04004725 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004726 struct sk_security_struct *sksec = sk->sk_security;
4727
Paul Mooreaa862902008-10-10 10:16:29 -04004728 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4729 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4730 family = PF_INET;
4731
4732 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004733}
4734
Eric Paris2606fd12010-10-13 16:24:41 -04004735static int selinux_secmark_relabel_packet(u32 sid)
4736{
4737 const struct task_security_struct *__tsec;
4738 u32 tsid;
4739
4740 __tsec = current_security();
4741 tsid = __tsec->sid;
4742
4743 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4744}
4745
4746static void selinux_secmark_refcount_inc(void)
4747{
4748 atomic_inc(&selinux_secmark_refcount);
4749}
4750
4751static void selinux_secmark_refcount_dec(void)
4752{
4753 atomic_dec(&selinux_secmark_refcount);
4754}
4755
Adrian Bunk9a673e52006-08-15 00:03:53 -07004756static void selinux_req_classify_flow(const struct request_sock *req,
4757 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004758{
David S. Miller1d28f422011-03-12 00:29:39 -05004759 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004760}
4761
Paul Moore5dbbaf22013-01-14 07:12:19 +00004762static int selinux_tun_dev_alloc_security(void **security)
4763{
4764 struct tun_security_struct *tunsec;
4765
4766 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4767 if (!tunsec)
4768 return -ENOMEM;
4769 tunsec->sid = current_sid();
4770
4771 *security = tunsec;
4772 return 0;
4773}
4774
4775static void selinux_tun_dev_free_security(void *security)
4776{
4777 kfree(security);
4778}
4779
Paul Mooreed6d76e2009-08-28 18:12:49 -04004780static int selinux_tun_dev_create(void)
4781{
4782 u32 sid = current_sid();
4783
4784 /* we aren't taking into account the "sockcreate" SID since the socket
4785 * that is being created here is not a socket in the traditional sense,
4786 * instead it is a private sock, accessible only to the kernel, and
4787 * representing a wide range of network traffic spanning multiple
4788 * connections unlike traditional sockets - check the TUN driver to
4789 * get a better understanding of why this socket is special */
4790
4791 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4792 NULL);
4793}
4794
Paul Moore5dbbaf22013-01-14 07:12:19 +00004795static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004796{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004797 struct tun_security_struct *tunsec = security;
4798
4799 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4800 TUN_SOCKET__ATTACH_QUEUE, NULL);
4801}
4802
4803static int selinux_tun_dev_attach(struct sock *sk, void *security)
4804{
4805 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004806 struct sk_security_struct *sksec = sk->sk_security;
4807
4808 /* we don't currently perform any NetLabel based labeling here and it
4809 * isn't clear that we would want to do so anyway; while we could apply
4810 * labeling without the support of the TUN user the resulting labeled
4811 * traffic from the other end of the connection would almost certainly
4812 * cause confusion to the TUN user that had no idea network labeling
4813 * protocols were being used */
4814
Paul Moore5dbbaf22013-01-14 07:12:19 +00004815 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004816 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004817
4818 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004819}
4820
Paul Moore5dbbaf22013-01-14 07:12:19 +00004821static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004822{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004823 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004824 u32 sid = current_sid();
4825 int err;
4826
Paul Moore5dbbaf22013-01-14 07:12:19 +00004827 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004828 TUN_SOCKET__RELABELFROM, NULL);
4829 if (err)
4830 return err;
4831 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4832 TUN_SOCKET__RELABELTO, NULL);
4833 if (err)
4834 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004835 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004836
4837 return 0;
4838}
4839
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4841{
4842 int err = 0;
4843 u32 perm;
4844 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004845 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004846
Hong zhi guo77954982013-03-27 06:49:35 +00004847 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848 err = -EINVAL;
4849 goto out;
4850 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004851 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004852
Paul Moore253bfae2010-04-22 14:46:19 -04004853 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004854 if (err) {
4855 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05004856 pr_warn_ratelimited("SELinux: unrecognized netlink"
4857 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
4858 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004859 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05004860 secclass_map[sksec->sclass - 1].name,
4861 task_pid_nr(current), current->comm);
Eric Paris39c9aed2008-11-05 09:34:42 -05004862 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863 err = 0;
4864 }
4865
4866 /* Ignore */
4867 if (err == -ENOENT)
4868 err = 0;
4869 goto out;
4870 }
4871
Paul Moore253bfae2010-04-22 14:46:19 -04004872 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873out:
4874 return err;
4875}
4876
4877#ifdef CONFIG_NETFILTER
4878
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004879static unsigned int selinux_ip_forward(struct sk_buff *skb,
4880 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004881 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882{
Paul Mooredfaebe92008-10-10 10:16:31 -04004883 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004884 char *addrp;
4885 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004886 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004887 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004888 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004889 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004890 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004891
Paul Mooreeffad8d2008-01-29 08:49:27 -05004892 if (!selinux_policycap_netpeer)
4893 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004894
Paul Mooreeffad8d2008-01-29 08:49:27 -05004895 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004896 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004897 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004898 if (!secmark_active && !peerlbl_active)
4899 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004900
Paul Moored8395c82008-10-10 10:16:30 -04004901 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4902 return NF_DROP;
4903
Eric Paris50c205f2012-04-04 15:01:43 -04004904 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004905 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004906 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004907 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004908 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4909 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910
Paul Mooredfaebe92008-10-10 10:16:31 -04004911 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004912 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4913 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004914 if (err) {
4915 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004916 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004917 }
4918 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004919
4920 if (secmark_active)
4921 if (avc_has_perm(peer_sid, skb->secmark,
4922 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4923 return NF_DROP;
4924
Paul Moore948bf852008-10-10 10:16:32 -04004925 if (netlbl_active)
4926 /* we do this in the FORWARD path and not the POST_ROUTING
4927 * path because we want to make sure we apply the necessary
4928 * labeling before IPsec is applied so we can leverage AH
4929 * protection */
4930 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4931 return NF_DROP;
4932
Paul Mooreeffad8d2008-01-29 08:49:27 -05004933 return NF_ACCEPT;
4934}
4935
Eric W. Biederman06198b32015-09-18 14:33:06 -05004936static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004937 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004938 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004939{
David S. Miller238e54c2015-04-03 20:32:56 -04004940 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004941}
4942
4943#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05004944static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004945 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004946 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004947{
David S. Miller238e54c2015-04-03 20:32:56 -04004948 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004949}
4950#endif /* IPV6 */
4951
Paul Moore948bf852008-10-10 10:16:32 -04004952static unsigned int selinux_ip_output(struct sk_buff *skb,
4953 u16 family)
4954{
Paul Moore47180062013-12-04 16:10:45 -05004955 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004956 u32 sid;
4957
4958 if (!netlbl_enabled())
4959 return NF_ACCEPT;
4960
4961 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4962 * because we want to make sure we apply the necessary labeling
4963 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004964 sk = skb->sk;
4965 if (sk) {
4966 struct sk_security_struct *sksec;
4967
Eric Dumazete446f9d2015-10-08 05:01:55 -07004968 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05004969 /* if the socket is the listening state then this
4970 * packet is a SYN-ACK packet which means it needs to
4971 * be labeled based on the connection/request_sock and
4972 * not the parent socket. unfortunately, we can't
4973 * lookup the request_sock yet as it isn't queued on
4974 * the parent socket until after the SYN-ACK is sent.
4975 * the "solution" is to simply pass the packet as-is
4976 * as any IP option based labeling should be copied
4977 * from the initial connection request (in the IP
4978 * layer). it is far from ideal, but until we get a
4979 * security label in the packet itself this is the
4980 * best we can do. */
4981 return NF_ACCEPT;
4982
4983 /* standard practice, label using the parent socket */
4984 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004985 sid = sksec->sid;
4986 } else
4987 sid = SECINITSID_KERNEL;
4988 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4989 return NF_DROP;
4990
4991 return NF_ACCEPT;
4992}
4993
Eric W. Biederman06198b32015-09-18 14:33:06 -05004994static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04004995 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004996 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004997{
4998 return selinux_ip_output(skb, PF_INET);
4999}
5000
Paul Mooreeffad8d2008-01-29 08:49:27 -05005001static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5002 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005003 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005004{
Eric Dumazet54abc682015-11-08 10:54:07 -08005005 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005006 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005007 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005008 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005009 char *addrp;
5010 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005011
Paul Mooreeffad8d2008-01-29 08:49:27 -05005012 if (sk == NULL)
5013 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005014 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005015
Eric Paris50c205f2012-04-04 15:01:43 -04005016 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005017 ad.u.net = &net;
5018 ad.u.net->netif = ifindex;
5019 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005020 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5021 return NF_DROP;
5022
Paul Moore58bfbb52009-03-27 17:10:41 -04005023 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005024 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005025 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005026 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005027
Steffen Klassertb9679a72011-02-23 12:55:21 +01005028 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5029 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005030
Paul Mooreeffad8d2008-01-29 08:49:27 -05005031 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032}
5033
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005034static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5035 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005036 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005038 u32 secmark_perm;
5039 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005040 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005041 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005042 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005043 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005044 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005045 u8 secmark_active;
5046 u8 peerlbl_active;
5047
Paul Mooreeffad8d2008-01-29 08:49:27 -05005048 /* If any sort of compatibility mode is enabled then handoff processing
5049 * to the selinux_ip_postroute_compat() function to deal with the
5050 * special handling. We do this in an attempt to keep this function
5051 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04005052 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04005053 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005054
Paul Mooreeffad8d2008-01-29 08:49:27 -05005055 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005056 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005057 if (!secmark_active && !peerlbl_active)
5058 return NF_ACCEPT;
5059
Eric Dumazet54abc682015-11-08 10:54:07 -08005060 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005061
Paul Mooreeffad8d2008-01-29 08:49:27 -05005062#ifdef CONFIG_XFRM
5063 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5064 * packet transformation so allow the packet to pass without any checks
5065 * since we'll have another chance to perform access control checks
5066 * when the packet is on it's final way out.
5067 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005068 * is NULL, in this case go ahead and apply access control.
5069 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5070 * TCP listening state we cannot wait until the XFRM processing
5071 * is done as we will miss out on the SA label if we do;
5072 * unfortunately, this means more work, but it is only once per
5073 * connection. */
5074 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005075 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005076 return NF_ACCEPT;
5077#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005078
Paul Moored8395c82008-10-10 10:16:30 -04005079 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005080 /* Without an associated socket the packet is either coming
5081 * from the kernel or it is being forwarded; check the packet
5082 * to determine which and if the packet is being forwarded
5083 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005084 if (skb->skb_iif) {
5085 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005086 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005087 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005088 } else {
5089 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005090 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005091 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005092 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005093 /* Locally generated packet but the associated socket is in the
5094 * listening state which means this is a SYN-ACK packet. In
5095 * this particular case the correct security label is assigned
5096 * to the connection/request_sock but unfortunately we can't
5097 * query the request_sock as it isn't queued on the parent
5098 * socket until after the SYN-ACK packet is sent; the only
5099 * viable choice is to regenerate the label like we do in
5100 * selinux_inet_conn_request(). See also selinux_ip_output()
5101 * for similar problems. */
5102 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005103 struct sk_security_struct *sksec;
5104
Eric Dumazete446f9d2015-10-08 05:01:55 -07005105 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005106 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5107 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005108 /* At this point, if the returned skb peerlbl is SECSID_NULL
5109 * and the packet has been through at least one XFRM
5110 * transformation then we must be dealing with the "final"
5111 * form of labeled IPsec packet; since we've already applied
5112 * all of our access controls on this packet we can safely
5113 * pass the packet. */
5114 if (skb_sid == SECSID_NULL) {
5115 switch (family) {
5116 case PF_INET:
5117 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5118 return NF_ACCEPT;
5119 break;
5120 case PF_INET6:
5121 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5122 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005123 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005124 default:
5125 return NF_DROP_ERR(-ECONNREFUSED);
5126 }
5127 }
Paul Moore446b8022013-12-04 16:10:51 -05005128 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5129 return NF_DROP;
5130 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005131 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005132 /* Locally generated packet, fetch the security label from the
5133 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005134 struct sk_security_struct *sksec = sk->sk_security;
5135 peer_sid = sksec->sid;
5136 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005137 }
5138
Eric Paris50c205f2012-04-04 15:01:43 -04005139 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005140 ad.u.net = &net;
5141 ad.u.net->netif = ifindex;
5142 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005143 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005144 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005145
Paul Mooreeffad8d2008-01-29 08:49:27 -05005146 if (secmark_active)
5147 if (avc_has_perm(peer_sid, skb->secmark,
5148 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005149 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005150
5151 if (peerlbl_active) {
5152 u32 if_sid;
5153 u32 node_sid;
5154
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005155 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005156 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005157 if (avc_has_perm(peer_sid, if_sid,
5158 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005159 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005160
5161 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005162 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005163 if (avc_has_perm(peer_sid, node_sid,
5164 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005165 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005166 }
5167
5168 return NF_ACCEPT;
5169}
5170
Eric W. Biederman06198b32015-09-18 14:33:06 -05005171static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005172 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005173 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005174{
David S. Miller238e54c2015-04-03 20:32:56 -04005175 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176}
5177
5178#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005179static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005180 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005181 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182{
David S. Miller238e54c2015-04-03 20:32:56 -04005183 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185#endif /* IPV6 */
5186
5187#endif /* CONFIG_NETFILTER */
5188
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5190{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005191 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192}
5193
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194static int ipc_alloc_security(struct task_struct *task,
5195 struct kern_ipc_perm *perm,
5196 u16 sclass)
5197{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005199 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200
James Morris89d155e2005-10-30 14:59:21 -08005201 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202 if (!isec)
5203 return -ENOMEM;
5204
David Howells275bb412008-11-14 10:39:19 +11005205 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005207 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208 perm->security = isec;
5209
5210 return 0;
5211}
5212
5213static void ipc_free_security(struct kern_ipc_perm *perm)
5214{
5215 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 perm->security = NULL;
5217 kfree(isec);
5218}
5219
5220static int msg_msg_alloc_security(struct msg_msg *msg)
5221{
5222 struct msg_security_struct *msec;
5223
James Morris89d155e2005-10-30 14:59:21 -08005224 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 if (!msec)
5226 return -ENOMEM;
5227
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228 msec->sid = SECINITSID_UNLABELED;
5229 msg->security = msec;
5230
5231 return 0;
5232}
5233
5234static void msg_msg_free_security(struct msg_msg *msg)
5235{
5236 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
5238 msg->security = NULL;
5239 kfree(msec);
5240}
5241
5242static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005243 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005246 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005247 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 isec = ipc_perms->security;
5250
Eric Paris50c205f2012-04-04 15:01:43 -04005251 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252 ad.u.ipc_id = ipc_perms->key;
5253
David Howells275bb412008-11-14 10:39:19 +11005254 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255}
5256
5257static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5258{
5259 return msg_msg_alloc_security(msg);
5260}
5261
5262static void selinux_msg_msg_free_security(struct msg_msg *msg)
5263{
5264 msg_msg_free_security(msg);
5265}
5266
5267/* message queue security operations */
5268static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5269{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005271 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005272 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273 int rc;
5274
5275 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5276 if (rc)
5277 return rc;
5278
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 isec = msq->q_perm.security;
5280
Eric Paris50c205f2012-04-04 15:01:43 -04005281 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005282 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283
David Howells275bb412008-11-14 10:39:19 +11005284 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285 MSGQ__CREATE, &ad);
5286 if (rc) {
5287 ipc_free_security(&msq->q_perm);
5288 return rc;
5289 }
5290 return 0;
5291}
5292
5293static void selinux_msg_queue_free_security(struct msg_queue *msq)
5294{
5295 ipc_free_security(&msq->q_perm);
5296}
5297
5298static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005301 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005302 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304 isec = msq->q_perm.security;
5305
Eric Paris50c205f2012-04-04 15:01:43 -04005306 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005307 ad.u.ipc_id = msq->q_perm.key;
5308
David Howells275bb412008-11-14 10:39:19 +11005309 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310 MSGQ__ASSOCIATE, &ad);
5311}
5312
5313static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5314{
5315 int err;
5316 int perms;
5317
Eric Paris828dfe12008-04-17 13:17:49 -04005318 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 case IPC_INFO:
5320 case MSG_INFO:
5321 /* No specific object, just general system-wide information. */
5322 return task_has_system(current, SYSTEM__IPC_INFO);
5323 case IPC_STAT:
5324 case MSG_STAT:
5325 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5326 break;
5327 case IPC_SET:
5328 perms = MSGQ__SETATTR;
5329 break;
5330 case IPC_RMID:
5331 perms = MSGQ__DESTROY;
5332 break;
5333 default:
5334 return 0;
5335 }
5336
Stephen Smalley6af963f2005-05-01 08:58:39 -07005337 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 return err;
5339}
5340
5341static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5342{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343 struct ipc_security_struct *isec;
5344 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005345 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005346 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347 int rc;
5348
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349 isec = msq->q_perm.security;
5350 msec = msg->security;
5351
5352 /*
5353 * First time through, need to assign label to the message
5354 */
5355 if (msec->sid == SECINITSID_UNLABELED) {
5356 /*
5357 * Compute new sid based on current process and
5358 * message queue this message will be stored in
5359 */
David Howells275bb412008-11-14 10:39:19 +11005360 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005361 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362 if (rc)
5363 return rc;
5364 }
5365
Eric Paris50c205f2012-04-04 15:01:43 -04005366 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 ad.u.ipc_id = msq->q_perm.key;
5368
5369 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005370 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 MSGQ__WRITE, &ad);
5372 if (!rc)
5373 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005374 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5375 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 if (!rc)
5377 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005378 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5379 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380
5381 return rc;
5382}
5383
5384static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5385 struct task_struct *target,
5386 long type, int mode)
5387{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388 struct ipc_security_struct *isec;
5389 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005390 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005391 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392 int rc;
5393
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394 isec = msq->q_perm.security;
5395 msec = msg->security;
5396
Eric Paris50c205f2012-04-04 15:01:43 -04005397 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005398 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399
David Howells275bb412008-11-14 10:39:19 +11005400 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 SECCLASS_MSGQ, MSGQ__READ, &ad);
5402 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005403 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404 SECCLASS_MSG, MSG__RECEIVE, &ad);
5405 return rc;
5406}
5407
5408/* Shared Memory security operations */
5409static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5410{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005412 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005413 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414 int rc;
5415
5416 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5417 if (rc)
5418 return rc;
5419
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420 isec = shp->shm_perm.security;
5421
Eric Paris50c205f2012-04-04 15:01:43 -04005422 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005423 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
David Howells275bb412008-11-14 10:39:19 +11005425 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426 SHM__CREATE, &ad);
5427 if (rc) {
5428 ipc_free_security(&shp->shm_perm);
5429 return rc;
5430 }
5431 return 0;
5432}
5433
5434static void selinux_shm_free_security(struct shmid_kernel *shp)
5435{
5436 ipc_free_security(&shp->shm_perm);
5437}
5438
5439static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5440{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005442 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005443 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445 isec = shp->shm_perm.security;
5446
Eric Paris50c205f2012-04-04 15:01:43 -04005447 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448 ad.u.ipc_id = shp->shm_perm.key;
5449
David Howells275bb412008-11-14 10:39:19 +11005450 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 SHM__ASSOCIATE, &ad);
5452}
5453
5454/* Note, at this point, shp is locked down */
5455static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5456{
5457 int perms;
5458 int err;
5459
Eric Paris828dfe12008-04-17 13:17:49 -04005460 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461 case IPC_INFO:
5462 case SHM_INFO:
5463 /* No specific object, just general system-wide information. */
5464 return task_has_system(current, SYSTEM__IPC_INFO);
5465 case IPC_STAT:
5466 case SHM_STAT:
5467 perms = SHM__GETATTR | SHM__ASSOCIATE;
5468 break;
5469 case IPC_SET:
5470 perms = SHM__SETATTR;
5471 break;
5472 case SHM_LOCK:
5473 case SHM_UNLOCK:
5474 perms = SHM__LOCK;
5475 break;
5476 case IPC_RMID:
5477 perms = SHM__DESTROY;
5478 break;
5479 default:
5480 return 0;
5481 }
5482
Stephen Smalley6af963f2005-05-01 08:58:39 -07005483 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 return err;
5485}
5486
5487static int selinux_shm_shmat(struct shmid_kernel *shp,
5488 char __user *shmaddr, int shmflg)
5489{
5490 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491
5492 if (shmflg & SHM_RDONLY)
5493 perms = SHM__READ;
5494 else
5495 perms = SHM__READ | SHM__WRITE;
5496
Stephen Smalley6af963f2005-05-01 08:58:39 -07005497 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005498}
5499
5500/* Semaphore security operations */
5501static int selinux_sem_alloc_security(struct sem_array *sma)
5502{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005504 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005505 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506 int rc;
5507
5508 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5509 if (rc)
5510 return rc;
5511
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 isec = sma->sem_perm.security;
5513
Eric Paris50c205f2012-04-04 15:01:43 -04005514 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005515 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516
David Howells275bb412008-11-14 10:39:19 +11005517 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 SEM__CREATE, &ad);
5519 if (rc) {
5520 ipc_free_security(&sma->sem_perm);
5521 return rc;
5522 }
5523 return 0;
5524}
5525
5526static void selinux_sem_free_security(struct sem_array *sma)
5527{
5528 ipc_free_security(&sma->sem_perm);
5529}
5530
5531static int selinux_sem_associate(struct sem_array *sma, int semflg)
5532{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005534 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005535 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537 isec = sma->sem_perm.security;
5538
Eric Paris50c205f2012-04-04 15:01:43 -04005539 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540 ad.u.ipc_id = sma->sem_perm.key;
5541
David Howells275bb412008-11-14 10:39:19 +11005542 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543 SEM__ASSOCIATE, &ad);
5544}
5545
5546/* Note, at this point, sma is locked down */
5547static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5548{
5549 int err;
5550 u32 perms;
5551
Eric Paris828dfe12008-04-17 13:17:49 -04005552 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553 case IPC_INFO:
5554 case SEM_INFO:
5555 /* No specific object, just general system-wide information. */
5556 return task_has_system(current, SYSTEM__IPC_INFO);
5557 case GETPID:
5558 case GETNCNT:
5559 case GETZCNT:
5560 perms = SEM__GETATTR;
5561 break;
5562 case GETVAL:
5563 case GETALL:
5564 perms = SEM__READ;
5565 break;
5566 case SETVAL:
5567 case SETALL:
5568 perms = SEM__WRITE;
5569 break;
5570 case IPC_RMID:
5571 perms = SEM__DESTROY;
5572 break;
5573 case IPC_SET:
5574 perms = SEM__SETATTR;
5575 break;
5576 case IPC_STAT:
5577 case SEM_STAT:
5578 perms = SEM__GETATTR | SEM__ASSOCIATE;
5579 break;
5580 default:
5581 return 0;
5582 }
5583
Stephen Smalley6af963f2005-05-01 08:58:39 -07005584 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 return err;
5586}
5587
5588static int selinux_sem_semop(struct sem_array *sma,
5589 struct sembuf *sops, unsigned nsops, int alter)
5590{
5591 u32 perms;
5592
5593 if (alter)
5594 perms = SEM__READ | SEM__WRITE;
5595 else
5596 perms = SEM__READ;
5597
Stephen Smalley6af963f2005-05-01 08:58:39 -07005598 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599}
5600
5601static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5602{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603 u32 av = 0;
5604
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605 av = 0;
5606 if (flag & S_IRUGO)
5607 av |= IPC__UNIX_READ;
5608 if (flag & S_IWUGO)
5609 av |= IPC__UNIX_WRITE;
5610
5611 if (av == 0)
5612 return 0;
5613
Stephen Smalley6af963f2005-05-01 08:58:39 -07005614 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615}
5616
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005617static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5618{
5619 struct ipc_security_struct *isec = ipcp->security;
5620 *secid = isec->sid;
5621}
5622
Eric Paris828dfe12008-04-17 13:17:49 -04005623static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624{
5625 if (inode)
5626 inode_doinit_with_dentry(inode, dentry);
5627}
5628
5629static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005630 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631{
David Howells275bb412008-11-14 10:39:19 +11005632 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005633 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005635 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636
5637 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005638 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639 if (error)
5640 return error;
5641 }
5642
David Howells275bb412008-11-14 10:39:19 +11005643 rcu_read_lock();
5644 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645
5646 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005647 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005649 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005651 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005652 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005653 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005654 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005655 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005656 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005657 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658 else
David Howells275bb412008-11-14 10:39:19 +11005659 goto invalid;
5660 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
5662 if (!sid)
5663 return 0;
5664
Al Viro04ff9702007-03-12 16:17:58 +00005665 error = security_sid_to_context(sid, value, &len);
5666 if (error)
5667 return error;
5668 return len;
David Howells275bb412008-11-14 10:39:19 +11005669
5670invalid:
5671 rcu_read_unlock();
5672 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673}
5674
5675static int selinux_setprocattr(struct task_struct *p,
5676 char *name, void *value, size_t size)
5677{
5678 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005679 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005680 struct cred *new;
5681 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 int error;
5683 char *str = value;
5684
5685 if (current != p) {
5686 /* SELinux only allows a process to change its own
5687 security attributes. */
5688 return -EACCES;
5689 }
5690
5691 /*
5692 * Basic control over ability to set these attributes at all.
5693 * current == p, but we'll pass them separately in case the
5694 * above restriction is ever removed.
5695 */
5696 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005697 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005699 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005700 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005701 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005702 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005703 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005705 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005706 else
5707 error = -EINVAL;
5708 if (error)
5709 return error;
5710
5711 /* Obtain a SID for the context, if one was specified. */
5712 if (size && str[1] && str[1] != '\n') {
5713 if (str[size-1] == '\n') {
5714 str[size-1] = 0;
5715 size--;
5716 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005717 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005718 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005719 if (!capable(CAP_MAC_ADMIN)) {
5720 struct audit_buffer *ab;
5721 size_t audit_size;
5722
5723 /* We strip a nul only if it is at the end, otherwise the
5724 * context contains a nul and we should audit that */
5725 if (str[size - 1] == '\0')
5726 audit_size = size - 1;
5727 else
5728 audit_size = size;
5729 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5730 audit_log_format(ab, "op=fscreate invalid_context=");
5731 audit_log_n_untrustedstring(ab, value, audit_size);
5732 audit_log_end(ab);
5733
Stephen Smalley12b29f32008-05-07 13:03:20 -04005734 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005735 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005736 error = security_context_to_sid_force(value, size,
5737 &sid);
5738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739 if (error)
5740 return error;
5741 }
5742
David Howellsd84f4f92008-11-14 10:39:23 +11005743 new = prepare_creds();
5744 if (!new)
5745 return -ENOMEM;
5746
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747 /* Permission checking based on the specified context is
5748 performed during the actual operation (execve,
5749 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005750 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 checks and may_create for the file creation checks. The
5752 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005753 tsec = new->security;
5754 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005755 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005756 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005757 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005758 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005759 error = may_create_key(sid, p);
5760 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005761 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005762 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005763 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005764 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005765 } else if (!strcmp(name, "current")) {
5766 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005768 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005769
David Howellsd84f4f92008-11-14 10:39:23 +11005770 /* Only allow single threaded processes to change context */
5771 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005772 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005773 error = security_bounded_transition(tsec->sid, sid);
5774 if (error)
5775 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777
5778 /* Check permissions for the transition. */
5779 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005780 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005782 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
5784 /* Check for ptracing, and update the task SID if ok.
5785 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005786 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005787 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005788 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005789 if (tracer)
5790 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005791 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792
David Howellsd84f4f92008-11-14 10:39:23 +11005793 if (tracer) {
5794 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5795 PROCESS__PTRACE, NULL);
5796 if (error)
5797 goto abort_change;
5798 }
5799
5800 tsec->sid = sid;
5801 } else {
5802 error = -EINVAL;
5803 goto abort_change;
5804 }
5805
5806 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005808
5809abort_change:
5810 abort_creds(new);
5811 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812}
5813
David Quigley746df9b2013-05-22 12:50:35 -04005814static int selinux_ismaclabel(const char *name)
5815{
5816 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5817}
5818
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005819static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5820{
5821 return security_sid_to_context(secid, secdata, seclen);
5822}
5823
David Howells7bf570d2008-04-29 20:52:51 +01005824static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005825{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005826 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005827}
5828
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005829static void selinux_release_secctx(char *secdata, u32 seclen)
5830{
Paul Moore088999e2007-08-01 11:12:58 -04005831 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005832}
5833
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05005834static void selinux_inode_invalidate_secctx(struct inode *inode)
5835{
5836 struct inode_security_struct *isec = inode->i_security;
5837
5838 mutex_lock(&isec->lock);
5839 isec->initialized = LABEL_INVALID;
5840 mutex_unlock(&isec->lock);
5841}
5842
David P. Quigley1ee65e32009-09-03 14:25:57 -04005843/*
5844 * called with inode->i_mutex locked
5845 */
5846static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5847{
5848 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5849}
5850
5851/*
5852 * called with inode->i_mutex locked
5853 */
5854static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5855{
5856 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5857}
5858
5859static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5860{
5861 int len = 0;
5862 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5863 ctx, true);
5864 if (len < 0)
5865 return len;
5866 *ctxlen = len;
5867 return 0;
5868}
Michael LeMayd7200242006-06-22 14:47:17 -07005869#ifdef CONFIG_KEYS
5870
David Howellsd84f4f92008-11-14 10:39:23 +11005871static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005872 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005873{
David Howellsd84f4f92008-11-14 10:39:23 +11005874 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005875 struct key_security_struct *ksec;
5876
5877 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5878 if (!ksec)
5879 return -ENOMEM;
5880
David Howellsd84f4f92008-11-14 10:39:23 +11005881 tsec = cred->security;
5882 if (tsec->keycreate_sid)
5883 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005884 else
David Howellsd84f4f92008-11-14 10:39:23 +11005885 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005886
David Howells275bb412008-11-14 10:39:19 +11005887 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005888 return 0;
5889}
5890
5891static void selinux_key_free(struct key *k)
5892{
5893 struct key_security_struct *ksec = k->security;
5894
5895 k->security = NULL;
5896 kfree(ksec);
5897}
5898
5899static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005900 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005901 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005902{
5903 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005904 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005905 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005906
5907 /* if no specific permissions are requested, we skip the
5908 permission check. No serious, additional covert channels
5909 appear to be created. */
5910 if (perm == 0)
5911 return 0;
5912
David Howellsd84f4f92008-11-14 10:39:23 +11005913 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005914
5915 key = key_ref_to_ptr(key_ref);
5916 ksec = key->security;
5917
5918 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005919}
5920
David Howells70a5bb72008-04-29 01:01:26 -07005921static int selinux_key_getsecurity(struct key *key, char **_buffer)
5922{
5923 struct key_security_struct *ksec = key->security;
5924 char *context = NULL;
5925 unsigned len;
5926 int rc;
5927
5928 rc = security_sid_to_context(ksec->sid, &context, &len);
5929 if (!rc)
5930 rc = len;
5931 *_buffer = context;
5932 return rc;
5933}
5934
Michael LeMayd7200242006-06-22 14:47:17 -07005935#endif
5936
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005937static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005938 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5939 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5940 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5941 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005942
Casey Schauflere20b0432015-05-02 15:11:36 -07005943 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5944 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5945 LSM_HOOK_INIT(capget, selinux_capget),
5946 LSM_HOOK_INIT(capset, selinux_capset),
5947 LSM_HOOK_INIT(capable, selinux_capable),
5948 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5949 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5950 LSM_HOOK_INIT(syslog, selinux_syslog),
5951 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05005952
Casey Schauflere20b0432015-05-02 15:11:36 -07005953 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954
Casey Schauflere20b0432015-05-02 15:11:36 -07005955 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5956 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5957 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5958 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959
Casey Schauflere20b0432015-05-02 15:11:36 -07005960 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5961 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5962 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5963 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5964 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5965 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5966 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5967 LSM_HOOK_INIT(sb_mount, selinux_mount),
5968 LSM_HOOK_INIT(sb_umount, selinux_umount),
5969 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5970 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5971 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
Casey Schauflere20b0432015-05-02 15:11:36 -07005973 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Eric Parise0007522008-03-05 10:31:54 -05005974
Casey Schauflere20b0432015-05-02 15:11:36 -07005975 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5976 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5977 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5978 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5979 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5980 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5981 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5982 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5983 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5984 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5985 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5986 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5987 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5988 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5989 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5990 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5991 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5992 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5993 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5994 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5995 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5996 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5997 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5998 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5999 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Casey Schauflere20b0432015-05-02 15:11:36 -07006001 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6002 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6003 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6004 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6005 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6006 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6007 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6008 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6009 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6010 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6011 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6012 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Casey Schauflere20b0432015-05-02 15:11:36 -07006014 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015
Casey Schauflere20b0432015-05-02 15:11:36 -07006016 LSM_HOOK_INIT(task_create, selinux_task_create),
6017 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6018 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6019 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6020 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
6021 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6022 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6023 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
6024 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6025 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6026 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6027 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6028 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6029 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6030 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
6031 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6032 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6033 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6034 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6035 LSM_HOOK_INIT(task_kill, selinux_task_kill),
6036 LSM_HOOK_INIT(task_wait, selinux_task_wait),
6037 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006038
Casey Schauflere20b0432015-05-02 15:11:36 -07006039 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6040 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041
Casey Schauflere20b0432015-05-02 15:11:36 -07006042 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6043 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044
Casey Schauflere20b0432015-05-02 15:11:36 -07006045 LSM_HOOK_INIT(msg_queue_alloc_security,
6046 selinux_msg_queue_alloc_security),
6047 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6048 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6049 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6050 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6051 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
Casey Schauflere20b0432015-05-02 15:11:36 -07006053 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6054 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6055 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6056 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6057 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058
Casey Schauflere20b0432015-05-02 15:11:36 -07006059 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6060 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6061 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6062 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6063 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Casey Schauflere20b0432015-05-02 15:11:36 -07006065 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Casey Schauflere20b0432015-05-02 15:11:36 -07006067 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6068 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
Casey Schauflere20b0432015-05-02 15:11:36 -07006070 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6071 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6072 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6073 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006074 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006075 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6076 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6077 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078
Casey Schauflere20b0432015-05-02 15:11:36 -07006079 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6080 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006081
Casey Schauflere20b0432015-05-02 15:11:36 -07006082 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6083 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6084 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6085 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6086 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6087 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6088 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6089 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6090 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6091 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6092 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6093 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6094 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6095 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6096 LSM_HOOK_INIT(socket_getpeersec_stream,
6097 selinux_socket_getpeersec_stream),
6098 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6099 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6100 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6101 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6102 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6103 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6104 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6105 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6106 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6107 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6108 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6109 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6110 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6111 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6112 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6113 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6114 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6115 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6116 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006117
6118#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006119 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6120 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6121 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6122 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6123 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6124 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6125 selinux_xfrm_state_alloc_acquire),
6126 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6127 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6128 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6129 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6130 selinux_xfrm_state_pol_flow_match),
6131 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006133
6134#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006135 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6136 LSM_HOOK_INIT(key_free, selinux_key_free),
6137 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6138 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006139#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006140
6141#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006142 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6143 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6144 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6145 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006146#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147};
6148
6149static __init int selinux_init(void)
6150{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006151 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006152 selinux_enabled = 0;
6153 return 0;
6154 }
6155
Linus Torvalds1da177e2005-04-16 15:20:36 -07006156 if (!selinux_enabled) {
6157 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6158 return 0;
6159 }
6160
6161 printk(KERN_INFO "SELinux: Initializing.\n");
6162
6163 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006164 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006166 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6167
James Morris7cae7e22006-03-22 00:09:22 -08006168 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6169 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006170 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006171 file_security_cache = kmem_cache_create("selinux_file_security",
6172 sizeof(struct file_security_struct),
6173 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174 avc_init();
6175
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006176 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177
Paul Moore615e51f2014-06-26 14:33:56 -04006178 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6179 panic("SELinux: Unable to register AVC netcache callback\n");
6180
Eric Paris828dfe12008-04-17 13:17:49 -04006181 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006182 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006183 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006184 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006185
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186 return 0;
6187}
6188
Al Viroe8c26252010-03-23 06:36:54 -04006189static void delayed_superblock_init(struct super_block *sb, void *unused)
6190{
6191 superblock_doinit(sb, NULL);
6192}
6193
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194void selinux_complete_init(void)
6195{
Eric Parisfadcdb42007-02-22 18:11:31 -05006196 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197
6198 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006199 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006200 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201}
6202
6203/* SELinux requires early initialization in order to label
6204 all processes and objects when they are created. */
6205security_initcall(selinux_init);
6206
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006207#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208
Jiri Pirko25db6be2014-09-03 17:42:13 +02006209static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006210 {
6211 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006212 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006213 .hooknum = NF_INET_POST_ROUTING,
6214 .priority = NF_IP_PRI_SELINUX_LAST,
6215 },
6216 {
6217 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006218 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006219 .hooknum = NF_INET_FORWARD,
6220 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006221 },
6222 {
6223 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006224 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006225 .hooknum = NF_INET_LOCAL_OUT,
6226 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006227 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006229 {
6230 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006231 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006232 .hooknum = NF_INET_POST_ROUTING,
6233 .priority = NF_IP6_PRI_SELINUX_LAST,
6234 },
6235 {
6236 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006237 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006238 .hooknum = NF_INET_FORWARD,
6239 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006240 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006241#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006242};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243
6244static int __init selinux_nf_ip_init(void)
6245{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006246 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247
6248 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006249 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006250
6251 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6252
Jiri Pirko25db6be2014-09-03 17:42:13 +02006253 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006254 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006255 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006256
Jiri Pirko25db6be2014-09-03 17:42:13 +02006257 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258}
6259
6260__initcall(selinux_nf_ip_init);
6261
6262#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6263static void selinux_nf_ip_exit(void)
6264{
Eric Parisfadcdb42007-02-22 18:11:31 -05006265 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266
Jiri Pirko25db6be2014-09-03 17:42:13 +02006267 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006268}
6269#endif
6270
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006271#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272
6273#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6274#define selinux_nf_ip_exit()
6275#endif
6276
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006277#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278
6279#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006280static int selinux_disabled;
6281
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282int selinux_disable(void)
6283{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006284 if (ss_initialized) {
6285 /* Not permitted after initial policy load. */
6286 return -EINVAL;
6287 }
6288
6289 if (selinux_disabled) {
6290 /* Only do this once. */
6291 return -EINVAL;
6292 }
6293
6294 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6295
6296 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006297 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006299 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006300
Eric Parisaf8ff042009-09-20 21:23:01 -04006301 /* Try to destroy the avc node cache */
6302 avc_disable();
6303
Linus Torvalds1da177e2005-04-16 15:20:36 -07006304 /* Unregister netfilter hooks. */
6305 selinux_nf_ip_exit();
6306
6307 /* Unregister selinuxfs. */
6308 exit_sel_fs();
6309
6310 return 0;
6311}
6312#endif