blob: 98a2e92b316890422a5a201f98f50a0f2df0ae06 [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 Moore3e112172008-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
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +0100234 spin_lock_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 isec->inode = inode;
237 isec->sid = SECINITSID_UNLABELED;
238 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100239 isec->task_sid = sid;
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100240 isec->initialized = LABEL_INVALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 inode->i_security = isec;
242
243 return 0;
244}
245
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500246static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
247
248/*
249 * Try reloading inode security labels that have been marked as invalid. The
250 * @may_sleep parameter indicates when sleeping and thus reloading labels is
Andreas Gruenbacher42059112016-11-10 22:18:27 +0100251 * allowed; when set to false, returns -ECHILD when the label is
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500252 * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
253 * when no dentry is available, set it to NULL instead.
254 */
255static int __inode_security_revalidate(struct inode *inode,
256 struct dentry *opt_dentry,
257 bool may_sleep)
258{
259 struct inode_security_struct *isec = inode->i_security;
260
261 might_sleep_if(may_sleep);
262
Paul Moore1ac424762016-04-18 16:41:38 -0400263 if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500264 if (!may_sleep)
265 return -ECHILD;
266
267 /*
268 * Try reloading the inode security label. This will fail if
269 * @opt_dentry is NULL and no dentry for this inode can be
270 * found; in that case, continue using the old label.
271 */
272 inode_doinit_with_dentry(inode, opt_dentry);
273 }
274 return 0;
275}
276
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500277static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
278{
279 return inode->i_security;
280}
281
282static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
283{
284 int error;
285
286 error = __inode_security_revalidate(inode, NULL, !rcu);
287 if (error)
288 return ERR_PTR(error);
289 return inode->i_security;
290}
291
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500292/*
293 * Get the security label of an inode.
294 */
295static struct inode_security_struct *inode_security(struct inode *inode)
296{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500297 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500298 return inode->i_security;
299}
300
Paul Moore2c971652016-04-19 16:36:28 -0400301static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
302{
303 struct inode *inode = d_backing_inode(dentry);
304
305 return inode->i_security;
306}
307
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500308/*
309 * Get the security label of a dentry's backing inode.
310 */
311static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
312{
313 struct inode *inode = d_backing_inode(dentry);
314
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500315 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500316 return inode->i_security;
317}
318
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500319static void inode_free_rcu(struct rcu_head *head)
320{
321 struct inode_security_struct *isec;
322
323 isec = container_of(head, struct inode_security_struct, rcu);
324 kmem_cache_free(sel_inode_cache, isec);
325}
326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327static void inode_free_security(struct inode *inode)
328{
329 struct inode_security_struct *isec = inode->i_security;
330 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
331
Waiman Long9629d042015-07-10 17:19:56 -0400332 /*
333 * As not all inode security structures are in a list, we check for
334 * empty list outside of the lock to make sure that we won't waste
335 * time taking a lock doing nothing.
336 *
337 * The list_del_init() function can be safely called more than once.
338 * It should not be possible for this function to be called with
339 * concurrent list_add(), but for better safety against future changes
340 * in the code, we use list_empty_careful() here.
341 */
342 if (!list_empty_careful(&isec->list)) {
343 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400345 spin_unlock(&sbsec->isec_lock);
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500348 /*
349 * The inode may still be referenced in a path walk and
350 * a call to selinux_inode_permission() can be made
351 * after inode_free_security() is called. Ideally, the VFS
352 * wouldn't do this, but fixing that is a much harder
353 * job. For now, simply free the i_security via RCU, and
354 * leave the current inode->i_security pointer intact.
355 * The inode will be freed after the RCU grace period too.
356 */
357 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
360static int file_alloc_security(struct file *file)
361{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100363 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Sangwoo63205652015-10-21 17:44:30 -0400365 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (!fsec)
367 return -ENOMEM;
368
David Howells275bb412008-11-14 10:39:19 +1100369 fsec->sid = sid;
370 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 file->f_security = fsec;
372
373 return 0;
374}
375
376static void file_free_security(struct file *file)
377{
378 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400380 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
382
383static int superblock_alloc_security(struct super_block *sb)
384{
385 struct superblock_security_struct *sbsec;
386
James Morris89d155e2005-10-30 14:59:21 -0800387 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 if (!sbsec)
389 return -ENOMEM;
390
Eric Parisbc7e9822006-09-25 23:32:02 -0700391 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 INIT_LIST_HEAD(&sbsec->isec_head);
393 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 sbsec->sb = sb;
395 sbsec->sid = SECINITSID_UNLABELED;
396 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700397 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 sb->s_security = sbsec;
399
400 return 0;
401}
402
403static void superblock_free_security(struct super_block *sb)
404{
405 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 sb->s_security = NULL;
407 kfree(sbsec);
408}
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410/* The file system's label must be initialized prior to use. */
411
David Quigleyeb9ae682013-05-22 12:50:37 -0400412static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 "uses xattr",
414 "uses transition SIDs",
415 "uses task SIDs",
416 "uses genfs_contexts",
417 "not configured for labeling",
418 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400419 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420};
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422static inline int inode_doinit(struct inode *inode)
423{
424 return inode_doinit_with_dentry(inode, NULL);
425}
426
427enum {
Eric Paris31e87932007-09-19 17:19:12 -0400428 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 Opt_context = 1,
430 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500431 Opt_defcontext = 3,
432 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500433 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400434 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435};
436
Eric Parisd355987f2012-08-24 15:58:53 -0400437#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
438
Steven Whitehousea447c092008-10-13 10:46:57 +0100439static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400440 {Opt_context, CONTEXT_STR "%s"},
441 {Opt_fscontext, FSCONTEXT_STR "%s"},
442 {Opt_defcontext, DEFCONTEXT_STR "%s"},
443 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500444 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400445 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446};
447
448#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
449
Eric Parisc312feb2006-07-10 04:43:53 -0700450static int may_context_mount_sb_relabel(u32 sid,
451 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100452 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700453{
David Howells275bb412008-11-14 10:39:19 +1100454 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700455 int rc;
456
457 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
458 FILESYSTEM__RELABELFROM, NULL);
459 if (rc)
460 return rc;
461
462 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
463 FILESYSTEM__RELABELTO, NULL);
464 return rc;
465}
466
Eric Paris08089252006-07-10 04:43:55 -0700467static int may_context_mount_inode_relabel(u32 sid,
468 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100469 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700470{
David Howells275bb412008-11-14 10:39:19 +1100471 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700472 int rc;
473 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
474 FILESYSTEM__RELABELFROM, NULL);
475 if (rc)
476 return rc;
477
478 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
479 FILESYSTEM__ASSOCIATE, NULL);
480 return rc;
481}
482
Eric Parisb43e7252012-10-10 14:27:35 -0400483static int selinux_is_sblabel_mnt(struct super_block *sb)
484{
485 struct superblock_security_struct *sbsec = sb->s_security;
486
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500487 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
488 sbsec->behavior == SECURITY_FS_USE_TRANS ||
489 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400490 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500491 /* Special handling. Genfs but also in-core setxattr handler */
492 !strcmp(sb->s_type->name, "sysfs") ||
493 !strcmp(sb->s_type->name, "pstore") ||
494 !strcmp(sb->s_type->name, "debugfs") ||
495 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400496}
497
Eric Parisc9180a52007-11-30 13:00:35 -0500498static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
500 struct superblock_security_struct *sbsec = sb->s_security;
501 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000502 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 int rc = 0;
504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
506 /* Make sure that the xattr handler exists and that no
507 error other than -ENODATA is returned by getxattr on
508 the root directory. -ENODATA is ok, as this may be
509 the first boot of the SELinux kernel before we have
510 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200511 if (!(root_inode->i_opflags & IOP_XATTR)) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800512 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
513 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 rc = -EOPNOTSUPP;
515 goto out;
516 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200517
518 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 if (rc < 0 && rc != -ENODATA) {
520 if (rc == -EOPNOTSUPP)
521 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800522 "%s) has no security xattr handler\n",
523 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 else
525 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800526 "%s) getxattr errno %d\n", sb->s_id,
527 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 goto out;
529 }
530 }
531
Eric Parisc9180a52007-11-30 13:00:35 -0500532 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800533 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
534 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
Eric Pariseadcabc2012-08-24 15:59:14 -0400536 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400537 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400538 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500541 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 /* Initialize any other inodes associated with the superblock, e.g.
544 inodes created prior to initial policy load or inodes created
545 during get_sb by a pseudo filesystem that directly
546 populates itself. */
547 spin_lock(&sbsec->isec_lock);
548next_inode:
549 if (!list_empty(&sbsec->isec_head)) {
550 struct inode_security_struct *isec =
551 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500552 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400554 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 spin_unlock(&sbsec->isec_lock);
556 inode = igrab(inode);
557 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500558 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 inode_doinit(inode);
560 iput(inode);
561 }
562 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 goto next_inode;
564 }
565 spin_unlock(&sbsec->isec_lock);
566out:
Eric Parisc9180a52007-11-30 13:00:35 -0500567 return rc;
568}
569
570/*
571 * This function should allow an FS to ask what it's mount security
572 * options were so it can use those later for submounts, displaying
573 * mount options, or whatever.
574 */
575static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500576 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500577{
578 int rc = 0, i;
579 struct superblock_security_struct *sbsec = sb->s_security;
580 char *context = NULL;
581 u32 len;
582 char tmp;
583
Eric Parise0007522008-03-05 10:31:54 -0500584 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500585
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500586 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500587 return -EINVAL;
588
589 if (!ss_initialized)
590 return -EINVAL;
591
Eric Parisaf8e50c2012-08-24 15:59:00 -0400592 /* make sure we always check enough bits to cover the mask */
593 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
594
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500595 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500596 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400597 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500598 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500599 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500600 tmp >>= 1;
601 }
David P. Quigley11689d42009-01-16 09:22:03 -0500602 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400603 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500604 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500605
Eric Parise0007522008-03-05 10:31:54 -0500606 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
607 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500608 rc = -ENOMEM;
609 goto out_free;
610 }
611
Eric Parise0007522008-03-05 10:31:54 -0500612 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
613 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500614 rc = -ENOMEM;
615 goto out_free;
616 }
617
618 i = 0;
619 if (sbsec->flags & FSCONTEXT_MNT) {
620 rc = security_sid_to_context(sbsec->sid, &context, &len);
621 if (rc)
622 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500623 opts->mnt_opts[i] = context;
624 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500625 }
626 if (sbsec->flags & CONTEXT_MNT) {
627 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
628 if (rc)
629 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500630 opts->mnt_opts[i] = context;
631 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500632 }
633 if (sbsec->flags & DEFCONTEXT_MNT) {
634 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
635 if (rc)
636 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500637 opts->mnt_opts[i] = context;
638 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500639 }
640 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500641 struct dentry *root = sbsec->sb->s_root;
642 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500643
644 rc = security_sid_to_context(isec->sid, &context, &len);
645 if (rc)
646 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500647 opts->mnt_opts[i] = context;
648 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500649 }
Eric Paris12f348b2012-10-09 10:56:25 -0400650 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500651 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400652 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500653 }
Eric Parisc9180a52007-11-30 13:00:35 -0500654
Eric Parise0007522008-03-05 10:31:54 -0500655 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500656
657 return 0;
658
659out_free:
Eric Parise0007522008-03-05 10:31:54 -0500660 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500661 return rc;
662}
663
664static int bad_option(struct superblock_security_struct *sbsec, char flag,
665 u32 old_sid, u32 new_sid)
666{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500667 char mnt_flags = sbsec->flags & SE_MNTMASK;
668
Eric Parisc9180a52007-11-30 13:00:35 -0500669 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500670 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500671 if (!(sbsec->flags & flag) ||
672 (old_sid != new_sid))
673 return 1;
674
675 /* check if we were passed the same options twice,
676 * aka someone passed context=a,context=b
677 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500678 if (!(sbsec->flags & SE_SBINITIALIZED))
679 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500680 return 1;
681 return 0;
682}
Eric Parise0007522008-03-05 10:31:54 -0500683
Eric Parisc9180a52007-11-30 13:00:35 -0500684/*
685 * Allow filesystems with binary mount data to explicitly set mount point
686 * labeling information.
687 */
Eric Parise0007522008-03-05 10:31:54 -0500688static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400689 struct security_mnt_opts *opts,
690 unsigned long kern_flags,
691 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500692{
David Howells275bb412008-11-14 10:39:19 +1100693 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500694 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500695 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800696 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500697 struct dentry *root = sbsec->sb->s_root;
Paul Moore2c971652016-04-19 16:36:28 -0400698 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500699 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
700 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500701 char **mount_options = opts->mnt_opts;
702 int *flags = opts->mnt_opts_flags;
703 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500704
705 mutex_lock(&sbsec->lock);
706
707 if (!ss_initialized) {
708 if (!num_opts) {
709 /* Defer initialization until selinux_complete_init,
710 after the initial policy is loaded and the security
711 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500712 goto out;
713 }
714 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400715 printk(KERN_WARNING "SELinux: Unable to set superblock options "
716 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500717 goto out;
718 }
David Quigley649f6e72013-05-22 12:50:36 -0400719 if (kern_flags && !set_kern_flags) {
720 /* Specifying internal flags without providing a place to
721 * place the results is not allowed */
722 rc = -EINVAL;
723 goto out;
724 }
Eric Parisc9180a52007-11-30 13:00:35 -0500725
726 /*
Eric Parise0007522008-03-05 10:31:54 -0500727 * Binary mount data FS will come through this function twice. Once
728 * from an explicit call and once from the generic calls from the vfs.
729 * Since the generic VFS calls will not contain any security mount data
730 * we need to skip the double mount verification.
731 *
732 * This does open a hole in which we will not notice if the first
733 * mount using this sb set explict options and a second mount using
734 * this sb does not set any security options. (The first options
735 * will be used for both mounts)
736 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500737 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500738 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400739 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500740
Paul Moore2c971652016-04-19 16:36:28 -0400741 root_isec = backing_inode_security_novalidate(root);
742
Eric Parise0007522008-03-05 10:31:54 -0500743 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500744 * parse the mount options, check if they are valid sids.
745 * also check if someone is trying to mount the same sb more
746 * than once with different security options.
747 */
748 for (i = 0; i < num_opts; i++) {
749 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500750
Eric Paris12f348b2012-10-09 10:56:25 -0400751 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500752 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400753 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500754 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400755 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800756 "(%s) failed for (dev %s, type %s) errno=%d\n",
757 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500758 goto out;
759 }
760 switch (flags[i]) {
761 case FSCONTEXT_MNT:
762 fscontext_sid = sid;
763
764 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
765 fscontext_sid))
766 goto out_double_mount;
767
768 sbsec->flags |= FSCONTEXT_MNT;
769 break;
770 case CONTEXT_MNT:
771 context_sid = sid;
772
773 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
774 context_sid))
775 goto out_double_mount;
776
777 sbsec->flags |= CONTEXT_MNT;
778 break;
779 case ROOTCONTEXT_MNT:
780 rootcontext_sid = sid;
781
782 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
783 rootcontext_sid))
784 goto out_double_mount;
785
786 sbsec->flags |= ROOTCONTEXT_MNT;
787
788 break;
789 case DEFCONTEXT_MNT:
790 defcontext_sid = sid;
791
792 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
793 defcontext_sid))
794 goto out_double_mount;
795
796 sbsec->flags |= DEFCONTEXT_MNT;
797
798 break;
799 default:
800 rc = -EINVAL;
801 goto out;
802 }
803 }
804
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500805 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500806 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500807 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500808 goto out_double_mount;
809 rc = 0;
810 goto out;
811 }
812
James Morris089be432008-07-15 18:32:49 +1000813 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400814 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
815
Stephen Smalley8e014722015-06-04 16:22:17 -0400816 if (!strcmp(sb->s_type->name, "debugfs") ||
817 !strcmp(sb->s_type->name, "sysfs") ||
818 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400819 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500820
David Quigleyeb9ae682013-05-22 12:50:37 -0400821 if (!sbsec->behavior) {
822 /*
823 * Determine the labeling behavior to use for this
824 * filesystem type.
825 */
Paul Moore98f700f2013-09-18 13:52:20 -0400826 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400827 if (rc) {
828 printk(KERN_WARNING
829 "%s: security_fs_use(%s) returned %d\n",
830 __func__, sb->s_type->name, rc);
831 goto out;
832 }
Eric Parisc9180a52007-11-30 13:00:35 -0500833 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500834
835 /*
836 * If this is a user namespace mount, no contexts are allowed
837 * on the command line and security labels must be ignored.
838 */
839 if (sb->s_user_ns != &init_user_ns) {
840 if (context_sid || fscontext_sid || rootcontext_sid ||
841 defcontext_sid) {
842 rc = -EACCES;
843 goto out;
844 }
845 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
846 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
847 rc = security_transition_sid(current_sid(), current_sid(),
848 SECCLASS_FILE, NULL,
849 &sbsec->mntpoint_sid);
850 if (rc)
851 goto out;
852 }
853 goto out_set_opts;
854 }
855
Eric Parisc9180a52007-11-30 13:00:35 -0500856 /* sets the context of the superblock for the fs being mounted. */
857 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100858 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500859 if (rc)
860 goto out;
861
862 sbsec->sid = fscontext_sid;
863 }
864
865 /*
866 * Switch to using mount point labeling behavior.
867 * sets the label used on all file below the mountpoint, and will set
868 * the superblock context if not already set.
869 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400870 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
871 sbsec->behavior = SECURITY_FS_USE_NATIVE;
872 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
873 }
874
Eric Parisc9180a52007-11-30 13:00:35 -0500875 if (context_sid) {
876 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100877 rc = may_context_mount_sb_relabel(context_sid, sbsec,
878 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500879 if (rc)
880 goto out;
881 sbsec->sid = context_sid;
882 } else {
David Howells275bb412008-11-14 10:39:19 +1100883 rc = may_context_mount_inode_relabel(context_sid, sbsec,
884 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500885 if (rc)
886 goto out;
887 }
888 if (!rootcontext_sid)
889 rootcontext_sid = context_sid;
890
891 sbsec->mntpoint_sid = context_sid;
892 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
893 }
894
895 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100896 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
897 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500898 if (rc)
899 goto out;
900
901 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500902 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500903 }
904
905 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400906 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
907 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500908 rc = -EINVAL;
909 printk(KERN_WARNING "SELinux: defcontext option is "
910 "invalid for this filesystem type\n");
911 goto out;
912 }
913
914 if (defcontext_sid != sbsec->def_sid) {
915 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100916 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500917 if (rc)
918 goto out;
919 }
920
921 sbsec->def_sid = defcontext_sid;
922 }
923
Seth Forsheeaad82892016-04-26 14:36:20 -0500924out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500925 rc = sb_finish_set_opts(sb);
926out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700927 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500929out_double_mount:
930 rc = -EINVAL;
931 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800932 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500933 goto out;
934}
935
Jeff Layton094f7b62013-04-01 08:14:24 -0400936static int selinux_cmp_sb_context(const struct super_block *oldsb,
937 const struct super_block *newsb)
938{
939 struct superblock_security_struct *old = oldsb->s_security;
940 struct superblock_security_struct *new = newsb->s_security;
941 char oldflags = old->flags & SE_MNTMASK;
942 char newflags = new->flags & SE_MNTMASK;
943
944 if (oldflags != newflags)
945 goto mismatch;
946 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
947 goto mismatch;
948 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
949 goto mismatch;
950 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
951 goto mismatch;
952 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500953 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
954 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400955 if (oldroot->sid != newroot->sid)
956 goto mismatch;
957 }
958 return 0;
959mismatch:
960 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
961 "different security settings for (dev %s, "
962 "type %s)\n", newsb->s_id, newsb->s_type->name);
963 return -EBUSY;
964}
965
966static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500967 struct super_block *newsb)
968{
969 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
970 struct superblock_security_struct *newsbsec = newsb->s_security;
971
972 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
973 int set_context = (oldsbsec->flags & CONTEXT_MNT);
974 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
975
Eric Paris0f5e6422008-04-21 16:24:11 -0400976 /*
977 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400978 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400979 */
Al Viroe8c26252010-03-23 06:36:54 -0400980 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400981 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500982
Eric Parisc9180a52007-11-30 13:00:35 -0500983 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500984 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500985
Jeff Layton094f7b62013-04-01 08:14:24 -0400986 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500987 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400988 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400989
Eric Parisc9180a52007-11-30 13:00:35 -0500990 mutex_lock(&newsbsec->lock);
991
992 newsbsec->flags = oldsbsec->flags;
993
994 newsbsec->sid = oldsbsec->sid;
995 newsbsec->def_sid = oldsbsec->def_sid;
996 newsbsec->behavior = oldsbsec->behavior;
997
998 if (set_context) {
999 u32 sid = oldsbsec->mntpoint_sid;
1000
1001 if (!set_fscontext)
1002 newsbsec->sid = sid;
1003 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001004 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -05001005 newisec->sid = sid;
1006 }
1007 newsbsec->mntpoint_sid = sid;
1008 }
1009 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001010 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
1011 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -05001012
1013 newisec->sid = oldisec->sid;
1014 }
1015
1016 sb_finish_set_opts(newsb);
1017 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -04001018 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001019}
1020
Adrian Bunk2e1479d2008-03-17 22:29:23 +02001021static int selinux_parse_opts_str(char *options,
1022 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001023{
Eric Parise0007522008-03-05 10:31:54 -05001024 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -05001025 char *context = NULL, *defcontext = NULL;
1026 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -05001027 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001028
Eric Parise0007522008-03-05 10:31:54 -05001029 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001030
1031 /* Standard string-based options. */
1032 while ((p = strsep(&options, "|")) != NULL) {
1033 int token;
1034 substring_t args[MAX_OPT_ARGS];
1035
1036 if (!*p)
1037 continue;
1038
1039 token = match_token(p, tokens, args);
1040
1041 switch (token) {
1042 case Opt_context:
1043 if (context || defcontext) {
1044 rc = -EINVAL;
1045 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1046 goto out_err;
1047 }
1048 context = match_strdup(&args[0]);
1049 if (!context) {
1050 rc = -ENOMEM;
1051 goto out_err;
1052 }
1053 break;
1054
1055 case Opt_fscontext:
1056 if (fscontext) {
1057 rc = -EINVAL;
1058 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1059 goto out_err;
1060 }
1061 fscontext = match_strdup(&args[0]);
1062 if (!fscontext) {
1063 rc = -ENOMEM;
1064 goto out_err;
1065 }
1066 break;
1067
1068 case Opt_rootcontext:
1069 if (rootcontext) {
1070 rc = -EINVAL;
1071 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1072 goto out_err;
1073 }
1074 rootcontext = match_strdup(&args[0]);
1075 if (!rootcontext) {
1076 rc = -ENOMEM;
1077 goto out_err;
1078 }
1079 break;
1080
1081 case Opt_defcontext:
1082 if (context || defcontext) {
1083 rc = -EINVAL;
1084 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1085 goto out_err;
1086 }
1087 defcontext = match_strdup(&args[0]);
1088 if (!defcontext) {
1089 rc = -ENOMEM;
1090 goto out_err;
1091 }
1092 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001093 case Opt_labelsupport:
1094 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001095 default:
1096 rc = -EINVAL;
1097 printk(KERN_WARNING "SELinux: unknown mount option\n");
1098 goto out_err;
1099
1100 }
1101 }
1102
Eric Parise0007522008-03-05 10:31:54 -05001103 rc = -ENOMEM;
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001104 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_KERNEL);
Eric Parise0007522008-03-05 10:31:54 -05001105 if (!opts->mnt_opts)
1106 goto out_err;
1107
Tetsuo Handa8931c3b2016-11-14 20:16:12 +09001108 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int),
1109 GFP_KERNEL);
Eric Parise0007522008-03-05 10:31:54 -05001110 if (!opts->mnt_opts_flags) {
1111 kfree(opts->mnt_opts);
1112 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001113 }
1114
Eric Parise0007522008-03-05 10:31:54 -05001115 if (fscontext) {
1116 opts->mnt_opts[num_mnt_opts] = fscontext;
1117 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1118 }
1119 if (context) {
1120 opts->mnt_opts[num_mnt_opts] = context;
1121 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1122 }
1123 if (rootcontext) {
1124 opts->mnt_opts[num_mnt_opts] = rootcontext;
1125 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1126 }
1127 if (defcontext) {
1128 opts->mnt_opts[num_mnt_opts] = defcontext;
1129 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1130 }
1131
1132 opts->num_mnt_opts = num_mnt_opts;
1133 return 0;
1134
Eric Parisc9180a52007-11-30 13:00:35 -05001135out_err:
1136 kfree(context);
1137 kfree(defcontext);
1138 kfree(fscontext);
1139 kfree(rootcontext);
1140 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141}
Eric Parise0007522008-03-05 10:31:54 -05001142/*
1143 * string mount options parsing and call set the sbsec
1144 */
1145static int superblock_doinit(struct super_block *sb, void *data)
1146{
1147 int rc = 0;
1148 char *options = data;
1149 struct security_mnt_opts opts;
1150
1151 security_init_mnt_opts(&opts);
1152
1153 if (!data)
1154 goto out;
1155
1156 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1157
1158 rc = selinux_parse_opts_str(options, &opts);
1159 if (rc)
1160 goto out_err;
1161
1162out:
David Quigley649f6e72013-05-22 12:50:36 -04001163 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001164
1165out_err:
1166 security_free_mnt_opts(&opts);
1167 return rc;
1168}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Adrian Bunk3583a712008-07-22 20:21:23 +03001170static void selinux_write_opts(struct seq_file *m,
1171 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001172{
1173 int i;
1174 char *prefix;
1175
1176 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001177 char *has_comma;
1178
1179 if (opts->mnt_opts[i])
1180 has_comma = strchr(opts->mnt_opts[i], ',');
1181 else
1182 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001183
1184 switch (opts->mnt_opts_flags[i]) {
1185 case CONTEXT_MNT:
1186 prefix = CONTEXT_STR;
1187 break;
1188 case FSCONTEXT_MNT:
1189 prefix = FSCONTEXT_STR;
1190 break;
1191 case ROOTCONTEXT_MNT:
1192 prefix = ROOTCONTEXT_STR;
1193 break;
1194 case DEFCONTEXT_MNT:
1195 prefix = DEFCONTEXT_STR;
1196 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001197 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001198 seq_putc(m, ',');
1199 seq_puts(m, LABELSUPP_STR);
1200 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001201 default:
1202 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001203 return;
Eric Paris2069f452008-07-04 09:47:13 +10001204 };
1205 /* we need a comma before each option */
1206 seq_putc(m, ',');
1207 seq_puts(m, prefix);
1208 if (has_comma)
1209 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001210 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001211 if (has_comma)
1212 seq_putc(m, '\"');
1213 }
1214}
1215
1216static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1217{
1218 struct security_mnt_opts opts;
1219 int rc;
1220
1221 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001222 if (rc) {
1223 /* before policy load we may get EINVAL, don't show anything */
1224 if (rc == -EINVAL)
1225 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001226 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001227 }
Eric Paris2069f452008-07-04 09:47:13 +10001228
1229 selinux_write_opts(m, &opts);
1230
1231 security_free_mnt_opts(&opts);
1232
1233 return rc;
1234}
1235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236static inline u16 inode_mode_to_security_class(umode_t mode)
1237{
1238 switch (mode & S_IFMT) {
1239 case S_IFSOCK:
1240 return SECCLASS_SOCK_FILE;
1241 case S_IFLNK:
1242 return SECCLASS_LNK_FILE;
1243 case S_IFREG:
1244 return SECCLASS_FILE;
1245 case S_IFBLK:
1246 return SECCLASS_BLK_FILE;
1247 case S_IFDIR:
1248 return SECCLASS_DIR;
1249 case S_IFCHR:
1250 return SECCLASS_CHR_FILE;
1251 case S_IFIFO:
1252 return SECCLASS_FIFO_FILE;
1253
1254 }
1255
1256 return SECCLASS_FILE;
1257}
1258
James Morris13402582005-09-30 14:24:34 -04001259static inline int default_protocol_stream(int protocol)
1260{
1261 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1262}
1263
1264static inline int default_protocol_dgram(int protocol)
1265{
1266 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1267}
1268
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1270{
1271 switch (family) {
1272 case PF_UNIX:
1273 switch (type) {
1274 case SOCK_STREAM:
1275 case SOCK_SEQPACKET:
1276 return SECCLASS_UNIX_STREAM_SOCKET;
1277 case SOCK_DGRAM:
1278 return SECCLASS_UNIX_DGRAM_SOCKET;
1279 }
1280 break;
1281 case PF_INET:
1282 case PF_INET6:
1283 switch (type) {
1284 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001285 if (default_protocol_stream(protocol))
1286 return SECCLASS_TCP_SOCKET;
1287 else
1288 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001290 if (default_protocol_dgram(protocol))
1291 return SECCLASS_UDP_SOCKET;
1292 else
1293 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001294 case SOCK_DCCP:
1295 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001296 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return SECCLASS_RAWIP_SOCKET;
1298 }
1299 break;
1300 case PF_NETLINK:
1301 switch (protocol) {
1302 case NETLINK_ROUTE:
1303 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001304 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1306 case NETLINK_NFLOG:
1307 return SECCLASS_NETLINK_NFLOG_SOCKET;
1308 case NETLINK_XFRM:
1309 return SECCLASS_NETLINK_XFRM_SOCKET;
1310 case NETLINK_SELINUX:
1311 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001312 case NETLINK_ISCSI:
1313 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 case NETLINK_AUDIT:
1315 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001316 case NETLINK_FIB_LOOKUP:
1317 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1318 case NETLINK_CONNECTOR:
1319 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1320 case NETLINK_NETFILTER:
1321 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 case NETLINK_DNRTMSG:
1323 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001324 case NETLINK_KOBJECT_UEVENT:
1325 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001326 case NETLINK_GENERIC:
1327 return SECCLASS_NETLINK_GENERIC_SOCKET;
1328 case NETLINK_SCSITRANSPORT:
1329 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1330 case NETLINK_RDMA:
1331 return SECCLASS_NETLINK_RDMA_SOCKET;
1332 case NETLINK_CRYPTO:
1333 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 default:
1335 return SECCLASS_NETLINK_SOCKET;
1336 }
1337 case PF_PACKET:
1338 return SECCLASS_PACKET_SOCKET;
1339 case PF_KEY:
1340 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001341 case PF_APPLETALK:
1342 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
1344
1345 return SECCLASS_SOCKET;
1346}
1347
Stephen Smalley134509d2015-06-04 16:22:17 -04001348static int selinux_genfs_get_sid(struct dentry *dentry,
1349 u16 tclass,
1350 u16 flags,
1351 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001353 int rc;
Al Virofc640052016-04-10 01:33:30 -04001354 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001355 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Eric Paris828dfe12008-04-17 13:17:49 -04001357 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 if (!buffer)
1359 return -ENOMEM;
1360
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001361 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1362 if (IS_ERR(path))
1363 rc = PTR_ERR(path);
1364 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001365 if (flags & SE_SBPROC) {
1366 /* each process gets a /proc/PID/ entry. Strip off the
1367 * PID part to get a valid selinux labeling.
1368 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1369 while (path[1] >= '0' && path[1] <= '9') {
1370 path[1] = '/';
1371 path++;
1372 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001373 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001374 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 free_page((unsigned long)buffer);
1377 return rc;
1378}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380/* The inode's security attributes must be initialized before first use. */
1381static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1382{
1383 struct superblock_security_struct *sbsec = NULL;
1384 struct inode_security_struct *isec = inode->i_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001385 u32 task_sid, sid = 0;
1386 u16 sclass;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 struct dentry *dentry;
1388#define INITCONTEXTLEN 255
1389 char *context = NULL;
1390 unsigned len = 0;
1391 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001393 if (isec->initialized == LABEL_INITIALIZED)
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001394 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001396 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001397 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001398 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Andreas Gruenbacher13457d02016-11-10 22:18:29 +01001400 if (isec->sclass == SECCLASS_FILE)
1401 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001404 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 /* Defer initialization until selinux_complete_init,
1406 after the initial policy is loaded and the security
1407 server is ready to handle calls. */
1408 spin_lock(&sbsec->isec_lock);
1409 if (list_empty(&isec->list))
1410 list_add(&isec->list, &sbsec->isec_head);
1411 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001412 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 }
1414
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001415 sclass = isec->sclass;
1416 task_sid = isec->task_sid;
1417 sid = isec->sid;
1418 isec->initialized = LABEL_PENDING;
1419 spin_unlock(&isec->lock);
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001422 case SECURITY_FS_USE_NATIVE:
1423 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001425 if (!(inode->i_opflags & IOP_XATTR)) {
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001426 sid = sbsec->def_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 break;
1428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 /* Need a dentry, since the xattr API requires one.
1430 Life would be simpler if we could just pass the inode. */
1431 if (opt_dentry) {
1432 /* Called from d_instantiate or d_splice_alias. */
1433 dentry = dget(opt_dentry);
1434 } else {
1435 /* Called from selinux_complete_init, try to find a dentry. */
1436 dentry = d_find_alias(inode);
1437 }
1438 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001439 /*
1440 * this is can be hit on boot when a file is accessed
1441 * before the policy is loaded. When we load policy we
1442 * may find inodes that have no dentry on the
1443 * sbsec->isec_head list. No reason to complain as these
1444 * will get fixed up the next time we go through
1445 * inode_doinit with a dentry, before these inodes could
1446 * be used again by userspace.
1447 */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001448 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 }
1450
1451 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001452 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 if (!context) {
1454 rc = -ENOMEM;
1455 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001456 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001458 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001459 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001461 kfree(context);
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001464 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (rc < 0) {
1466 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001467 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001470 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 if (!context) {
1472 rc = -ENOMEM;
1473 dput(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001474 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001476 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001477 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 }
1479 dput(dentry);
1480 if (rc < 0) {
1481 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001482 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001483 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 -rc, inode->i_sb->s_id, inode->i_ino);
1485 kfree(context);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001486 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 }
1488 /* Map ENODATA to the default file SID */
1489 sid = sbsec->def_sid;
1490 rc = 0;
1491 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001492 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001493 sbsec->def_sid,
1494 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001496 char *dev = inode->i_sb->s_id;
1497 unsigned long ino = inode->i_ino;
1498
1499 if (rc == -EINVAL) {
1500 if (printk_ratelimit())
1501 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1502 "context=%s. This indicates you may need to relabel the inode or the "
1503 "filesystem in question.\n", ino, dev, context);
1504 } else {
1505 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1506 "returned %d for dev=%s ino=%ld\n",
1507 __func__, context, -rc, dev, ino);
1508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 kfree(context);
1510 /* Leave with the unlabeled SID */
1511 rc = 0;
1512 break;
1513 }
1514 }
1515 kfree(context);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 break;
1517 case SECURITY_FS_USE_TASK:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001518 sid = task_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520 case SECURITY_FS_USE_TRANS:
1521 /* Default to the fs SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001522 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 /* Try to obtain a transition SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001525 rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001527 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001529 case SECURITY_FS_USE_MNTPOINT:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001530 sid = sbsec->mntpoint_sid;
Eric Parisc312feb2006-07-10 04:43:53 -07001531 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001533 /* Default to the fs superblock SID. */
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001534 sid = sbsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Stephen Smalley134509d2015-06-04 16:22:17 -04001536 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001537 /* We must have a dentry to determine the label on
1538 * procfs inodes */
1539 if (opt_dentry)
1540 /* Called from d_instantiate or
1541 * d_splice_alias. */
1542 dentry = dget(opt_dentry);
1543 else
1544 /* Called from selinux_complete_init, try to
1545 * find a dentry. */
1546 dentry = d_find_alias(inode);
1547 /*
1548 * This can be hit on boot when a file is accessed
1549 * before the policy is loaded. When we load policy we
1550 * may find inodes that have no dentry on the
1551 * sbsec->isec_head list. No reason to complain as
1552 * these will get fixed up the next time we go through
1553 * inode_doinit() with a dentry, before these inodes
1554 * could be used again by userspace.
1555 */
1556 if (!dentry)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001557 goto out;
1558 rc = selinux_genfs_get_sid(dentry, sclass,
Stephen Smalley134509d2015-06-04 16:22:17 -04001559 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001560 dput(dentry);
1561 if (rc)
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001562 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 }
1564 break;
1565 }
1566
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001567out:
1568 spin_lock(&isec->lock);
1569 if (isec->initialized == LABEL_PENDING) {
1570 if (!sid || rc) {
1571 isec->initialized = LABEL_INVALID;
1572 goto out_unlock;
1573 }
1574
1575 isec->initialized = LABEL_INITIALIZED;
1576 isec->sid = sid;
1577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Eric Paris23970742006-09-25 23:32:01 -07001579out_unlock:
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01001580 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 return rc;
1582}
1583
1584/* Convert a Linux signal to an access vector. */
1585static inline u32 signal_to_av(int sig)
1586{
1587 u32 perm = 0;
1588
1589 switch (sig) {
1590 case SIGCHLD:
1591 /* Commonly granted from child to parent. */
1592 perm = PROCESS__SIGCHLD;
1593 break;
1594 case SIGKILL:
1595 /* Cannot be caught or ignored */
1596 perm = PROCESS__SIGKILL;
1597 break;
1598 case SIGSTOP:
1599 /* Cannot be caught or ignored */
1600 perm = PROCESS__SIGSTOP;
1601 break;
1602 default:
1603 /* All other signals. */
1604 perm = PROCESS__SIGNAL;
1605 break;
1606 }
1607
1608 return perm;
1609}
1610
David Howells275bb412008-11-14 10:39:19 +11001611/*
David Howellsd84f4f92008-11-14 10:39:23 +11001612 * Check permission between a pair of credentials
1613 * fork check, ptrace check, etc.
1614 */
1615static int cred_has_perm(const struct cred *actor,
1616 const struct cred *target,
1617 u32 perms)
1618{
1619 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1620
1621 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1622}
1623
1624/*
David Howells88e67f32008-11-14 10:39:21 +11001625 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001626 * fork check, ptrace check, etc.
1627 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001628 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001629 */
1630static int task_has_perm(const struct task_struct *tsk1,
1631 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 u32 perms)
1633{
David Howells275bb412008-11-14 10:39:19 +11001634 const struct task_security_struct *__tsec1, *__tsec2;
1635 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
David Howells275bb412008-11-14 10:39:19 +11001637 rcu_read_lock();
1638 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1639 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1640 rcu_read_unlock();
1641 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642}
1643
David Howells3b11a1d2008-11-14 10:39:26 +11001644/*
1645 * Check permission between current and another task, e.g. signal checks,
1646 * fork check, ptrace check, etc.
1647 * current is the actor and tsk2 is the target
1648 * - this uses current's subjective creds
1649 */
1650static int current_has_perm(const struct task_struct *tsk,
1651 u32 perms)
1652{
1653 u32 sid, tsid;
1654
1655 sid = current_sid();
1656 tsid = task_sid(tsk);
1657 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1658}
1659
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001660#if CAP_LAST_CAP > 63
1661#error Fix SELinux to handle capabilities > 63.
1662#endif
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001665static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001666 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
Thomas Liu2bf49692009-07-14 12:14:09 -04001668 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001669 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001670 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001671 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001672 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001673 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
Eric Paris50c205f2012-04-04 15:01:43 -04001675 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 ad.u.cap = cap;
1677
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001678 switch (CAP_TO_INDEX(cap)) {
1679 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001680 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001681 break;
1682 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001683 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001684 break;
1685 default:
1686 printk(KERN_ERR
1687 "SELinux: out of range capability %d\n", cap);
1688 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001689 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001690 }
Eric Paris06112162008-11-11 22:02:50 +11001691
David Howells275bb412008-11-14 10:39:19 +11001692 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001693 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001694 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001695 if (rc2)
1696 return rc2;
1697 }
Eric Paris06112162008-11-11 22:02:50 +11001698 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699}
1700
1701/* Check whether a task is allowed to use a system operation. */
1702static int task_has_system(struct task_struct *tsk,
1703 u32 perms)
1704{
David Howells275bb412008-11-14 10:39:19 +11001705 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
David Howells275bb412008-11-14 10:39:19 +11001707 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 SECCLASS_SYSTEM, perms, NULL);
1709}
1710
1711/* Check whether a task has a particular permission to an inode.
1712 The 'adp' parameter is optional and allows other audit
1713 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001714static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 struct inode *inode,
1716 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001717 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001720 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
David Howellse0e81732009-09-02 09:13:40 +01001722 validate_creds(cred);
1723
Eric Paris828dfe12008-04-17 13:17:49 -04001724 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001725 return 0;
1726
David Howells88e67f32008-11-14 10:39:21 +11001727 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 isec = inode->i_security;
1729
Linus Torvalds19e49832013-10-04 12:54:11 -07001730 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731}
1732
1733/* Same as inode_has_perm, but pass explicit audit data containing
1734 the dentry to help the auditing code to more easily generate the
1735 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001736static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 struct dentry *dentry,
1738 u32 av)
1739{
David Howellsc6f493d2015-03-17 22:26:22 +00001740 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001741 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001742
Eric Paris50c205f2012-04-04 15:01:43 -04001743 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001744 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001745 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001746 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001747}
1748
1749/* Same as inode_has_perm, but pass explicit audit data containing
1750 the path to help the auditing code to more easily generate the
1751 pathname if needed. */
1752static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001753 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001754 u32 av)
1755{
David Howellsc6f493d2015-03-17 22:26:22 +00001756 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001757 struct common_audit_data ad;
1758
Eric Paris50c205f2012-04-04 15:01:43 -04001759 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001760 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001761 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001762 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763}
1764
David Howells13f8e982013-06-13 23:37:55 +01001765/* Same as path_has_perm, but uses the inode from the file struct. */
1766static inline int file_path_has_perm(const struct cred *cred,
1767 struct file *file,
1768 u32 av)
1769{
1770 struct common_audit_data ad;
1771
Vivek Goyal43af5de2016-09-09 11:37:49 -04001772 ad.type = LSM_AUDIT_DATA_FILE;
1773 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001774 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001775}
1776
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777/* Check whether a task can use an open file descriptor to
1778 access an inode in a given way. Check access to the
1779 descriptor itself, and then use dentry_has_perm to
1780 check a particular permission to the file.
1781 Access to the descriptor is implicitly granted if it
1782 has the same SID as the process. If av is zero, then
1783 access to the file is not checked, e.g. for cases
1784 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001785static int file_has_perm(const struct cred *cred,
1786 struct file *file,
1787 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001790 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001791 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001792 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 int rc;
1794
Vivek Goyal43af5de2016-09-09 11:37:49 -04001795 ad.type = LSM_AUDIT_DATA_FILE;
1796 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
David Howells275bb412008-11-14 10:39:19 +11001798 if (sid != fsec->sid) {
1799 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 SECCLASS_FD,
1801 FD__USE,
1802 &ad);
1803 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001804 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 }
1806
1807 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001808 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001810 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
David Howells88e67f32008-11-14 10:39:21 +11001812out:
1813 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814}
1815
David Howellsc3c188b2015-07-10 17:19:58 -04001816/*
1817 * Determine the label for an inode that might be unioned.
1818 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001819static int
1820selinux_determine_inode_label(const struct task_security_struct *tsec,
1821 struct inode *dir,
1822 const struct qstr *name, u16 tclass,
1823 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001824{
1825 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001826
1827 if ((sbsec->flags & SE_SBINITIALIZED) &&
1828 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1829 *_new_isid = sbsec->mntpoint_sid;
1830 } else if ((sbsec->flags & SBLABEL_MNT) &&
1831 tsec->create_sid) {
1832 *_new_isid = tsec->create_sid;
1833 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001834 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001835 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1836 name, _new_isid);
1837 }
1838
1839 return 0;
1840}
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842/* Check whether a task can create a file. */
1843static int may_create(struct inode *dir,
1844 struct dentry *dentry,
1845 u16 tclass)
1846{
Paul Moore5fb49872010-04-22 14:46:19 -04001847 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 struct inode_security_struct *dsec;
1849 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001850 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001851 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 int rc;
1853
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001854 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 sbsec = dir->i_sb->s_security;
1856
David Howells275bb412008-11-14 10:39:19 +11001857 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001858
Eric Paris50c205f2012-04-04 15:01:43 -04001859 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001860 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
David Howells275bb412008-11-14 10:39:19 +11001862 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 DIR__ADD_NAME | DIR__SEARCH,
1864 &ad);
1865 if (rc)
1866 return rc;
1867
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001868 rc = selinux_determine_inode_label(current_security(), dir,
1869 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001870 if (rc)
1871 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
David Howells275bb412008-11-14 10:39:19 +11001873 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if (rc)
1875 return rc;
1876
1877 return avc_has_perm(newsid, sbsec->sid,
1878 SECCLASS_FILESYSTEM,
1879 FILESYSTEM__ASSOCIATE, &ad);
1880}
1881
Michael LeMay4eb582c2006-06-26 00:24:57 -07001882/* Check whether a task can create a key. */
1883static int may_create_key(u32 ksid,
1884 struct task_struct *ctx)
1885{
David Howells275bb412008-11-14 10:39:19 +11001886 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001887
David Howells275bb412008-11-14 10:39:19 +11001888 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001889}
1890
Eric Paris828dfe12008-04-17 13:17:49 -04001891#define MAY_LINK 0
1892#define MAY_UNLINK 1
1893#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
1895/* Check whether a task can link, unlink, or rmdir a file/directory. */
1896static int may_link(struct inode *dir,
1897 struct dentry *dentry,
1898 int kind)
1899
1900{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001902 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001903 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 u32 av;
1905 int rc;
1906
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001907 dsec = inode_security(dir);
1908 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
Eric Paris50c205f2012-04-04 15:01:43 -04001910 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001911 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 av = DIR__SEARCH;
1914 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001915 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 if (rc)
1917 return rc;
1918
1919 switch (kind) {
1920 case MAY_LINK:
1921 av = FILE__LINK;
1922 break;
1923 case MAY_UNLINK:
1924 av = FILE__UNLINK;
1925 break;
1926 case MAY_RMDIR:
1927 av = DIR__RMDIR;
1928 break;
1929 default:
Eric Paris744ba352008-04-17 11:52:44 -04001930 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1931 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 return 0;
1933 }
1934
David Howells275bb412008-11-14 10:39:19 +11001935 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 return rc;
1937}
1938
1939static inline int may_rename(struct inode *old_dir,
1940 struct dentry *old_dentry,
1941 struct inode *new_dir,
1942 struct dentry *new_dentry)
1943{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001945 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001946 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 u32 av;
1948 int old_is_dir, new_is_dir;
1949 int rc;
1950
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001951 old_dsec = inode_security(old_dir);
1952 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001953 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001954 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Eric Paris50c205f2012-04-04 15:01:43 -04001956 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
Eric Parisa2694342011-04-25 13:10:27 -04001958 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001959 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1961 if (rc)
1962 return rc;
David Howells275bb412008-11-14 10:39:19 +11001963 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 old_isec->sclass, FILE__RENAME, &ad);
1965 if (rc)
1966 return rc;
1967 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001968 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 old_isec->sclass, DIR__REPARENT, &ad);
1970 if (rc)
1971 return rc;
1972 }
1973
Eric Parisa2694342011-04-25 13:10:27 -04001974 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001976 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001978 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 if (rc)
1980 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001981 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001982 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001983 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001984 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 new_isec->sclass,
1986 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1987 if (rc)
1988 return rc;
1989 }
1990
1991 return 0;
1992}
1993
1994/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001995static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 struct super_block *sb,
1997 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001998 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11002001 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11002004 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005}
2006
2007/* Convert a Linux mode and permission mask to an access vector. */
2008static inline u32 file_mask_to_av(int mode, int mask)
2009{
2010 u32 av = 0;
2011
Al Virodba19c62011-07-25 20:49:29 -04002012 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 if (mask & MAY_EXEC)
2014 av |= FILE__EXECUTE;
2015 if (mask & MAY_READ)
2016 av |= FILE__READ;
2017
2018 if (mask & MAY_APPEND)
2019 av |= FILE__APPEND;
2020 else if (mask & MAY_WRITE)
2021 av |= FILE__WRITE;
2022
2023 } else {
2024 if (mask & MAY_EXEC)
2025 av |= DIR__SEARCH;
2026 if (mask & MAY_WRITE)
2027 av |= DIR__WRITE;
2028 if (mask & MAY_READ)
2029 av |= DIR__READ;
2030 }
2031
2032 return av;
2033}
2034
2035/* Convert a Linux file to an access vector. */
2036static inline u32 file_to_av(struct file *file)
2037{
2038 u32 av = 0;
2039
2040 if (file->f_mode & FMODE_READ)
2041 av |= FILE__READ;
2042 if (file->f_mode & FMODE_WRITE) {
2043 if (file->f_flags & O_APPEND)
2044 av |= FILE__APPEND;
2045 else
2046 av |= FILE__WRITE;
2047 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002048 if (!av) {
2049 /*
2050 * Special file opened with flags 3 for ioctl-only use.
2051 */
2052 av = FILE__IOCTL;
2053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
2055 return av;
2056}
2057
Eric Paris8b6a5a32008-10-29 17:06:46 -04002058/*
2059 * Convert a file to an access vector and include the correct open
2060 * open permission.
2061 */
2062static inline u32 open_file_to_av(struct file *file)
2063{
2064 u32 av = file_to_av(file);
2065
Eric Paris49b7b8d2010-07-23 11:44:09 -04002066 if (selinux_policycap_openperm)
2067 av |= FILE__OPEN;
2068
Eric Paris8b6a5a32008-10-29 17:06:46 -04002069 return av;
2070}
2071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072/* Hook functions begin here. */
2073
Stephen Smalley79af7302015-01-21 10:54:10 -05002074static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2075{
2076 u32 mysid = current_sid();
2077 u32 mgrsid = task_sid(mgr);
2078
2079 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
2080 BINDER__SET_CONTEXT_MGR, NULL);
2081}
2082
2083static int selinux_binder_transaction(struct task_struct *from,
2084 struct task_struct *to)
2085{
2086 u32 mysid = current_sid();
2087 u32 fromsid = task_sid(from);
2088 u32 tosid = task_sid(to);
2089 int rc;
2090
2091 if (mysid != fromsid) {
2092 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2093 BINDER__IMPERSONATE, NULL);
2094 if (rc)
2095 return rc;
2096 }
2097
2098 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2099 NULL);
2100}
2101
2102static int selinux_binder_transfer_binder(struct task_struct *from,
2103 struct task_struct *to)
2104{
2105 u32 fromsid = task_sid(from);
2106 u32 tosid = task_sid(to);
2107
2108 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2109 NULL);
2110}
2111
2112static int selinux_binder_transfer_file(struct task_struct *from,
2113 struct task_struct *to,
2114 struct file *file)
2115{
2116 u32 sid = task_sid(to);
2117 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002118 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002119 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002120 struct common_audit_data ad;
2121 int rc;
2122
2123 ad.type = LSM_AUDIT_DATA_PATH;
2124 ad.u.path = file->f_path;
2125
2126 if (sid != fsec->sid) {
2127 rc = avc_has_perm(sid, fsec->sid,
2128 SECCLASS_FD,
2129 FD__USE,
2130 &ad);
2131 if (rc)
2132 return rc;
2133 }
2134
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002135 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002136 return 0;
2137
Paul Moore20cdef82016-04-04 14:14:42 -04002138 isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002139 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2140 &ad);
2141}
2142
Ingo Molnar9e488582009-05-07 19:26:19 +10002143static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002144 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145{
Eric Paris69f594a2012-01-03 12:25:15 -05002146 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002147 u32 sid = current_sid();
2148 u32 csid = task_sid(child);
2149 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002150 }
2151
David Howells3b11a1d2008-11-14 10:39:26 +11002152 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002153}
2154
2155static int selinux_ptrace_traceme(struct task_struct *parent)
2156{
David Howells5cd9c582008-08-14 11:37:28 +01002157 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158}
2159
2160static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002161 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002163 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164}
2165
David Howellsd84f4f92008-11-14 10:39:23 +11002166static int selinux_capset(struct cred *new, const struct cred *old,
2167 const kernel_cap_t *effective,
2168 const kernel_cap_t *inheritable,
2169 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170{
David Howellsd84f4f92008-11-14 10:39:23 +11002171 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172}
2173
James Morris5626d3e2009-01-30 10:05:06 +11002174/*
2175 * (This comment used to live with the selinux_task_setuid hook,
2176 * which was removed).
2177 *
2178 * Since setuid only affects the current process, and since the SELinux
2179 * controls are not based on the Linux identity attributes, SELinux does not
2180 * need to control this operation. However, SELinux does control the use of
2181 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2182 */
2183
Eric Paris6a9de492012-01-03 12:25:14 -05002184static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2185 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002187 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188}
2189
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2191{
David Howells88e67f32008-11-14 10:39:21 +11002192 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 int rc = 0;
2194
2195 if (!sb)
2196 return 0;
2197
2198 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002199 case Q_SYNC:
2200 case Q_QUOTAON:
2201 case Q_QUOTAOFF:
2202 case Q_SETINFO:
2203 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002204 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002205 break;
2206 case Q_GETFMT:
2207 case Q_GETINFO:
2208 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002209 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002210 break;
2211 default:
2212 rc = 0; /* let the kernel handle invalid cmds */
2213 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215 return rc;
2216}
2217
2218static int selinux_quota_on(struct dentry *dentry)
2219{
David Howells88e67f32008-11-14 10:39:21 +11002220 const struct cred *cred = current_cred();
2221
Eric Paris2875fa02011-04-28 16:04:24 -04002222 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223}
2224
Eric Paris12b30522010-11-15 18:36:29 -05002225static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226{
2227 int rc;
2228
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002230 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2231 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002232 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2233 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002234 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2235 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2236 /* Set level of messages printed to console */
2237 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002238 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2239 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002240 case SYSLOG_ACTION_CLOSE: /* Close log */
2241 case SYSLOG_ACTION_OPEN: /* Open log */
2242 case SYSLOG_ACTION_READ: /* Read from log */
2243 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2244 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002245 default:
2246 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2247 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 }
2249 return rc;
2250}
2251
2252/*
2253 * Check that a process has enough memory to allocate a new virtual
2254 * mapping. 0 means there is enough memory for the allocation to
2255 * succeed and -ENOMEM implies there is not.
2256 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 * Do not audit the selinux permission check, as this is applied to all
2258 * processes that allocate mappings.
2259 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002260static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261{
2262 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002264 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002265 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 if (rc == 0)
2267 cap_sys_admin = 1;
2268
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002269 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270}
2271
2272/* binprm security operations */
2273
Paul Moore0c6181c2016-03-30 21:41:21 -04002274static u32 ptrace_parent_sid(struct task_struct *task)
2275{
2276 u32 sid = 0;
2277 struct task_struct *tracer;
2278
2279 rcu_read_lock();
2280 tracer = ptrace_parent(task);
2281 if (tracer)
2282 sid = task_sid(tracer);
2283 rcu_read_unlock();
2284
2285 return sid;
2286}
2287
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002288static int check_nnp_nosuid(const struct linux_binprm *bprm,
2289 const struct task_security_struct *old_tsec,
2290 const struct task_security_struct *new_tsec)
2291{
2292 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002293 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002294 int rc;
2295
2296 if (!nnp && !nosuid)
2297 return 0; /* neither NNP nor nosuid */
2298
2299 if (new_tsec->sid == old_tsec->sid)
2300 return 0; /* No change in credentials */
2301
2302 /*
2303 * The only transitions we permit under NNP or nosuid
2304 * are transitions to bounded SIDs, i.e. SIDs that are
2305 * guaranteed to only be allowed a subset of the permissions
2306 * of the current SID.
2307 */
2308 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2309 if (rc) {
2310 /*
2311 * On failure, preserve the errno values for NNP vs nosuid.
2312 * NNP: Operation not permitted for caller.
2313 * nosuid: Permission denied to file.
2314 */
2315 if (nnp)
2316 return -EPERM;
2317 else
2318 return -EACCES;
2319 }
2320 return 0;
2321}
2322
David Howellsa6f76f22008-11-14 10:39:24 +11002323static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324{
David Howellsa6f76f22008-11-14 10:39:24 +11002325 const struct task_security_struct *old_tsec;
2326 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002328 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002329 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 int rc;
2331
David Howellsa6f76f22008-11-14 10:39:24 +11002332 /* SELinux context only depends on initial program or script and not
2333 * the script interpreter */
2334 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 return 0;
2336
David Howellsa6f76f22008-11-14 10:39:24 +11002337 old_tsec = current_security();
2338 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002339 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
2341 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002342 new_tsec->sid = old_tsec->sid;
2343 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
Michael LeMay28eba5b2006-06-27 02:53:42 -07002345 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002346 new_tsec->create_sid = 0;
2347 new_tsec->keycreate_sid = 0;
2348 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
David Howellsa6f76f22008-11-14 10:39:24 +11002350 if (old_tsec->exec_sid) {
2351 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002353 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002354
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002355 /* Fail on NNP or nosuid if not an allowed transition. */
2356 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2357 if (rc)
2358 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 } else {
2360 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002361 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002362 SECCLASS_PROCESS, NULL,
2363 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 if (rc)
2365 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002366
2367 /*
2368 * Fallback to old SID on NNP or nosuid if not an allowed
2369 * transition.
2370 */
2371 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2372 if (rc)
2373 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 }
2375
Vivek Goyal43af5de2016-09-09 11:37:49 -04002376 ad.type = LSM_AUDIT_DATA_FILE;
2377 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
David Howellsa6f76f22008-11-14 10:39:24 +11002379 if (new_tsec->sid == old_tsec->sid) {
2380 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2382 if (rc)
2383 return rc;
2384 } else {
2385 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002386 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2388 if (rc)
2389 return rc;
2390
David Howellsa6f76f22008-11-14 10:39:24 +11002391 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2393 if (rc)
2394 return rc;
2395
David Howellsa6f76f22008-11-14 10:39:24 +11002396 /* Check for shared state */
2397 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2398 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2399 SECCLASS_PROCESS, PROCESS__SHARE,
2400 NULL);
2401 if (rc)
2402 return -EPERM;
2403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
David Howellsa6f76f22008-11-14 10:39:24 +11002405 /* Make sure that anyone attempting to ptrace over a task that
2406 * changes its SID has the appropriate permit */
2407 if (bprm->unsafe &
2408 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Paul Moore0c6181c2016-03-30 21:41:21 -04002409 u32 ptsid = ptrace_parent_sid(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002410 if (ptsid != 0) {
2411 rc = avc_has_perm(ptsid, new_tsec->sid,
2412 SECCLASS_PROCESS,
2413 PROCESS__PTRACE, NULL);
2414 if (rc)
2415 return -EPERM;
2416 }
2417 }
2418
2419 /* Clear any possibly unsafe personality bits on exec: */
2420 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
2422
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 return 0;
2424}
2425
Eric Paris828dfe12008-04-17 13:17:49 -04002426static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427{
Paul Moore5fb49872010-04-22 14:46:19 -04002428 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002429 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 int atsecure = 0;
2431
David Howells275bb412008-11-14 10:39:19 +11002432 sid = tsec->sid;
2433 osid = tsec->osid;
2434
2435 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 /* Enable secure mode for SIDs transitions unless
2437 the noatsecure permission is granted between
2438 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002439 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002440 SECCLASS_PROCESS,
2441 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 }
2443
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002444 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445}
2446
Al Viroc3c073f2012-08-21 22:32:06 -04002447static int match_file(const void *p, struct file *file, unsigned fd)
2448{
2449 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2450}
2451
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002453static inline void flush_unauthorized_files(const struct cred *cred,
2454 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002457 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002458 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002459 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002461 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002463 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002464 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002465 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002466
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002468 Use file_path_has_perm on the tty path directly
2469 rather than using file_has_perm, as this particular
2470 open file may belong to another process and we are
2471 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002472 file_priv = list_first_entry(&tty->tty_files,
2473 struct tty_file_private, list);
2474 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002475 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002476 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 }
Peter Hurley4a510962016-01-09 21:35:23 -08002478 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002479 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002481 /* Reset controlling tty. */
2482 if (drop_tty)
2483 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
2485 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002486 n = iterate_fd(files, 0, match_file, cred);
2487 if (!n) /* none found? */
2488 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Al Viroc3c073f2012-08-21 22:32:06 -04002490 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002491 if (IS_ERR(devnull))
2492 devnull = NULL;
2493 /* replace all the matching ones with this */
2494 do {
2495 replace_fd(n - 1, devnull, 0);
2496 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2497 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002498 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499}
2500
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501/*
David Howellsa6f76f22008-11-14 10:39:24 +11002502 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 */
David Howellsa6f76f22008-11-14 10:39:24 +11002504static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505{
David Howellsa6f76f22008-11-14 10:39:24 +11002506 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 int rc, i;
2509
David Howellsa6f76f22008-11-14 10:39:24 +11002510 new_tsec = bprm->cred->security;
2511 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 return;
2513
2514 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002515 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
David Howellsa6f76f22008-11-14 10:39:24 +11002517 /* Always clear parent death signal on SID transitions. */
2518 current->pdeath_signal = 0;
2519
2520 /* Check whether the new SID can inherit resource limits from the old
2521 * SID. If not, reset all soft limits to the lower of the current
2522 * task's hard limit and the init task's soft limit.
2523 *
2524 * Note that the setting of hard limits (even to lower them) can be
2525 * controlled by the setrlimit check. The inclusion of the init task's
2526 * soft limit into the computation is to avoid resetting soft limits
2527 * higher than the default soft limit for cases where the default is
2528 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2529 */
2530 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2531 PROCESS__RLIMITINH, NULL);
2532 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002533 /* protect against do_prlimit() */
2534 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002535 for (i = 0; i < RLIM_NLIMITS; i++) {
2536 rlim = current->signal->rlim + i;
2537 initrlim = init_task.signal->rlim + i;
2538 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2539 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002540 task_unlock(current);
2541 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002542 }
2543}
2544
2545/*
2546 * Clean up the process immediately after the installation of new credentials
2547 * due to exec
2548 */
2549static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2550{
2551 const struct task_security_struct *tsec = current_security();
2552 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002553 u32 osid, sid;
2554 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002555
David Howellsa6f76f22008-11-14 10:39:24 +11002556 osid = tsec->osid;
2557 sid = tsec->sid;
2558
2559 if (sid == osid)
2560 return;
2561
2562 /* Check whether the new SID can inherit signal state from the old SID.
2563 * If not, clear itimers to avoid subsequent signal generation and
2564 * flush and unblock signals.
2565 *
2566 * This must occur _after_ the task SID has been updated so that any
2567 * kill done after the flush will be checked against the new SID.
2568 */
2569 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 if (rc) {
2571 memset(&itimer, 0, sizeof itimer);
2572 for (i = 0; i < 3; i++)
2573 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002575 if (!fatal_signal_pending(current)) {
2576 flush_sigqueue(&current->pending);
2577 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002578 flush_signal_handlers(current, 1);
2579 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002580 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 spin_unlock_irq(&current->sighand->siglock);
2583 }
2584
David Howellsa6f76f22008-11-14 10:39:24 +11002585 /* Wake up the parent if it is waiting so that it can recheck
2586 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002587 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002588 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002589 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590}
2591
2592/* superblock security operations */
2593
2594static int selinux_sb_alloc_security(struct super_block *sb)
2595{
2596 return superblock_alloc_security(sb);
2597}
2598
2599static void selinux_sb_free_security(struct super_block *sb)
2600{
2601 superblock_free_security(sb);
2602}
2603
2604static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2605{
2606 if (plen > olen)
2607 return 0;
2608
2609 return !memcmp(prefix, option, plen);
2610}
2611
2612static inline int selinux_option(char *option, int len)
2613{
Eric Paris832cbd92008-04-01 13:24:09 -04002614 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2615 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2616 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002617 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2618 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619}
2620
2621static inline void take_option(char **to, char *from, int *first, int len)
2622{
2623 if (!*first) {
2624 **to = ',';
2625 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002626 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 *first = 0;
2628 memcpy(*to, from, len);
2629 *to += len;
2630}
2631
Eric Paris828dfe12008-04-17 13:17:49 -04002632static inline void take_selinux_option(char **to, char *from, int *first,
2633 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002634{
2635 int current_size = 0;
2636
2637 if (!*first) {
2638 **to = '|';
2639 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002640 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002641 *first = 0;
2642
2643 while (current_size < len) {
2644 if (*from != '"') {
2645 **to = *from;
2646 *to += 1;
2647 }
2648 from += 1;
2649 current_size += 1;
2650 }
2651}
2652
Eric Parise0007522008-03-05 10:31:54 -05002653static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654{
2655 int fnosec, fsec, rc = 0;
2656 char *in_save, *in_curr, *in_end;
2657 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002658 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
2660 in_curr = orig;
2661 sec_curr = copy;
2662
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2664 if (!nosec) {
2665 rc = -ENOMEM;
2666 goto out;
2667 }
2668
2669 nosec_save = nosec;
2670 fnosec = fsec = 1;
2671 in_save = in_end = orig;
2672
2673 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002674 if (*in_end == '"')
2675 open_quote = !open_quote;
2676 if ((*in_end == ',' && open_quote == 0) ||
2677 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 int len = in_end - in_curr;
2679
2680 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002681 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 else
2683 take_option(&nosec, in_curr, &fnosec, len);
2684
2685 in_curr = in_end + 1;
2686 }
2687 } while (*in_end++);
2688
Eric Paris6931dfc2005-06-30 02:58:51 -07002689 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002690 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691out:
2692 return rc;
2693}
2694
Eric Paris026eb162011-03-03 16:09:14 -05002695static int selinux_sb_remount(struct super_block *sb, void *data)
2696{
2697 int rc, i, *flags;
2698 struct security_mnt_opts opts;
2699 char *secdata, **mount_options;
2700 struct superblock_security_struct *sbsec = sb->s_security;
2701
2702 if (!(sbsec->flags & SE_SBINITIALIZED))
2703 return 0;
2704
2705 if (!data)
2706 return 0;
2707
2708 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2709 return 0;
2710
2711 security_init_mnt_opts(&opts);
2712 secdata = alloc_secdata();
2713 if (!secdata)
2714 return -ENOMEM;
2715 rc = selinux_sb_copy_data(data, secdata);
2716 if (rc)
2717 goto out_free_secdata;
2718
2719 rc = selinux_parse_opts_str(secdata, &opts);
2720 if (rc)
2721 goto out_free_secdata;
2722
2723 mount_options = opts.mnt_opts;
2724 flags = opts.mnt_opts_flags;
2725
2726 for (i = 0; i < opts.num_mnt_opts; i++) {
2727 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002728
Eric Paris12f348b2012-10-09 10:56:25 -04002729 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002730 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002731 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002732 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002733 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002734 "(%s) failed for (dev %s, type %s) errno=%d\n",
2735 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002736 goto out_free_opts;
2737 }
2738 rc = -EINVAL;
2739 switch (flags[i]) {
2740 case FSCONTEXT_MNT:
2741 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2742 goto out_bad_option;
2743 break;
2744 case CONTEXT_MNT:
2745 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2746 goto out_bad_option;
2747 break;
2748 case ROOTCONTEXT_MNT: {
2749 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002750 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002751
2752 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2753 goto out_bad_option;
2754 break;
2755 }
2756 case DEFCONTEXT_MNT:
2757 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2758 goto out_bad_option;
2759 break;
2760 default:
2761 goto out_free_opts;
2762 }
2763 }
2764
2765 rc = 0;
2766out_free_opts:
2767 security_free_mnt_opts(&opts);
2768out_free_secdata:
2769 free_secdata(secdata);
2770 return rc;
2771out_bad_option:
2772 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002773 "during remount (dev %s, type=%s)\n", sb->s_id,
2774 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002775 goto out_free_opts;
2776}
2777
James Morris12204e22008-12-19 10:44:42 +11002778static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779{
David Howells88e67f32008-11-14 10:39:21 +11002780 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002781 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 int rc;
2783
2784 rc = superblock_doinit(sb, data);
2785 if (rc)
2786 return rc;
2787
James Morris74192242008-12-19 11:41:10 +11002788 /* Allow all mounts performed by the kernel */
2789 if (flags & MS_KERNMOUNT)
2790 return 0;
2791
Eric Paris50c205f2012-04-04 15:01:43 -04002792 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002793 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002794 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795}
2796
David Howells726c3342006-06-23 02:02:58 -07002797static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
David Howells88e67f32008-11-14 10:39:21 +11002799 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002800 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
Eric Paris50c205f2012-04-04 15:01:43 -04002802 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002803 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002804 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805}
2806
Al Viro808d4e32012-10-11 11:42:01 -04002807static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002808 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002809 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002810 unsigned long flags,
2811 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
David Howells88e67f32008-11-14 10:39:21 +11002813 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
2815 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002816 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002817 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 else
Eric Paris2875fa02011-04-28 16:04:24 -04002819 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820}
2821
2822static int selinux_umount(struct vfsmount *mnt, int flags)
2823{
David Howells88e67f32008-11-14 10:39:21 +11002824 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
David Howells88e67f32008-11-14 10:39:21 +11002826 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002827 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828}
2829
2830/* inode security operations */
2831
2832static int selinux_inode_alloc_security(struct inode *inode)
2833{
2834 return inode_alloc_security(inode);
2835}
2836
2837static void selinux_inode_free_security(struct inode *inode)
2838{
2839 inode_free_security(inode);
2840}
2841
David Quigleyd47be3d2013-05-22 12:50:34 -04002842static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002843 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002844 u32 *ctxlen)
2845{
David Quigleyd47be3d2013-05-22 12:50:34 -04002846 u32 newsid;
2847 int rc;
2848
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002849 rc = selinux_determine_inode_label(current_security(),
2850 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002851 inode_mode_to_security_class(mode),
2852 &newsid);
2853 if (rc)
2854 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002855
2856 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2857}
2858
Vivek Goyala518b0a2016-07-13 10:44:53 -04002859static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2860 struct qstr *name,
2861 const struct cred *old,
2862 struct cred *new)
2863{
2864 u32 newsid;
2865 int rc;
2866 struct task_security_struct *tsec;
2867
2868 rc = selinux_determine_inode_label(old->security,
2869 d_inode(dentry->d_parent), name,
2870 inode_mode_to_security_class(mode),
2871 &newsid);
2872 if (rc)
2873 return rc;
2874
2875 tsec = new->security;
2876 tsec->create_sid = newsid;
2877 return 0;
2878}
2879
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002880static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002881 const struct qstr *qstr,
2882 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002883 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002884{
Paul Moore5fb49872010-04-22 14:46:19 -04002885 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002886 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002887 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002888 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002889 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002890
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002891 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002892
David Howells275bb412008-11-14 10:39:19 +11002893 sid = tsec->sid;
2894 newsid = tsec->create_sid;
2895
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002896 rc = selinux_determine_inode_label(current_security(),
David Howellsc3c188b2015-07-10 17:19:58 -04002897 dir, qstr,
2898 inode_mode_to_security_class(inode->i_mode),
2899 &newsid);
2900 if (rc)
2901 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002902
Eric Paris296fddf2006-09-25 23:32:00 -07002903 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002904 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002905 struct inode_security_struct *isec = inode->i_security;
2906 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2907 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002908 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002909 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002910
Eric Paris12f348b2012-10-09 10:56:25 -04002911 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002912 return -EOPNOTSUPP;
2913
Tetsuo Handa95489062013-07-25 05:44:02 +09002914 if (name)
2915 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002916
2917 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002918 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002919 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002920 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002921 *value = context;
2922 *len = clen;
2923 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002924
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002925 return 0;
2926}
2927
Al Viro4acdaf22011-07-26 01:42:34 -04002928static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929{
2930 return may_create(dir, dentry, SECCLASS_FILE);
2931}
2932
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2934{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 return may_link(dir, old_dentry, MAY_LINK);
2936}
2937
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2939{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 return may_link(dir, dentry, MAY_UNLINK);
2941}
2942
2943static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2944{
2945 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2946}
2947
Al Viro18bb1db2011-07-26 01:41:39 -04002948static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949{
2950 return may_create(dir, dentry, SECCLASS_DIR);
2951}
2952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2954{
2955 return may_link(dir, dentry, MAY_RMDIR);
2956}
2957
Al Viro1a67aaf2011-07-26 01:52:52 -04002958static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2961}
2962
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002964 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965{
2966 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2967}
2968
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969static int selinux_inode_readlink(struct dentry *dentry)
2970{
David Howells88e67f32008-11-14 10:39:21 +11002971 const struct cred *cred = current_cred();
2972
Eric Paris2875fa02011-04-28 16:04:24 -04002973 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974}
2975
NeilBrownbda0be72015-03-23 13:37:39 +11002976static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2977 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978{
David Howells88e67f32008-11-14 10:39:21 +11002979 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002980 struct common_audit_data ad;
2981 struct inode_security_struct *isec;
2982 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
NeilBrownbda0be72015-03-23 13:37:39 +11002984 validate_creds(cred);
2985
2986 ad.type = LSM_AUDIT_DATA_DENTRY;
2987 ad.u.dentry = dentry;
2988 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002989 isec = inode_security_rcu(inode, rcu);
2990 if (IS_ERR(isec))
2991 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002992
2993 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2994 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995}
2996
Eric Parisd4cf970d2012-04-04 15:01:42 -04002997static noinline int audit_inode_permission(struct inode *inode,
2998 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002999 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04003000 unsigned flags)
3001{
3002 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003003 struct inode_security_struct *isec = inode->i_security;
3004 int rc;
3005
Eric Paris50c205f2012-04-04 15:01:43 -04003006 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04003007 ad.u.inode = inode;
3008
3009 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07003010 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003011 if (rc)
3012 return rc;
3013 return 0;
3014}
3015
Al Viroe74f71e2011-06-20 19:38:15 -04003016static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
David Howells88e67f32008-11-14 10:39:21 +11003018 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003019 u32 perms;
3020 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04003021 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003022 struct inode_security_struct *isec;
3023 u32 sid;
3024 struct av_decision avd;
3025 int rc, rc2;
3026 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
Eric Parisb782e0a2010-07-23 11:44:03 -04003028 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003029 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3030
Eric Parisb782e0a2010-07-23 11:44:03 -04003031 /* No permission to check. Existence test. */
3032 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
Eric Paris2e334052012-04-04 15:01:42 -04003035 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003036
Eric Paris2e334052012-04-04 15:01:42 -04003037 if (unlikely(IS_PRIVATE(inode)))
3038 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003039
3040 perms = file_mask_to_av(inode->i_mode, mask);
3041
Eric Paris2e334052012-04-04 15:01:42 -04003042 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003043 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
3044 if (IS_ERR(isec))
3045 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003046
3047 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
3048 audited = avc_audit_required(perms, &avd, rc,
3049 from_access ? FILE__AUDIT_ACCESS : 0,
3050 &denied);
3051 if (likely(!audited))
3052 return rc;
3053
Stephen Smalley626b9742014-04-29 11:29:04 -07003054 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04003055 if (rc2)
3056 return rc2;
3057 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058}
3059
3060static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3061{
David Howells88e67f32008-11-14 10:39:21 +11003062 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003063 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003064 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003066 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3067 if (ia_valid & ATTR_FORCE) {
3068 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3069 ATTR_FORCE);
3070 if (!ia_valid)
3071 return 0;
3072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003074 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3075 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003076 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077
Jeff Vander Stoep44d37ad2015-10-21 17:44:25 -04003078 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
3079 && !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003080 av |= FILE__OPEN;
3081
3082 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083}
3084
Al Viro3f7036a2015-03-08 19:28:30 -04003085static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086{
Al Viro3f7036a2015-03-08 19:28:30 -04003087 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088}
3089
David Howells8f0cfa52008-04-29 00:59:41 -07003090static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07003091{
David Howells88e67f32008-11-14 10:39:21 +11003092 const struct cred *cred = current_cred();
3093
Serge E. Hallynb5376772007-10-16 23:31:36 -07003094 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3095 sizeof XATTR_SECURITY_PREFIX - 1)) {
3096 if (!strcmp(name, XATTR_NAME_CAPS)) {
3097 if (!capable(CAP_SETFCAP))
3098 return -EPERM;
3099 } else if (!capable(CAP_SYS_ADMIN)) {
3100 /* A different attribute in the security namespace.
3101 Restrict to administrator. */
3102 return -EPERM;
3103 }
3104 }
3105
3106 /* Not an attribute we recognize, so just check the
3107 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04003108 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003109}
3110
David Howells8f0cfa52008-04-29 00:59:41 -07003111static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3112 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113{
David Howellsc6f493d2015-03-17 22:26:22 +00003114 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003115 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003117 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003118 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 int rc = 0;
3120
Serge E. Hallynb5376772007-10-16 23:31:36 -07003121 if (strcmp(name, XATTR_NAME_SELINUX))
3122 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
3124 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003125 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 return -EOPNOTSUPP;
3127
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003128 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 return -EPERM;
3130
Eric Paris50c205f2012-04-04 15:01:43 -04003131 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003132 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
Paul Moore20cdef82016-04-04 14:14:42 -04003134 isec = backing_inode_security(dentry);
David Howells275bb412008-11-14 10:39:19 +11003135 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 FILE__RELABELFROM, &ad);
3137 if (rc)
3138 return rc;
3139
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003140 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003141 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003142 if (!capable(CAP_MAC_ADMIN)) {
3143 struct audit_buffer *ab;
3144 size_t audit_size;
3145 const char *str;
3146
3147 /* We strip a nul only if it is at the end, otherwise the
3148 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003149 if (value) {
3150 str = value;
3151 if (str[size - 1] == '\0')
3152 audit_size = size - 1;
3153 else
3154 audit_size = size;
3155 } else {
3156 str = "";
3157 audit_size = 0;
3158 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003159 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3160 audit_log_format(ab, "op=setxattr invalid_context=");
3161 audit_log_n_untrustedstring(ab, value, audit_size);
3162 audit_log_end(ab);
3163
Stephen Smalley12b29f32008-05-07 13:03:20 -04003164 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003165 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003166 rc = security_context_to_sid_force(value, size, &newsid);
3167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 if (rc)
3169 return rc;
3170
David Howells275bb412008-11-14 10:39:19 +11003171 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 FILE__RELABELTO, &ad);
3173 if (rc)
3174 return rc;
3175
David Howells275bb412008-11-14 10:39:19 +11003176 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003177 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 if (rc)
3179 return rc;
3180
3181 return avc_has_perm(newsid,
3182 sbsec->sid,
3183 SECCLASS_FILESYSTEM,
3184 FILESYSTEM__ASSOCIATE,
3185 &ad);
3186}
3187
David Howells8f0cfa52008-04-29 00:59:41 -07003188static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003189 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003190 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191{
David Howellsc6f493d2015-03-17 22:26:22 +00003192 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003193 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 u32 newsid;
3195 int rc;
3196
3197 if (strcmp(name, XATTR_NAME_SELINUX)) {
3198 /* Not an attribute we recognize, so nothing to do. */
3199 return;
3200 }
3201
Stephen Smalley12b29f32008-05-07 13:03:20 -04003202 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003204 printk(KERN_ERR "SELinux: unable to map context to SID"
3205 "for (%s, %lu), rc=%d\n",
3206 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 return;
3208 }
3209
Paul Moore20cdef82016-04-04 14:14:42 -04003210 isec = backing_inode_security(dentry);
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003211 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003212 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003214 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003215 spin_unlock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003216
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 return;
3218}
3219
David Howells8f0cfa52008-04-29 00:59:41 -07003220static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221{
David Howells88e67f32008-11-14 10:39:21 +11003222 const struct cred *cred = current_cred();
3223
Eric Paris2875fa02011-04-28 16:04:24 -04003224 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225}
3226
Eric Paris828dfe12008-04-17 13:17:49 -04003227static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228{
David Howells88e67f32008-11-14 10:39:21 +11003229 const struct cred *cred = current_cred();
3230
Eric Paris2875fa02011-04-28 16:04:24 -04003231 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232}
3233
David Howells8f0cfa52008-04-29 00:59:41 -07003234static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003236 if (strcmp(name, XATTR_NAME_SELINUX))
3237 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238
3239 /* No one is allowed to remove a SELinux security label.
3240 You can change the label, but all data must be labeled. */
3241 return -EACCES;
3242}
3243
James Morrisd381d8a2005-10-30 14:59:22 -08003244/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003245 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003246 *
3247 * Permission check is handled by selinux_inode_getxattr hook.
3248 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003249static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250{
David P. Quigley42492592008-02-04 22:29:39 -08003251 u32 size;
3252 int error;
3253 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003254 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003256 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3257 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003259 /*
3260 * If the caller has CAP_MAC_ADMIN, then get the raw context
3261 * value even if it is not defined by current policy; otherwise,
3262 * use the in-core value under current policy.
3263 * Use the non-auditing forms of the permission checks since
3264 * getxattr may be called by unprivileged processes commonly
3265 * and lack of permission just means that we fall back to the
3266 * in-core context value, not a denial.
3267 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003268 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3269 SECURITY_CAP_NOAUDIT);
3270 if (!error)
3271 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003272 SECURITY_CAP_NOAUDIT, true);
Paul Moore20cdef82016-04-04 14:14:42 -04003273 isec = inode_security(inode);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003274 if (!error)
3275 error = security_sid_to_context_force(isec->sid, &context,
3276 &size);
3277 else
3278 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003279 if (error)
3280 return error;
3281 error = size;
3282 if (alloc) {
3283 *buffer = context;
3284 goto out_nofree;
3285 }
3286 kfree(context);
3287out_nofree:
3288 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289}
3290
3291static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003292 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293{
Paul Moore2c971652016-04-19 16:36:28 -04003294 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295 u32 newsid;
3296 int rc;
3297
3298 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3299 return -EOPNOTSUPP;
3300
3301 if (!value || !size)
3302 return -EACCES;
3303
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003304 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 if (rc)
3306 return rc;
3307
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003308 spin_lock(&isec->lock);
David Quigleyaa9c2662013-05-22 12:50:44 -04003309 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003311 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003312 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 return 0;
3314}
3315
3316static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3317{
3318 const int len = sizeof(XATTR_NAME_SELINUX);
3319 if (buffer && len <= buffer_size)
3320 memcpy(buffer, XATTR_NAME_SELINUX, len);
3321 return len;
3322}
3323
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003324static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003325{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003326 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003327 *secid = isec->sid;
3328}
3329
Vivek Goyal56909eb2016-07-13 10:44:48 -04003330static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3331{
3332 u32 sid;
3333 struct task_security_struct *tsec;
3334 struct cred *new_creds = *new;
3335
3336 if (new_creds == NULL) {
3337 new_creds = prepare_creds();
3338 if (!new_creds)
3339 return -ENOMEM;
3340 }
3341
3342 tsec = new_creds->security;
3343 /* Get label from overlay inode and set it in create_sid */
3344 selinux_inode_getsecid(d_inode(src), &sid);
3345 tsec->create_sid = sid;
3346 *new = new_creds;
3347 return 0;
3348}
3349
Vivek Goyal19472b62016-07-13 10:44:50 -04003350static int selinux_inode_copy_up_xattr(const char *name)
3351{
3352 /* The copy_up hook above sets the initial context on an inode, but we
3353 * don't then want to overwrite it by blindly copying all the lower
3354 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3355 */
3356 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3357 return 1; /* Discard */
3358 /*
3359 * Any other attribute apart from SELINUX is not claimed, supported
3360 * by selinux.
3361 */
3362 return -EOPNOTSUPP;
3363}
3364
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365/* file security operations */
3366
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003367static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
David Howells88e67f32008-11-14 10:39:21 +11003369 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003370 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3373 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3374 mask |= MAY_APPEND;
3375
Paul Moore389fb8002009-03-27 17:10:34 -04003376 return file_has_perm(cred, file,
3377 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378}
3379
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003380static int selinux_file_permission(struct file *file, int mask)
3381{
Al Viro496ad9a2013-01-23 17:07:38 -05003382 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003383 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003384 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003385 u32 sid = current_sid();
3386
Paul Moore389fb8002009-03-27 17:10:34 -04003387 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003388 /* No permission to check. Existence test. */
3389 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003390
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003391 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003392 if (sid == fsec->sid && fsec->isid == isec->sid &&
3393 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003394 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003395 return 0;
3396
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003397 return selinux_revalidate_file_permission(file, mask);
3398}
3399
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400static int selinux_file_alloc_security(struct file *file)
3401{
3402 return file_alloc_security(file);
3403}
3404
3405static void selinux_file_free_security(struct file *file)
3406{
3407 file_free_security(file);
3408}
3409
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003410/*
3411 * Check whether a task has the ioctl permission and cmd
3412 * operation to an inode.
3413 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003414static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003415 u32 requested, u16 cmd)
3416{
3417 struct common_audit_data ad;
3418 struct file_security_struct *fsec = file->f_security;
3419 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003420 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003421 struct lsm_ioctlop_audit ioctl;
3422 u32 ssid = cred_sid(cred);
3423 int rc;
3424 u8 driver = cmd >> 8;
3425 u8 xperm = cmd & 0xff;
3426
3427 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3428 ad.u.op = &ioctl;
3429 ad.u.op->cmd = cmd;
3430 ad.u.op->path = file->f_path;
3431
3432 if (ssid != fsec->sid) {
3433 rc = avc_has_perm(ssid, fsec->sid,
3434 SECCLASS_FD,
3435 FD__USE,
3436 &ad);
3437 if (rc)
3438 goto out;
3439 }
3440
3441 if (unlikely(IS_PRIVATE(inode)))
3442 return 0;
3443
Paul Moore20cdef82016-04-04 14:14:42 -04003444 isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003445 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3446 requested, driver, xperm, &ad);
3447out:
3448 return rc;
3449}
3450
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3452 unsigned long arg)
3453{
David Howells88e67f32008-11-14 10:39:21 +11003454 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003455 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
Eric Paris0b24dcb2011-02-25 15:39:20 -05003457 switch (cmd) {
3458 case FIONREAD:
3459 /* fall through */
3460 case FIBMAP:
3461 /* fall through */
3462 case FIGETBSZ:
3463 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003464 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003465 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003466 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003467 error = file_has_perm(cred, file, FILE__GETATTR);
3468 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
Al Viro2f99c362012-03-23 16:04:05 -04003470 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003471 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003472 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003473 error = file_has_perm(cred, file, FILE__SETATTR);
3474 break;
3475
3476 /* sys_ioctl() checks */
3477 case FIONBIO:
3478 /* fall through */
3479 case FIOASYNC:
3480 error = file_has_perm(cred, file, 0);
3481 break;
3482
3483 case KDSKBENT:
3484 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003485 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003486 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003487 break;
3488
3489 /* default case assumes that the command will go
3490 * to the file's ioctl() function.
3491 */
3492 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003493 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003494 }
3495 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496}
3497
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003498static int default_noexec;
3499
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3501{
David Howells88e67f32008-11-14 10:39:21 +11003502 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003503 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003504
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003505 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003506 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3507 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508 /*
3509 * We are making executable an anonymous mapping or a
3510 * private file mapping that will also be writable.
3511 * This has an additional check.
3512 */
David Howellsd84f4f92008-11-14 10:39:23 +11003513 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003515 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517
3518 if (file) {
3519 /* read access is always possible with a mapping */
3520 u32 av = FILE__READ;
3521
3522 /* write access only matters if the mapping is shared */
3523 if (shared && (prot & PROT_WRITE))
3524 av |= FILE__WRITE;
3525
3526 if (prot & PROT_EXEC)
3527 av |= FILE__EXECUTE;
3528
David Howells88e67f32008-11-14 10:39:21 +11003529 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530 }
David Howellsd84f4f92008-11-14 10:39:23 +11003531
3532error:
3533 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534}
3535
Al Viroe5467852012-05-30 13:30:51 -04003536static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003538 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003539
3540 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3541 u32 sid = current_sid();
3542 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3543 MEMPROTECT__MMAP_ZERO, NULL);
3544 }
3545
3546 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003547}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548
Al Viroe5467852012-05-30 13:30:51 -04003549static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3550 unsigned long prot, unsigned long flags)
3551{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 if (selinux_checkreqprot)
3553 prot = reqprot;
3554
3555 return file_map_prot_check(file, prot,
3556 (flags & MAP_TYPE) == MAP_SHARED);
3557}
3558
3559static int selinux_file_mprotect(struct vm_area_struct *vma,
3560 unsigned long reqprot,
3561 unsigned long prot)
3562{
David Howells88e67f32008-11-14 10:39:21 +11003563 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
3565 if (selinux_checkreqprot)
3566 prot = reqprot;
3567
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003568 if (default_noexec &&
3569 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003570 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003571 if (vma->vm_start >= vma->vm_mm->start_brk &&
3572 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003573 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003574 } else if (!vma->vm_file &&
Stephen Smalleyc2316db2016-04-08 13:55:03 -04003575 ((vma->vm_start <= vma->vm_mm->start_stack &&
3576 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003577 vma_is_stack_for_current(vma))) {
David Howells3b11a1d2008-11-14 10:39:26 +11003578 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003579 } else if (vma->vm_file && vma->anon_vma) {
3580 /*
3581 * We are making executable a file mapping that has
3582 * had some COW done. Since pages might have been
3583 * written, check ability to execute the possibly
3584 * modified content. This typically should only
3585 * occur for text relocations.
3586 */
David Howellsd84f4f92008-11-14 10:39:23 +11003587 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003588 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003589 if (rc)
3590 return rc;
3591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592
3593 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3594}
3595
3596static int selinux_file_lock(struct file *file, unsigned int cmd)
3597{
David Howells88e67f32008-11-14 10:39:21 +11003598 const struct cred *cred = current_cred();
3599
3600 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601}
3602
3603static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3604 unsigned long arg)
3605{
David Howells88e67f32008-11-14 10:39:21 +11003606 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 int err = 0;
3608
3609 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003610 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003611 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003612 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003614 }
3615 /* fall through */
3616 case F_SETOWN:
3617 case F_SETSIG:
3618 case F_GETFL:
3619 case F_GETOWN:
3620 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003621 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003622 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003623 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003624 break;
3625 case F_GETLK:
3626 case F_SETLK:
3627 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003628 case F_OFD_GETLK:
3629 case F_OFD_SETLK:
3630 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003632 case F_GETLK64:
3633 case F_SETLK64:
3634 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635#endif
David Howells88e67f32008-11-14 10:39:21 +11003636 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003637 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 }
3639
3640 return err;
3641}
3642
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003643static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 struct file_security_struct *fsec;
3646
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003648 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649}
3650
3651static int selinux_file_send_sigiotask(struct task_struct *tsk,
3652 struct fown_struct *fown, int signum)
3653{
Eric Paris828dfe12008-04-17 13:17:49 -04003654 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003655 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 struct file_security_struct *fsec;
3658
3659 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003660 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 fsec = file->f_security;
3663
3664 if (!signum)
3665 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3666 else
3667 perm = signal_to_av(signum);
3668
David Howells275bb412008-11-14 10:39:19 +11003669 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 SECCLASS_PROCESS, perm, NULL);
3671}
3672
3673static int selinux_file_receive(struct file *file)
3674{
David Howells88e67f32008-11-14 10:39:21 +11003675 const struct cred *cred = current_cred();
3676
3677 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678}
3679
Eric Paris83d49852012-04-04 13:45:40 -04003680static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003681{
3682 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003683 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003684
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003685 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003686 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003687 /*
3688 * Save inode label and policy sequence number
3689 * at open-time so that selinux_file_permission
3690 * can determine whether revalidation is necessary.
3691 * Task label is already saved in the file security
3692 * struct as its SID.
3693 */
3694 fsec->isid = isec->sid;
3695 fsec->pseqno = avc_policy_seqno();
3696 /*
3697 * Since the inode label or policy seqno may have changed
3698 * between the selinux_inode_permission check and the saving
3699 * of state above, recheck that access is still permitted.
3700 * Otherwise, access might never be revalidated against the
3701 * new inode label or new policy.
3702 * This check is not redundant - do not remove.
3703 */
David Howells13f8e982013-06-13 23:37:55 +01003704 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003705}
3706
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707/* task security operations */
3708
3709static int selinux_task_create(unsigned long clone_flags)
3710{
David Howells3b11a1d2008-11-14 10:39:26 +11003711 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712}
3713
David Howellsf1752ee2008-11-14 10:39:17 +11003714/*
David Howellsee18d642009-09-02 09:14:21 +01003715 * allocate the SELinux part of blank credentials
3716 */
3717static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3718{
3719 struct task_security_struct *tsec;
3720
3721 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3722 if (!tsec)
3723 return -ENOMEM;
3724
3725 cred->security = tsec;
3726 return 0;
3727}
3728
3729/*
David Howellsf1752ee2008-11-14 10:39:17 +11003730 * detach and free the LSM part of a set of credentials
3731 */
3732static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733{
David Howellsf1752ee2008-11-14 10:39:17 +11003734 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003735
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003736 /*
3737 * cred->security == NULL if security_cred_alloc_blank() or
3738 * security_prepare_creds() returned an error.
3739 */
3740 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003741 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003742 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743}
3744
David Howellsd84f4f92008-11-14 10:39:23 +11003745/*
3746 * prepare a new set of credentials for modification
3747 */
3748static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3749 gfp_t gfp)
3750{
3751 const struct task_security_struct *old_tsec;
3752 struct task_security_struct *tsec;
3753
3754 old_tsec = old->security;
3755
3756 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3757 if (!tsec)
3758 return -ENOMEM;
3759
3760 new->security = tsec;
3761 return 0;
3762}
3763
3764/*
David Howellsee18d642009-09-02 09:14:21 +01003765 * transfer the SELinux data to a blank set of creds
3766 */
3767static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3768{
3769 const struct task_security_struct *old_tsec = old->security;
3770 struct task_security_struct *tsec = new->security;
3771
3772 *tsec = *old_tsec;
3773}
3774
3775/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003776 * set the security data for a kernel service
3777 * - all the creation contexts are set to unlabelled
3778 */
3779static int selinux_kernel_act_as(struct cred *new, u32 secid)
3780{
3781 struct task_security_struct *tsec = new->security;
3782 u32 sid = current_sid();
3783 int ret;
3784
3785 ret = avc_has_perm(sid, secid,
3786 SECCLASS_KERNEL_SERVICE,
3787 KERNEL_SERVICE__USE_AS_OVERRIDE,
3788 NULL);
3789 if (ret == 0) {
3790 tsec->sid = secid;
3791 tsec->create_sid = 0;
3792 tsec->keycreate_sid = 0;
3793 tsec->sockcreate_sid = 0;
3794 }
3795 return ret;
3796}
3797
3798/*
3799 * set the file creation context in a security record to the same as the
3800 * objective context of the specified inode
3801 */
3802static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3803{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003804 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003805 struct task_security_struct *tsec = new->security;
3806 u32 sid = current_sid();
3807 int ret;
3808
3809 ret = avc_has_perm(sid, isec->sid,
3810 SECCLASS_KERNEL_SERVICE,
3811 KERNEL_SERVICE__CREATE_FILES_AS,
3812 NULL);
3813
3814 if (ret == 0)
3815 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003816 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003817}
3818
Eric Parisdd8dbf22009-11-03 16:35:32 +11003819static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003820{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003821 u32 sid;
3822 struct common_audit_data ad;
3823
3824 sid = task_sid(current);
3825
Eric Paris50c205f2012-04-04 15:01:43 -04003826 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003827 ad.u.kmod_name = kmod_name;
3828
3829 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3830 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003831}
3832
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003833static int selinux_kernel_module_from_file(struct file *file)
3834{
3835 struct common_audit_data ad;
3836 struct inode_security_struct *isec;
3837 struct file_security_struct *fsec;
3838 u32 sid = current_sid();
3839 int rc;
3840
3841 /* init_module */
3842 if (file == NULL)
3843 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
3844 SYSTEM__MODULE_LOAD, NULL);
3845
3846 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003847
Vivek Goyal43af5de2016-09-09 11:37:49 -04003848 ad.type = LSM_AUDIT_DATA_FILE;
3849 ad.u.file = file;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003850
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003851 fsec = file->f_security;
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003852 if (sid != fsec->sid) {
3853 rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
3854 if (rc)
3855 return rc;
3856 }
3857
Paul Moore20cdef82016-04-04 14:14:42 -04003858 isec = inode_security(file_inode(file));
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07003859 return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
3860 SYSTEM__MODULE_LOAD, &ad);
3861}
3862
3863static int selinux_kernel_read_file(struct file *file,
3864 enum kernel_read_file_id id)
3865{
3866 int rc = 0;
3867
3868 switch (id) {
3869 case READING_MODULE:
3870 rc = selinux_kernel_module_from_file(file);
3871 break;
3872 default:
3873 break;
3874 }
3875
3876 return rc;
3877}
3878
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3880{
David Howells3b11a1d2008-11-14 10:39:26 +11003881 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882}
3883
3884static int selinux_task_getpgid(struct task_struct *p)
3885{
David Howells3b11a1d2008-11-14 10:39:26 +11003886 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887}
3888
3889static int selinux_task_getsid(struct task_struct *p)
3890{
David Howells3b11a1d2008-11-14 10:39:26 +11003891 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892}
3893
David Quigleyf9008e4c2006-06-30 01:55:46 -07003894static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3895{
David Howells275bb412008-11-14 10:39:19 +11003896 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003897}
3898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899static int selinux_task_setnice(struct task_struct *p, int nice)
3900{
David Howells3b11a1d2008-11-14 10:39:26 +11003901 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902}
3903
James Morris03e68062006-06-23 02:03:58 -07003904static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3905{
David Howells3b11a1d2008-11-14 10:39:26 +11003906 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003907}
3908
David Quigleya1836a42006-06-30 01:55:49 -07003909static int selinux_task_getioprio(struct task_struct *p)
3910{
David Howells3b11a1d2008-11-14 10:39:26 +11003911 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003912}
3913
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003914static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3915 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003917 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
3919 /* Control the ability to change the hard limit (whether
3920 lowering or raising it), so that the hard limit can
3921 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003922 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003924 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
3926 return 0;
3927}
3928
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003929static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930{
David Howells3b11a1d2008-11-14 10:39:26 +11003931 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932}
3933
3934static int selinux_task_getscheduler(struct task_struct *p)
3935{
David Howells3b11a1d2008-11-14 10:39:26 +11003936 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937}
3938
David Quigley35601542006-06-23 02:04:01 -07003939static int selinux_task_movememory(struct task_struct *p)
3940{
David Howells3b11a1d2008-11-14 10:39:26 +11003941 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003942}
3943
David Quigleyf9008e4c2006-06-30 01:55:46 -07003944static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3945 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946{
3947 u32 perm;
3948 int rc;
3949
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 if (!sig)
3951 perm = PROCESS__SIGNULL; /* null signal; existence test */
3952 else
3953 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003954 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003955 rc = avc_has_perm(secid, task_sid(p),
3956 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003957 else
David Howells3b11a1d2008-11-14 10:39:26 +11003958 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003959 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960}
3961
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962static int selinux_task_wait(struct task_struct *p)
3963{
Eric Paris8a535142007-10-22 16:10:31 -04003964 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965}
3966
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967static void selinux_task_to_inode(struct task_struct *p,
3968 struct inode *inode)
3969{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003971 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003973 spin_lock(&isec->lock);
Andreas Gruenbacherdb978da2016-11-10 22:18:28 +01003974 isec->sclass = inode_mode_to_security_class(inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11003975 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003976 isec->initialized = LABEL_INITIALIZED;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01003977 spin_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978}
3979
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003981static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003982 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983{
3984 int offset, ihlen, ret = -EINVAL;
3985 struct iphdr _iph, *ih;
3986
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003987 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3989 if (ih == NULL)
3990 goto out;
3991
3992 ihlen = ih->ihl * 4;
3993 if (ihlen < sizeof(_iph))
3994 goto out;
3995
Eric Paris48c62af2012-04-02 13:15:44 -04003996 ad->u.net->v4info.saddr = ih->saddr;
3997 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 ret = 0;
3999
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004000 if (proto)
4001 *proto = ih->protocol;
4002
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04004004 case IPPROTO_TCP: {
4005 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006
Eric Paris828dfe12008-04-17 13:17:49 -04004007 if (ntohs(ih->frag_off) & IP_OFFSET)
4008 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
4010 offset += ihlen;
4011 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4012 if (th == NULL)
4013 break;
4014
Eric Paris48c62af2012-04-02 13:15:44 -04004015 ad->u.net->sport = th->source;
4016 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
Eric Paris828dfe12008-04-17 13:17:49 -04004020 case IPPROTO_UDP: {
4021 struct udphdr _udph, *uh;
4022
4023 if (ntohs(ih->frag_off) & IP_OFFSET)
4024 break;
4025
4026 offset += ihlen;
4027 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4028 if (uh == NULL)
4029 break;
4030
Eric Paris48c62af2012-04-02 13:15:44 -04004031 ad->u.net->sport = uh->source;
4032 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004033 break;
4034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035
James Morris2ee92d42006-11-13 16:09:01 -08004036 case IPPROTO_DCCP: {
4037 struct dccp_hdr _dccph, *dh;
4038
4039 if (ntohs(ih->frag_off) & IP_OFFSET)
4040 break;
4041
4042 offset += ihlen;
4043 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4044 if (dh == NULL)
4045 break;
4046
Eric Paris48c62af2012-04-02 13:15:44 -04004047 ad->u.net->sport = dh->dccph_sport;
4048 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004049 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004050 }
James Morris2ee92d42006-11-13 16:09:01 -08004051
Eric Paris828dfe12008-04-17 13:17:49 -04004052 default:
4053 break;
4054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055out:
4056 return ret;
4057}
4058
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004059#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
4061/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004062static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004063 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
4065 u8 nexthdr;
4066 int ret = -EINVAL, offset;
4067 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004068 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004070 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4072 if (ip6 == NULL)
4073 goto out;
4074
Eric Paris48c62af2012-04-02 13:15:44 -04004075 ad->u.net->v6info.saddr = ip6->saddr;
4076 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 ret = 0;
4078
4079 nexthdr = ip6->nexthdr;
4080 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004081 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 if (offset < 0)
4083 goto out;
4084
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004085 if (proto)
4086 *proto = nexthdr;
4087
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 switch (nexthdr) {
4089 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004090 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
4092 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4093 if (th == NULL)
4094 break;
4095
Eric Paris48c62af2012-04-02 13:15:44 -04004096 ad->u.net->sport = th->source;
4097 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 break;
4099 }
4100
4101 case IPPROTO_UDP: {
4102 struct udphdr _udph, *uh;
4103
4104 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4105 if (uh == NULL)
4106 break;
4107
Eric Paris48c62af2012-04-02 13:15:44 -04004108 ad->u.net->sport = uh->source;
4109 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 break;
4111 }
4112
James Morris2ee92d42006-11-13 16:09:01 -08004113 case IPPROTO_DCCP: {
4114 struct dccp_hdr _dccph, *dh;
4115
4116 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4117 if (dh == NULL)
4118 break;
4119
Eric Paris48c62af2012-04-02 13:15:44 -04004120 ad->u.net->sport = dh->dccph_sport;
4121 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004122 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004123 }
James Morris2ee92d42006-11-13 16:09:01 -08004124
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 /* includes fragments */
4126 default:
4127 break;
4128 }
4129out:
4130 return ret;
4131}
4132
4133#endif /* IPV6 */
4134
Thomas Liu2bf49692009-07-14 12:14:09 -04004135static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004136 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137{
David Howellscf9481e2008-07-27 21:31:07 +10004138 char *addrp;
4139 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Eric Paris48c62af2012-04-02 13:15:44 -04004141 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004143 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004144 if (ret)
4145 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004146 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4147 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004148 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004150#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004152 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004153 if (ret)
4154 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004155 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4156 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004157 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158#endif /* IPV6 */
4159 default:
David Howellscf9481e2008-07-27 21:31:07 +10004160 addrp = NULL;
4161 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 }
4163
David Howellscf9481e2008-07-27 21:31:07 +10004164parse_error:
4165 printk(KERN_WARNING
4166 "SELinux: failure in selinux_parse_skb(),"
4167 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004169
4170okay:
4171 if (_addrp)
4172 *_addrp = addrp;
4173 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174}
4175
Paul Moore4f6a9932007-03-01 14:35:22 -05004176/**
Paul Moore220deb92008-01-29 08:38:23 -05004177 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004178 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004179 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004180 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004181 *
4182 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004183 * Check the various different forms of network peer labeling and determine
4184 * the peer label/SID for the packet; most of the magic actually occurs in
4185 * the security server function security_net_peersid_cmp(). The function
4186 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4187 * or -EACCES if @sid is invalid due to inconsistencies with the different
4188 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004189 *
4190 */
Paul Moore220deb92008-01-29 08:38:23 -05004191static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004192{
Paul Moore71f1cb02008-01-29 08:51:16 -05004193 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004194 u32 xfrm_sid;
4195 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004196 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004197
Paul Moore817eff72013-12-10 14:57:54 -05004198 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004199 if (unlikely(err))
4200 return -EACCES;
4201 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4202 if (unlikely(err))
4203 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004204
Paul Moore71f1cb02008-01-29 08:51:16 -05004205 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
4206 if (unlikely(err)) {
4207 printk(KERN_WARNING
4208 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4209 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004210 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004211 }
Paul Moore220deb92008-01-29 08:38:23 -05004212
4213 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004214}
4215
Paul Moore446b8022013-12-04 16:10:51 -05004216/**
4217 * selinux_conn_sid - Determine the child socket label for a connection
4218 * @sk_sid: the parent socket's SID
4219 * @skb_sid: the packet's SID
4220 * @conn_sid: the resulting connection SID
4221 *
4222 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4223 * combined with the MLS information from @skb_sid in order to create
4224 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4225 * of @sk_sid. Returns zero on success, negative values on failure.
4226 *
4227 */
4228static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4229{
4230 int err = 0;
4231
4232 if (skb_sid != SECSID_NULL)
4233 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4234 else
4235 *conn_sid = sk_sid;
4236
4237 return err;
4238}
4239
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004241
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004242static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4243 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004244{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004245 if (tsec->sockcreate_sid > SECSID_NULL) {
4246 *socksid = tsec->sockcreate_sid;
4247 return 0;
4248 }
4249
4250 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4251 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004252}
4253
Paul Moore253bfae2010-04-22 14:46:19 -04004254static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255{
Paul Moore253bfae2010-04-22 14:46:19 -04004256 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004257 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004258 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004259 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
Paul Moore253bfae2010-04-22 14:46:19 -04004261 if (sksec->sid == SECINITSID_KERNEL)
4262 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263
Eric Paris50c205f2012-04-04 15:01:43 -04004264 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004265 ad.u.net = &net;
4266 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Paul Moore253bfae2010-04-22 14:46:19 -04004268 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271static int selinux_socket_create(int family, int type,
4272 int protocol, int kern)
4273{
Paul Moore5fb49872010-04-22 14:46:19 -04004274 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004275 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004276 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004277 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
4279 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281
David Howells275bb412008-11-14 10:39:19 +11004282 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004283 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4284 if (rc)
4285 return rc;
4286
Paul Moored4f2d972010-04-22 14:46:18 -04004287 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288}
4289
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004290static int selinux_socket_post_create(struct socket *sock, int family,
4291 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292{
Paul Moore5fb49872010-04-22 14:46:19 -04004293 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004294 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004295 struct sk_security_struct *sksec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004296 u16 sclass = socket_type_to_security_class(family, type, protocol);
4297 u32 sid = SECINITSID_KERNEL;
David Howells275bb412008-11-14 10:39:19 +11004298 int err = 0;
4299
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004300 if (!kern) {
4301 err = socket_sockcreate_sid(tsec, sclass, &sid);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004302 if (err)
4303 return err;
4304 }
David Howells275bb412008-11-14 10:39:19 +11004305
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004306 isec->sclass = sclass;
4307 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004308 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004310 if (sock->sk) {
4311 sksec = sock->sk->sk_security;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004312 sksec->sclass = sclass;
4313 sksec->sid = sid;
Paul Moore389fb8002009-03-27 17:10:34 -04004314 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004315 }
4316
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004317 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318}
4319
4320/* Range of port numbers used to automatically bind.
4321 Need to determine whether we should perform a name_bind
4322 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323
4324static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4325{
Paul Moore253bfae2010-04-22 14:46:19 -04004326 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 u16 family;
4328 int err;
4329
Paul Moore253bfae2010-04-22 14:46:19 -04004330 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 if (err)
4332 goto out;
4333
4334 /*
4335 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004336 * Multiple address binding for SCTP is not supported yet: we just
4337 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 */
Paul Moore253bfae2010-04-22 14:46:19 -04004339 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 if (family == PF_INET || family == PF_INET6) {
4341 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004342 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004343 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004344 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 struct sockaddr_in *addr4 = NULL;
4346 struct sockaddr_in6 *addr6 = NULL;
4347 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004348 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 if (family == PF_INET) {
4351 addr4 = (struct sockaddr_in *)address;
4352 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 addrp = (char *)&addr4->sin_addr.s_addr;
4354 } else {
4355 addr6 = (struct sockaddr_in6 *)address;
4356 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 addrp = (char *)&addr6->sin6_addr.s6_addr;
4358 }
4359
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004360 if (snum) {
4361 int low, high;
4362
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004363 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004364
4365 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004366 err = sel_netport_sid(sk->sk_protocol,
4367 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004368 if (err)
4369 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004370 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004371 ad.u.net = &net;
4372 ad.u.net->sport = htons(snum);
4373 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004374 err = avc_has_perm(sksec->sid, sid,
4375 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004376 SOCKET__NAME_BIND, &ad);
4377 if (err)
4378 goto out;
4379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 }
Eric Paris828dfe12008-04-17 13:17:49 -04004381
Paul Moore253bfae2010-04-22 14:46:19 -04004382 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004383 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 node_perm = TCP_SOCKET__NODE_BIND;
4385 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004386
James Morris13402582005-09-30 14:24:34 -04004387 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 node_perm = UDP_SOCKET__NODE_BIND;
4389 break;
James Morris2ee92d42006-11-13 16:09:01 -08004390
4391 case SECCLASS_DCCP_SOCKET:
4392 node_perm = DCCP_SOCKET__NODE_BIND;
4393 break;
4394
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 default:
4396 node_perm = RAWIP_SOCKET__NODE_BIND;
4397 break;
4398 }
Eric Paris828dfe12008-04-17 13:17:49 -04004399
Paul Moore224dfbd2008-01-29 08:38:13 -05004400 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 if (err)
4402 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004403
Eric Paris50c205f2012-04-04 15:01:43 -04004404 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004405 ad.u.net = &net;
4406 ad.u.net->sport = htons(snum);
4407 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
4409 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004410 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 else
Eric Paris48c62af2012-04-02 13:15:44 -04004412 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413
Paul Moore253bfae2010-04-22 14:46:19 -04004414 err = avc_has_perm(sksec->sid, sid,
4415 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416 if (err)
4417 goto out;
4418 }
4419out:
4420 return err;
4421}
4422
4423static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4424{
Paul Moore014ab192008-10-10 10:16:33 -04004425 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004426 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 int err;
4428
Paul Moore253bfae2010-04-22 14:46:19 -04004429 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 if (err)
4431 return err;
4432
4433 /*
James Morris2ee92d42006-11-13 16:09:01 -08004434 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 */
Paul Moore253bfae2010-04-22 14:46:19 -04004436 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4437 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004438 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004439 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 struct sockaddr_in *addr4 = NULL;
4441 struct sockaddr_in6 *addr6 = NULL;
4442 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004443 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
4445 if (sk->sk_family == PF_INET) {
4446 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004447 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 return -EINVAL;
4449 snum = ntohs(addr4->sin_port);
4450 } else {
4451 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004452 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 return -EINVAL;
4454 snum = ntohs(addr6->sin6_port);
4455 }
4456
Paul Moore3e112172008-04-10 10:48:14 -04004457 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 if (err)
4459 goto out;
4460
Paul Moore253bfae2010-04-22 14:46:19 -04004461 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004462 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4463
Eric Paris50c205f2012-04-04 15:01:43 -04004464 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004465 ad.u.net = &net;
4466 ad.u.net->dport = htons(snum);
4467 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004468 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 if (err)
4470 goto out;
4471 }
4472
Paul Moore014ab192008-10-10 10:16:33 -04004473 err = selinux_netlbl_socket_connect(sk, address);
4474
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475out:
4476 return err;
4477}
4478
4479static int selinux_socket_listen(struct socket *sock, int backlog)
4480{
Paul Moore253bfae2010-04-22 14:46:19 -04004481 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482}
4483
4484static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4485{
4486 int err;
4487 struct inode_security_struct *isec;
4488 struct inode_security_struct *newisec;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004489 u16 sclass;
4490 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Paul Moore253bfae2010-04-22 14:46:19 -04004492 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 if (err)
4494 return err;
4495
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004496 isec = inode_security_novalidate(SOCK_INODE(sock));
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01004497 spin_lock(&isec->lock);
4498 sclass = isec->sclass;
4499 sid = isec->sid;
4500 spin_unlock(&isec->lock);
4501
4502 newisec = inode_security_novalidate(SOCK_INODE(newsock));
4503 newisec->sclass = sclass;
4504 newisec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004505 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
4507 return 0;
4508}
4509
4510static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004511 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512{
Paul Moore253bfae2010-04-22 14:46:19 -04004513 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514}
4515
4516static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4517 int size, int flags)
4518{
Paul Moore253bfae2010-04-22 14:46:19 -04004519 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520}
4521
4522static int selinux_socket_getsockname(struct socket *sock)
4523{
Paul Moore253bfae2010-04-22 14:46:19 -04004524 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525}
4526
4527static int selinux_socket_getpeername(struct socket *sock)
4528{
Paul Moore253bfae2010-04-22 14:46:19 -04004529 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530}
4531
Eric Paris828dfe12008-04-17 13:17:49 -04004532static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533{
Paul Mooref8687af2006-10-30 15:22:15 -08004534 int err;
4535
Paul Moore253bfae2010-04-22 14:46:19 -04004536 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004537 if (err)
4538 return err;
4539
4540 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541}
4542
4543static int selinux_socket_getsockopt(struct socket *sock, int level,
4544 int optname)
4545{
Paul Moore253bfae2010-04-22 14:46:19 -04004546 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547}
4548
4549static int selinux_socket_shutdown(struct socket *sock, int how)
4550{
Paul Moore253bfae2010-04-22 14:46:19 -04004551 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552}
4553
David S. Miller3610cda2011-01-05 15:38:53 -08004554static int selinux_socket_unix_stream_connect(struct sock *sock,
4555 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556 struct sock *newsk)
4557{
David S. Miller3610cda2011-01-05 15:38:53 -08004558 struct sk_security_struct *sksec_sock = sock->sk_security;
4559 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004560 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004561 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004562 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 int err;
4564
Eric Paris50c205f2012-04-04 15:01:43 -04004565 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004566 ad.u.net = &net;
4567 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568
Paul Moore4d1e2452010-04-22 14:46:18 -04004569 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4570 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4572 if (err)
4573 return err;
4574
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004576 sksec_new->peer_sid = sksec_sock->sid;
4577 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4578 &sksec_new->sid);
4579 if (err)
4580 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581
Paul Moore4d1e2452010-04-22 14:46:18 -04004582 /* connecting socket */
4583 sksec_sock->peer_sid = sksec_new->sid;
4584
4585 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586}
4587
4588static int selinux_socket_unix_may_send(struct socket *sock,
4589 struct socket *other)
4590{
Paul Moore253bfae2010-04-22 14:46:19 -04004591 struct sk_security_struct *ssec = sock->sk->sk_security;
4592 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004593 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004594 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595
Eric Paris50c205f2012-04-04 15:01:43 -04004596 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004597 ad.u.net = &net;
4598 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599
Paul Moore253bfae2010-04-22 14:46:19 -04004600 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4601 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602}
4603
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004604static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4605 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004606 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004607{
4608 int err;
4609 u32 if_sid;
4610 u32 node_sid;
4611
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004612 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004613 if (err)
4614 return err;
4615 err = avc_has_perm(peer_sid, if_sid,
4616 SECCLASS_NETIF, NETIF__INGRESS, ad);
4617 if (err)
4618 return err;
4619
4620 err = sel_netnode_sid(addrp, family, &node_sid);
4621 if (err)
4622 return err;
4623 return avc_has_perm(peer_sid, node_sid,
4624 SECCLASS_NODE, NODE__RECVFROM, ad);
4625}
4626
Paul Moore220deb92008-01-29 08:38:23 -05004627static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004628 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004629{
Paul Moore277d3422008-12-31 12:54:11 -05004630 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004631 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004632 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004633 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004634 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004635 char *addrp;
4636
Eric Paris50c205f2012-04-04 15:01:43 -04004637 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004638 ad.u.net = &net;
4639 ad.u.net->netif = skb->skb_iif;
4640 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004641 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4642 if (err)
4643 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004644
Paul Moore58bfbb52009-03-27 17:10:41 -04004645 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004646 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004647 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004648 if (err)
4649 return err;
4650 }
Paul Moore220deb92008-01-29 08:38:23 -05004651
Steffen Klassertb9679a72011-02-23 12:55:21 +01004652 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4653 if (err)
4654 return err;
4655 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004656
James Morris4e5ab4c2006-06-09 00:33:33 -07004657 return err;
4658}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004659
James Morris4e5ab4c2006-06-09 00:33:33 -07004660static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4661{
Paul Moore220deb92008-01-29 08:38:23 -05004662 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004663 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004664 u16 family = sk->sk_family;
4665 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004666 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004667 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004668 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004669 u8 secmark_active;
4670 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004671
James Morris4e5ab4c2006-06-09 00:33:33 -07004672 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004673 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004674
4675 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004676 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004677 family = PF_INET;
4678
Paul Moored8395c82008-10-10 10:16:30 -04004679 /* If any sort of compatibility mode is enabled then handoff processing
4680 * to the selinux_sock_rcv_skb_compat() function to deal with the
4681 * special handling. We do this in an attempt to keep this function
4682 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004683 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004684 return selinux_sock_rcv_skb_compat(sk, skb, family);
4685
4686 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004687 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004688 if (!secmark_active && !peerlbl_active)
4689 return 0;
4690
Eric Paris50c205f2012-04-04 15:01:43 -04004691 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004692 ad.u.net = &net;
4693 ad.u.net->netif = skb->skb_iif;
4694 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004695 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004696 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004697 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004698
Paul Moored8395c82008-10-10 10:16:30 -04004699 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004700 u32 peer_sid;
4701
4702 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4703 if (err)
4704 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004705 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4706 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004707 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004708 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004709 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004710 }
Paul Moored621d352008-01-29 08:43:36 -05004711 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4712 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004713 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004714 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004715 return err;
4716 }
Paul Moored621d352008-01-29 08:43:36 -05004717 }
4718
Paul Moored8395c82008-10-10 10:16:30 -04004719 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004720 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4721 PACKET__RECV, &ad);
4722 if (err)
4723 return err;
4724 }
4725
Paul Moored621d352008-01-29 08:43:36 -05004726 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727}
4728
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004729static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4730 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731{
4732 int err = 0;
4733 char *scontext;
4734 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004735 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004736 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737
Paul Moore253bfae2010-04-22 14:46:19 -04004738 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4739 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004740 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004741 if (peer_sid == SECSID_NULL)
4742 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004744 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004746 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747
4748 if (scontext_len > len) {
4749 err = -ERANGE;
4750 goto out_len;
4751 }
4752
4753 if (copy_to_user(optval, scontext, scontext_len))
4754 err = -EFAULT;
4755
4756out_len:
4757 if (put_user(scontext_len, optlen))
4758 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760 return err;
4761}
4762
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004763static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004764{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004765 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004766 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004767 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004768
Paul Mooreaa862902008-10-10 10:16:29 -04004769 if (skb && skb->protocol == htons(ETH_P_IP))
4770 family = PF_INET;
4771 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4772 family = PF_INET6;
4773 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004774 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004775 else
4776 goto out;
4777
Paul Moore899134f2016-03-28 15:19:10 -04004778 if (sock && family == PF_UNIX) {
4779 isec = inode_security_novalidate(SOCK_INODE(sock));
4780 peer_secid = isec->sid;
4781 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004782 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004783
Paul Moore75e22912008-01-29 08:38:04 -05004784out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004785 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004786 if (peer_secid == SECSID_NULL)
4787 return -EINVAL;
4788 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004789}
4790
Al Viro7d877f32005-10-21 03:20:43 -04004791static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792{
Paul Moore84914b72010-04-22 14:46:18 -04004793 struct sk_security_struct *sksec;
4794
4795 sksec = kzalloc(sizeof(*sksec), priority);
4796 if (!sksec)
4797 return -ENOMEM;
4798
4799 sksec->peer_sid = SECINITSID_UNLABELED;
4800 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004801 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004802 selinux_netlbl_sk_security_reset(sksec);
4803 sk->sk_security = sksec;
4804
4805 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806}
4807
4808static void selinux_sk_free_security(struct sock *sk)
4809{
Paul Moore84914b72010-04-22 14:46:18 -04004810 struct sk_security_struct *sksec = sk->sk_security;
4811
4812 sk->sk_security = NULL;
4813 selinux_netlbl_sk_security_free(sksec);
4814 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815}
4816
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004817static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4818{
Eric Parisdd3e7832010-04-07 15:08:46 -04004819 struct sk_security_struct *sksec = sk->sk_security;
4820 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004821
Eric Parisdd3e7832010-04-07 15:08:46 -04004822 newsksec->sid = sksec->sid;
4823 newsksec->peer_sid = sksec->peer_sid;
4824 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004825
Eric Parisdd3e7832010-04-07 15:08:46 -04004826 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004827}
4828
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004829static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004830{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004831 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004832 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004833 else {
4834 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004835
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004836 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004837 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004838}
4839
Eric Paris828dfe12008-04-17 13:17:49 -04004840static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004841{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004842 struct inode_security_struct *isec =
4843 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004844 struct sk_security_struct *sksec = sk->sk_security;
4845
Paul Moore2873ead2014-07-28 10:42:48 -04004846 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4847 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004848 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004849 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004850}
4851
Adrian Bunk9a673e52006-08-15 00:03:53 -07004852static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4853 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004854{
4855 struct sk_security_struct *sksec = sk->sk_security;
4856 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004857 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004858 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004859 u32 peersid;
4860
Paul Mooreaa862902008-10-10 10:16:29 -04004861 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004862 if (err)
4863 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004864 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4865 if (err)
4866 return err;
4867 req->secid = connsid;
4868 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004869
Paul Moore389fb8002009-03-27 17:10:34 -04004870 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004871}
4872
Adrian Bunk9a673e52006-08-15 00:03:53 -07004873static void selinux_inet_csk_clone(struct sock *newsk,
4874 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004875{
4876 struct sk_security_struct *newsksec = newsk->sk_security;
4877
4878 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004879 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004880 /* NOTE: Ideally, we should also get the isec->sid for the
4881 new socket in sync, but we don't have the isec available yet.
4882 So we will wait until sock_graft to do it, by which
4883 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004884
Paul Moore9f2ad662006-11-17 17:38:53 -05004885 /* We don't need to take any sort of lock here as we are the only
4886 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004887 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004888}
4889
Paul Moore014ab192008-10-10 10:16:33 -04004890static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004891{
Paul Mooreaa862902008-10-10 10:16:29 -04004892 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004893 struct sk_security_struct *sksec = sk->sk_security;
4894
Paul Mooreaa862902008-10-10 10:16:29 -04004895 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4896 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4897 family = PF_INET;
4898
4899 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004900}
4901
Eric Paris2606fd12010-10-13 16:24:41 -04004902static int selinux_secmark_relabel_packet(u32 sid)
4903{
4904 const struct task_security_struct *__tsec;
4905 u32 tsid;
4906
4907 __tsec = current_security();
4908 tsid = __tsec->sid;
4909
4910 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4911}
4912
4913static void selinux_secmark_refcount_inc(void)
4914{
4915 atomic_inc(&selinux_secmark_refcount);
4916}
4917
4918static void selinux_secmark_refcount_dec(void)
4919{
4920 atomic_dec(&selinux_secmark_refcount);
4921}
4922
Adrian Bunk9a673e52006-08-15 00:03:53 -07004923static void selinux_req_classify_flow(const struct request_sock *req,
4924 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004925{
David S. Miller1d28f422011-03-12 00:29:39 -05004926 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004927}
4928
Paul Moore5dbbaf22013-01-14 07:12:19 +00004929static int selinux_tun_dev_alloc_security(void **security)
4930{
4931 struct tun_security_struct *tunsec;
4932
4933 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4934 if (!tunsec)
4935 return -ENOMEM;
4936 tunsec->sid = current_sid();
4937
4938 *security = tunsec;
4939 return 0;
4940}
4941
4942static void selinux_tun_dev_free_security(void *security)
4943{
4944 kfree(security);
4945}
4946
Paul Mooreed6d76e2009-08-28 18:12:49 -04004947static int selinux_tun_dev_create(void)
4948{
4949 u32 sid = current_sid();
4950
4951 /* we aren't taking into account the "sockcreate" SID since the socket
4952 * that is being created here is not a socket in the traditional sense,
4953 * instead it is a private sock, accessible only to the kernel, and
4954 * representing a wide range of network traffic spanning multiple
4955 * connections unlike traditional sockets - check the TUN driver to
4956 * get a better understanding of why this socket is special */
4957
4958 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4959 NULL);
4960}
4961
Paul Moore5dbbaf22013-01-14 07:12:19 +00004962static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004963{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004964 struct tun_security_struct *tunsec = security;
4965
4966 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4967 TUN_SOCKET__ATTACH_QUEUE, NULL);
4968}
4969
4970static int selinux_tun_dev_attach(struct sock *sk, void *security)
4971{
4972 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004973 struct sk_security_struct *sksec = sk->sk_security;
4974
4975 /* we don't currently perform any NetLabel based labeling here and it
4976 * isn't clear that we would want to do so anyway; while we could apply
4977 * labeling without the support of the TUN user the resulting labeled
4978 * traffic from the other end of the connection would almost certainly
4979 * cause confusion to the TUN user that had no idea network labeling
4980 * protocols were being used */
4981
Paul Moore5dbbaf22013-01-14 07:12:19 +00004982 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004983 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004984
4985 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004986}
4987
Paul Moore5dbbaf22013-01-14 07:12:19 +00004988static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004989{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004990 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004991 u32 sid = current_sid();
4992 int err;
4993
Paul Moore5dbbaf22013-01-14 07:12:19 +00004994 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004995 TUN_SOCKET__RELABELFROM, NULL);
4996 if (err)
4997 return err;
4998 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4999 TUN_SOCKET__RELABELTO, NULL);
5000 if (err)
5001 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00005002 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04005003
5004 return 0;
5005}
5006
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
5008{
5009 int err = 0;
5010 u32 perm;
5011 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005012 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005013
Hong zhi guo77954982013-03-27 06:49:35 +00005014 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015 err = -EINVAL;
5016 goto out;
5017 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005018 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005019
Paul Moore253bfae2010-04-22 14:46:19 -04005020 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021 if (err) {
5022 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005023 pr_warn_ratelimited("SELinux: unrecognized netlink"
5024 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5025 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005026 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005027 secclass_map[sksec->sclass - 1].name,
5028 task_pid_nr(current), current->comm);
Eric Paris39c9aed2008-11-05 09:34:42 -05005029 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030 err = 0;
5031 }
5032
5033 /* Ignore */
5034 if (err == -ENOENT)
5035 err = 0;
5036 goto out;
5037 }
5038
Paul Moore253bfae2010-04-22 14:46:19 -04005039 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040out:
5041 return err;
5042}
5043
5044#ifdef CONFIG_NETFILTER
5045
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005046static unsigned int selinux_ip_forward(struct sk_buff *skb,
5047 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005048 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049{
Paul Mooredfaebe92008-10-10 10:16:31 -04005050 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005051 char *addrp;
5052 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005053 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005054 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005055 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005056 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005057 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005058
Paul Mooreeffad8d2008-01-29 08:49:27 -05005059 if (!selinux_policycap_netpeer)
5060 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005061
Paul Mooreeffad8d2008-01-29 08:49:27 -05005062 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005063 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005064 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005065 if (!secmark_active && !peerlbl_active)
5066 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005067
Paul Moored8395c82008-10-10 10:16:30 -04005068 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5069 return NF_DROP;
5070
Eric Paris50c205f2012-04-04 15:01:43 -04005071 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005072 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005073 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005074 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005075 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5076 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077
Paul Mooredfaebe92008-10-10 10:16:31 -04005078 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005079 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5080 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005081 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005082 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005083 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005084 }
5085 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005086
5087 if (secmark_active)
5088 if (avc_has_perm(peer_sid, skb->secmark,
5089 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5090 return NF_DROP;
5091
Paul Moore948bf852008-10-10 10:16:32 -04005092 if (netlbl_active)
5093 /* we do this in the FORWARD path and not the POST_ROUTING
5094 * path because we want to make sure we apply the necessary
5095 * labeling before IPsec is applied so we can leverage AH
5096 * protection */
5097 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5098 return NF_DROP;
5099
Paul Mooreeffad8d2008-01-29 08:49:27 -05005100 return NF_ACCEPT;
5101}
5102
Eric W. Biederman06198b32015-09-18 14:33:06 -05005103static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005104 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005105 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005106{
David S. Miller238e54c2015-04-03 20:32:56 -04005107 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005108}
5109
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005110#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005111static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005112 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005113 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005114{
David S. Miller238e54c2015-04-03 20:32:56 -04005115 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005116}
5117#endif /* IPV6 */
5118
Paul Moore948bf852008-10-10 10:16:32 -04005119static unsigned int selinux_ip_output(struct sk_buff *skb,
5120 u16 family)
5121{
Paul Moore47180062013-12-04 16:10:45 -05005122 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005123 u32 sid;
5124
5125 if (!netlbl_enabled())
5126 return NF_ACCEPT;
5127
5128 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5129 * because we want to make sure we apply the necessary labeling
5130 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005131 sk = skb->sk;
5132 if (sk) {
5133 struct sk_security_struct *sksec;
5134
Eric Dumazete446f9d2015-10-08 05:01:55 -07005135 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005136 /* if the socket is the listening state then this
5137 * packet is a SYN-ACK packet which means it needs to
5138 * be labeled based on the connection/request_sock and
5139 * not the parent socket. unfortunately, we can't
5140 * lookup the request_sock yet as it isn't queued on
5141 * the parent socket until after the SYN-ACK is sent.
5142 * the "solution" is to simply pass the packet as-is
5143 * as any IP option based labeling should be copied
5144 * from the initial connection request (in the IP
5145 * layer). it is far from ideal, but until we get a
5146 * security label in the packet itself this is the
5147 * best we can do. */
5148 return NF_ACCEPT;
5149
5150 /* standard practice, label using the parent socket */
5151 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005152 sid = sksec->sid;
5153 } else
5154 sid = SECINITSID_KERNEL;
5155 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5156 return NF_DROP;
5157
5158 return NF_ACCEPT;
5159}
5160
Eric W. Biederman06198b32015-09-18 14:33:06 -05005161static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005162 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005163 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005164{
5165 return selinux_ip_output(skb, PF_INET);
5166}
5167
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005168#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005169static unsigned int selinux_ipv6_output(void *priv,
5170 struct sk_buff *skb,
5171 const struct nf_hook_state *state)
5172{
5173 return selinux_ip_output(skb, PF_INET6);
5174}
5175#endif /* IPV6 */
5176
Paul Mooreeffad8d2008-01-29 08:49:27 -05005177static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5178 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005179 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005180{
Eric Dumazet54abc682015-11-08 10:54:07 -08005181 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005182 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005183 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005184 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005185 char *addrp;
5186 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005187
Paul Mooreeffad8d2008-01-29 08:49:27 -05005188 if (sk == NULL)
5189 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005190 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005191
Eric Paris50c205f2012-04-04 15:01:43 -04005192 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005193 ad.u.net = &net;
5194 ad.u.net->netif = ifindex;
5195 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005196 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5197 return NF_DROP;
5198
Paul Moore58bfbb52009-03-27 17:10:41 -04005199 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005200 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005201 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005202 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005203
Steffen Klassertb9679a72011-02-23 12:55:21 +01005204 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5205 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005206
Paul Mooreeffad8d2008-01-29 08:49:27 -05005207 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208}
5209
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005210static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5211 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005212 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005214 u32 secmark_perm;
5215 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005216 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005217 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005218 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005219 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005220 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005221 u8 secmark_active;
5222 u8 peerlbl_active;
5223
Paul Mooreeffad8d2008-01-29 08:49:27 -05005224 /* If any sort of compatibility mode is enabled then handoff processing
5225 * to the selinux_ip_postroute_compat() function to deal with the
5226 * special handling. We do this in an attempt to keep this function
5227 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04005228 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04005229 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005230
Paul Mooreeffad8d2008-01-29 08:49:27 -05005231 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005232 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005233 if (!secmark_active && !peerlbl_active)
5234 return NF_ACCEPT;
5235
Eric Dumazet54abc682015-11-08 10:54:07 -08005236 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005237
Paul Mooreeffad8d2008-01-29 08:49:27 -05005238#ifdef CONFIG_XFRM
5239 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5240 * packet transformation so allow the packet to pass without any checks
5241 * since we'll have another chance to perform access control checks
5242 * when the packet is on it's final way out.
5243 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005244 * is NULL, in this case go ahead and apply access control.
5245 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5246 * TCP listening state we cannot wait until the XFRM processing
5247 * is done as we will miss out on the SA label if we do;
5248 * unfortunately, this means more work, but it is only once per
5249 * connection. */
5250 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005251 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005252 return NF_ACCEPT;
5253#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005254
Paul Moored8395c82008-10-10 10:16:30 -04005255 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005256 /* Without an associated socket the packet is either coming
5257 * from the kernel or it is being forwarded; check the packet
5258 * to determine which and if the packet is being forwarded
5259 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005260 if (skb->skb_iif) {
5261 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005262 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005263 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005264 } else {
5265 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005266 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005267 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005268 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005269 /* Locally generated packet but the associated socket is in the
5270 * listening state which means this is a SYN-ACK packet. In
5271 * this particular case the correct security label is assigned
5272 * to the connection/request_sock but unfortunately we can't
5273 * query the request_sock as it isn't queued on the parent
5274 * socket until after the SYN-ACK packet is sent; the only
5275 * viable choice is to regenerate the label like we do in
5276 * selinux_inet_conn_request(). See also selinux_ip_output()
5277 * for similar problems. */
5278 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005279 struct sk_security_struct *sksec;
5280
Eric Dumazete446f9d2015-10-08 05:01:55 -07005281 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005282 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5283 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005284 /* At this point, if the returned skb peerlbl is SECSID_NULL
5285 * and the packet has been through at least one XFRM
5286 * transformation then we must be dealing with the "final"
5287 * form of labeled IPsec packet; since we've already applied
5288 * all of our access controls on this packet we can safely
5289 * pass the packet. */
5290 if (skb_sid == SECSID_NULL) {
5291 switch (family) {
5292 case PF_INET:
5293 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5294 return NF_ACCEPT;
5295 break;
5296 case PF_INET6:
5297 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5298 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005299 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005300 default:
5301 return NF_DROP_ERR(-ECONNREFUSED);
5302 }
5303 }
Paul Moore446b8022013-12-04 16:10:51 -05005304 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5305 return NF_DROP;
5306 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005307 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005308 /* Locally generated packet, fetch the security label from the
5309 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005310 struct sk_security_struct *sksec = sk->sk_security;
5311 peer_sid = sksec->sid;
5312 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005313 }
5314
Eric Paris50c205f2012-04-04 15:01:43 -04005315 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005316 ad.u.net = &net;
5317 ad.u.net->netif = ifindex;
5318 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005319 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005320 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005321
Paul Mooreeffad8d2008-01-29 08:49:27 -05005322 if (secmark_active)
5323 if (avc_has_perm(peer_sid, skb->secmark,
5324 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005325 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005326
5327 if (peerlbl_active) {
5328 u32 if_sid;
5329 u32 node_sid;
5330
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005331 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005332 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005333 if (avc_has_perm(peer_sid, if_sid,
5334 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005335 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005336
5337 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005338 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005339 if (avc_has_perm(peer_sid, node_sid,
5340 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005341 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005342 }
5343
5344 return NF_ACCEPT;
5345}
5346
Eric W. Biederman06198b32015-09-18 14:33:06 -05005347static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005348 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005349 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005350{
David S. Miller238e54c2015-04-03 20:32:56 -04005351 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352}
5353
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005354#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005355static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005356 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005357 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358{
David S. Miller238e54c2015-04-03 20:32:56 -04005359 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005360}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361#endif /* IPV6 */
5362
5363#endif /* CONFIG_NETFILTER */
5364
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5366{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005367 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368}
5369
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370static int ipc_alloc_security(struct task_struct *task,
5371 struct kern_ipc_perm *perm,
5372 u16 sclass)
5373{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005375 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376
James Morris89d155e2005-10-30 14:59:21 -08005377 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378 if (!isec)
5379 return -ENOMEM;
5380
David Howells275bb412008-11-14 10:39:19 +11005381 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005383 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384 perm->security = isec;
5385
5386 return 0;
5387}
5388
5389static void ipc_free_security(struct kern_ipc_perm *perm)
5390{
5391 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392 perm->security = NULL;
5393 kfree(isec);
5394}
5395
5396static int msg_msg_alloc_security(struct msg_msg *msg)
5397{
5398 struct msg_security_struct *msec;
5399
James Morris89d155e2005-10-30 14:59:21 -08005400 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 if (!msec)
5402 return -ENOMEM;
5403
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404 msec->sid = SECINITSID_UNLABELED;
5405 msg->security = msec;
5406
5407 return 0;
5408}
5409
5410static void msg_msg_free_security(struct msg_msg *msg)
5411{
5412 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
5414 msg->security = NULL;
5415 kfree(msec);
5416}
5417
5418static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005419 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005422 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005423 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Linus Torvalds1da177e2005-04-16 15:20:36 -07005425 isec = ipc_perms->security;
5426
Eric Paris50c205f2012-04-04 15:01:43 -04005427 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428 ad.u.ipc_id = ipc_perms->key;
5429
David Howells275bb412008-11-14 10:39:19 +11005430 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431}
5432
5433static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5434{
5435 return msg_msg_alloc_security(msg);
5436}
5437
5438static void selinux_msg_msg_free_security(struct msg_msg *msg)
5439{
5440 msg_msg_free_security(msg);
5441}
5442
5443/* message queue security operations */
5444static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5445{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005447 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005448 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005449 int rc;
5450
5451 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5452 if (rc)
5453 return rc;
5454
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455 isec = msq->q_perm.security;
5456
Eric Paris50c205f2012-04-04 15:01:43 -04005457 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005458 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459
David Howells275bb412008-11-14 10:39:19 +11005460 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461 MSGQ__CREATE, &ad);
5462 if (rc) {
5463 ipc_free_security(&msq->q_perm);
5464 return rc;
5465 }
5466 return 0;
5467}
5468
5469static void selinux_msg_queue_free_security(struct msg_queue *msq)
5470{
5471 ipc_free_security(&msq->q_perm);
5472}
5473
5474static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5475{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005477 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005478 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Linus Torvalds1da177e2005-04-16 15:20:36 -07005480 isec = msq->q_perm.security;
5481
Eric Paris50c205f2012-04-04 15:01:43 -04005482 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483 ad.u.ipc_id = msq->q_perm.key;
5484
David Howells275bb412008-11-14 10:39:19 +11005485 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486 MSGQ__ASSOCIATE, &ad);
5487}
5488
5489static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5490{
5491 int err;
5492 int perms;
5493
Eric Paris828dfe12008-04-17 13:17:49 -04005494 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495 case IPC_INFO:
5496 case MSG_INFO:
5497 /* No specific object, just general system-wide information. */
5498 return task_has_system(current, SYSTEM__IPC_INFO);
5499 case IPC_STAT:
5500 case MSG_STAT:
5501 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5502 break;
5503 case IPC_SET:
5504 perms = MSGQ__SETATTR;
5505 break;
5506 case IPC_RMID:
5507 perms = MSGQ__DESTROY;
5508 break;
5509 default:
5510 return 0;
5511 }
5512
Stephen Smalley6af963f2005-05-01 08:58:39 -07005513 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514 return err;
5515}
5516
5517static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5518{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 struct ipc_security_struct *isec;
5520 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005521 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005522 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 int rc;
5524
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 isec = msq->q_perm.security;
5526 msec = msg->security;
5527
5528 /*
5529 * First time through, need to assign label to the message
5530 */
5531 if (msec->sid == SECINITSID_UNLABELED) {
5532 /*
5533 * Compute new sid based on current process and
5534 * message queue this message will be stored in
5535 */
David Howells275bb412008-11-14 10:39:19 +11005536 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005537 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005538 if (rc)
5539 return rc;
5540 }
5541
Eric Paris50c205f2012-04-04 15:01:43 -04005542 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543 ad.u.ipc_id = msq->q_perm.key;
5544
5545 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005546 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547 MSGQ__WRITE, &ad);
5548 if (!rc)
5549 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005550 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5551 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 if (!rc)
5553 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005554 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5555 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556
5557 return rc;
5558}
5559
5560static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5561 struct task_struct *target,
5562 long type, int mode)
5563{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564 struct ipc_security_struct *isec;
5565 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005566 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005567 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 int rc;
5569
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 isec = msq->q_perm.security;
5571 msec = msg->security;
5572
Eric Paris50c205f2012-04-04 15:01:43 -04005573 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005574 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005575
David Howells275bb412008-11-14 10:39:19 +11005576 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577 SECCLASS_MSGQ, MSGQ__READ, &ad);
5578 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005579 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580 SECCLASS_MSG, MSG__RECEIVE, &ad);
5581 return rc;
5582}
5583
5584/* Shared Memory security operations */
5585static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5586{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005588 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005589 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590 int rc;
5591
5592 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5593 if (rc)
5594 return rc;
5595
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 isec = shp->shm_perm.security;
5597
Eric Paris50c205f2012-04-04 15:01:43 -04005598 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005599 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600
David Howells275bb412008-11-14 10:39:19 +11005601 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602 SHM__CREATE, &ad);
5603 if (rc) {
5604 ipc_free_security(&shp->shm_perm);
5605 return rc;
5606 }
5607 return 0;
5608}
5609
5610static void selinux_shm_free_security(struct shmid_kernel *shp)
5611{
5612 ipc_free_security(&shp->shm_perm);
5613}
5614
5615static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5616{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005618 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005619 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621 isec = shp->shm_perm.security;
5622
Eric Paris50c205f2012-04-04 15:01:43 -04005623 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 ad.u.ipc_id = shp->shm_perm.key;
5625
David Howells275bb412008-11-14 10:39:19 +11005626 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627 SHM__ASSOCIATE, &ad);
5628}
5629
5630/* Note, at this point, shp is locked down */
5631static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5632{
5633 int perms;
5634 int err;
5635
Eric Paris828dfe12008-04-17 13:17:49 -04005636 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 case IPC_INFO:
5638 case SHM_INFO:
5639 /* No specific object, just general system-wide information. */
5640 return task_has_system(current, SYSTEM__IPC_INFO);
5641 case IPC_STAT:
5642 case SHM_STAT:
5643 perms = SHM__GETATTR | SHM__ASSOCIATE;
5644 break;
5645 case IPC_SET:
5646 perms = SHM__SETATTR;
5647 break;
5648 case SHM_LOCK:
5649 case SHM_UNLOCK:
5650 perms = SHM__LOCK;
5651 break;
5652 case IPC_RMID:
5653 perms = SHM__DESTROY;
5654 break;
5655 default:
5656 return 0;
5657 }
5658
Stephen Smalley6af963f2005-05-01 08:58:39 -07005659 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660 return err;
5661}
5662
5663static int selinux_shm_shmat(struct shmid_kernel *shp,
5664 char __user *shmaddr, int shmflg)
5665{
5666 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667
5668 if (shmflg & SHM_RDONLY)
5669 perms = SHM__READ;
5670 else
5671 perms = SHM__READ | SHM__WRITE;
5672
Stephen Smalley6af963f2005-05-01 08:58:39 -07005673 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674}
5675
5676/* Semaphore security operations */
5677static int selinux_sem_alloc_security(struct sem_array *sma)
5678{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005680 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005681 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 int rc;
5683
5684 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5685 if (rc)
5686 return rc;
5687
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688 isec = sma->sem_perm.security;
5689
Eric Paris50c205f2012-04-04 15:01:43 -04005690 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005691 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
David Howells275bb412008-11-14 10:39:19 +11005693 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005694 SEM__CREATE, &ad);
5695 if (rc) {
5696 ipc_free_security(&sma->sem_perm);
5697 return rc;
5698 }
5699 return 0;
5700}
5701
5702static void selinux_sem_free_security(struct sem_array *sma)
5703{
5704 ipc_free_security(&sma->sem_perm);
5705}
5706
5707static int selinux_sem_associate(struct sem_array *sma, int semflg)
5708{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005710 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005711 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713 isec = sma->sem_perm.security;
5714
Eric Paris50c205f2012-04-04 15:01:43 -04005715 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716 ad.u.ipc_id = sma->sem_perm.key;
5717
David Howells275bb412008-11-14 10:39:19 +11005718 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719 SEM__ASSOCIATE, &ad);
5720}
5721
5722/* Note, at this point, sma is locked down */
5723static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5724{
5725 int err;
5726 u32 perms;
5727
Eric Paris828dfe12008-04-17 13:17:49 -04005728 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 case IPC_INFO:
5730 case SEM_INFO:
5731 /* No specific object, just general system-wide information. */
5732 return task_has_system(current, SYSTEM__IPC_INFO);
5733 case GETPID:
5734 case GETNCNT:
5735 case GETZCNT:
5736 perms = SEM__GETATTR;
5737 break;
5738 case GETVAL:
5739 case GETALL:
5740 perms = SEM__READ;
5741 break;
5742 case SETVAL:
5743 case SETALL:
5744 perms = SEM__WRITE;
5745 break;
5746 case IPC_RMID:
5747 perms = SEM__DESTROY;
5748 break;
5749 case IPC_SET:
5750 perms = SEM__SETATTR;
5751 break;
5752 case IPC_STAT:
5753 case SEM_STAT:
5754 perms = SEM__GETATTR | SEM__ASSOCIATE;
5755 break;
5756 default:
5757 return 0;
5758 }
5759
Stephen Smalley6af963f2005-05-01 08:58:39 -07005760 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005761 return err;
5762}
5763
5764static int selinux_sem_semop(struct sem_array *sma,
5765 struct sembuf *sops, unsigned nsops, int alter)
5766{
5767 u32 perms;
5768
5769 if (alter)
5770 perms = SEM__READ | SEM__WRITE;
5771 else
5772 perms = SEM__READ;
5773
Stephen Smalley6af963f2005-05-01 08:58:39 -07005774 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775}
5776
5777static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5778{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779 u32 av = 0;
5780
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781 av = 0;
5782 if (flag & S_IRUGO)
5783 av |= IPC__UNIX_READ;
5784 if (flag & S_IWUGO)
5785 av |= IPC__UNIX_WRITE;
5786
5787 if (av == 0)
5788 return 0;
5789
Stephen Smalley6af963f2005-05-01 08:58:39 -07005790 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791}
5792
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005793static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5794{
5795 struct ipc_security_struct *isec = ipcp->security;
5796 *secid = isec->sid;
5797}
5798
Eric Paris828dfe12008-04-17 13:17:49 -04005799static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800{
5801 if (inode)
5802 inode_doinit_with_dentry(inode, dentry);
5803}
5804
5805static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005806 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807{
David Howells275bb412008-11-14 10:39:19 +11005808 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005809 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005811 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
5813 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005814 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815 if (error)
5816 return error;
5817 }
5818
David Howells275bb412008-11-14 10:39:19 +11005819 rcu_read_lock();
5820 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
5822 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005823 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005825 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005827 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005828 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005829 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005830 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005831 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005832 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005833 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834 else
David Howells275bb412008-11-14 10:39:19 +11005835 goto invalid;
5836 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
5838 if (!sid)
5839 return 0;
5840
Al Viro04ff9702007-03-12 16:17:58 +00005841 error = security_sid_to_context(sid, value, &len);
5842 if (error)
5843 return error;
5844 return len;
David Howells275bb412008-11-14 10:39:19 +11005845
5846invalid:
5847 rcu_read_unlock();
5848 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849}
5850
5851static int selinux_setprocattr(struct task_struct *p,
5852 char *name, void *value, size_t size)
5853{
5854 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11005855 struct cred *new;
5856 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857 int error;
5858 char *str = value;
5859
5860 if (current != p) {
5861 /* SELinux only allows a process to change its own
5862 security attributes. */
5863 return -EACCES;
5864 }
5865
5866 /*
5867 * Basic control over ability to set these attributes at all.
5868 * current == p, but we'll pass them separately in case the
5869 * above restriction is ever removed.
5870 */
5871 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005872 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005874 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005875 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005876 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005877 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005878 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005880 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881 else
5882 error = -EINVAL;
5883 if (error)
5884 return error;
5885
5886 /* Obtain a SID for the context, if one was specified. */
5887 if (size && str[1] && str[1] != '\n') {
5888 if (str[size-1] == '\n') {
5889 str[size-1] = 0;
5890 size--;
5891 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005892 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005893 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005894 if (!capable(CAP_MAC_ADMIN)) {
5895 struct audit_buffer *ab;
5896 size_t audit_size;
5897
5898 /* We strip a nul only if it is at the end, otherwise the
5899 * context contains a nul and we should audit that */
5900 if (str[size - 1] == '\0')
5901 audit_size = size - 1;
5902 else
5903 audit_size = size;
5904 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5905 audit_log_format(ab, "op=fscreate invalid_context=");
5906 audit_log_n_untrustedstring(ab, value, audit_size);
5907 audit_log_end(ab);
5908
Stephen Smalley12b29f32008-05-07 13:03:20 -04005909 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005910 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005911 error = security_context_to_sid_force(value, size,
5912 &sid);
5913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914 if (error)
5915 return error;
5916 }
5917
David Howellsd84f4f92008-11-14 10:39:23 +11005918 new = prepare_creds();
5919 if (!new)
5920 return -ENOMEM;
5921
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922 /* Permission checking based on the specified context is
5923 performed during the actual operation (execve,
5924 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005925 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926 checks and may_create for the file creation checks. The
5927 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005928 tsec = new->security;
5929 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005931 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005933 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005934 error = may_create_key(sid, p);
5935 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005936 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005937 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005938 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005939 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005940 } else if (!strcmp(name, "current")) {
5941 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005943 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005944
David Howellsd84f4f92008-11-14 10:39:23 +11005945 /* Only allow single threaded processes to change context */
5946 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005947 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005948 error = security_bounded_transition(tsec->sid, sid);
5949 if (error)
5950 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
5953 /* Check permissions for the transition. */
5954 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005955 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005957 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958
5959 /* Check for ptracing, and update the task SID if ok.
5960 Otherwise, leave SID unchanged and fail. */
Paul Moore0c6181c2016-03-30 21:41:21 -04005961 ptsid = ptrace_parent_sid(p);
5962 if (ptsid != 0) {
David Howellsd84f4f92008-11-14 10:39:23 +11005963 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5964 PROCESS__PTRACE, NULL);
5965 if (error)
5966 goto abort_change;
5967 }
5968
5969 tsec->sid = sid;
5970 } else {
5971 error = -EINVAL;
5972 goto abort_change;
5973 }
5974
5975 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005977
5978abort_change:
5979 abort_creds(new);
5980 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981}
5982
David Quigley746df9b2013-05-22 12:50:35 -04005983static int selinux_ismaclabel(const char *name)
5984{
5985 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5986}
5987
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005988static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5989{
5990 return security_sid_to_context(secid, secdata, seclen);
5991}
5992
David Howells7bf570d2008-04-29 20:52:51 +01005993static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005994{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005995 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005996}
5997
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005998static void selinux_release_secctx(char *secdata, u32 seclen)
5999{
Paul Moore088999e2007-08-01 11:12:58 -04006000 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006001}
6002
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006003static void selinux_inode_invalidate_secctx(struct inode *inode)
6004{
6005 struct inode_security_struct *isec = inode->i_security;
6006
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006007 spin_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006008 isec->initialized = LABEL_INVALID;
Andreas Gruenbacher9287aed2016-11-15 11:06:40 +01006009 spin_unlock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006010}
6011
David P. Quigley1ee65e32009-09-03 14:25:57 -04006012/*
6013 * called with inode->i_mutex locked
6014 */
6015static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6016{
6017 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6018}
6019
6020/*
6021 * called with inode->i_mutex locked
6022 */
6023static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6024{
6025 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6026}
6027
6028static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6029{
6030 int len = 0;
6031 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6032 ctx, true);
6033 if (len < 0)
6034 return len;
6035 *ctxlen = len;
6036 return 0;
6037}
Michael LeMayd7200242006-06-22 14:47:17 -07006038#ifdef CONFIG_KEYS
6039
David Howellsd84f4f92008-11-14 10:39:23 +11006040static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006041 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006042{
David Howellsd84f4f92008-11-14 10:39:23 +11006043 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006044 struct key_security_struct *ksec;
6045
6046 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6047 if (!ksec)
6048 return -ENOMEM;
6049
David Howellsd84f4f92008-11-14 10:39:23 +11006050 tsec = cred->security;
6051 if (tsec->keycreate_sid)
6052 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006053 else
David Howellsd84f4f92008-11-14 10:39:23 +11006054 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006055
David Howells275bb412008-11-14 10:39:19 +11006056 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006057 return 0;
6058}
6059
6060static void selinux_key_free(struct key *k)
6061{
6062 struct key_security_struct *ksec = k->security;
6063
6064 k->security = NULL;
6065 kfree(ksec);
6066}
6067
6068static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006069 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006070 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006071{
6072 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006073 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006074 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006075
6076 /* if no specific permissions are requested, we skip the
6077 permission check. No serious, additional covert channels
6078 appear to be created. */
6079 if (perm == 0)
6080 return 0;
6081
David Howellsd84f4f92008-11-14 10:39:23 +11006082 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006083
6084 key = key_ref_to_ptr(key_ref);
6085 ksec = key->security;
6086
6087 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006088}
6089
David Howells70a5bb72008-04-29 01:01:26 -07006090static int selinux_key_getsecurity(struct key *key, char **_buffer)
6091{
6092 struct key_security_struct *ksec = key->security;
6093 char *context = NULL;
6094 unsigned len;
6095 int rc;
6096
6097 rc = security_sid_to_context(ksec->sid, &context, &len);
6098 if (!rc)
6099 rc = len;
6100 *_buffer = context;
6101 return rc;
6102}
6103
Michael LeMayd7200242006-06-22 14:47:17 -07006104#endif
6105
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006106static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006107 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6108 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6109 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6110 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006111
Casey Schauflere20b0432015-05-02 15:11:36 -07006112 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6113 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6114 LSM_HOOK_INIT(capget, selinux_capget),
6115 LSM_HOOK_INIT(capset, selinux_capset),
6116 LSM_HOOK_INIT(capable, selinux_capable),
6117 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6118 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6119 LSM_HOOK_INIT(syslog, selinux_syslog),
6120 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006121
Casey Schauflere20b0432015-05-02 15:11:36 -07006122 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123
Casey Schauflere20b0432015-05-02 15:11:36 -07006124 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6125 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6126 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
6127 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128
Casey Schauflere20b0432015-05-02 15:11:36 -07006129 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6130 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
6131 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
6132 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6133 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6134 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6135 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6136 LSM_HOOK_INIT(sb_mount, selinux_mount),
6137 LSM_HOOK_INIT(sb_umount, selinux_umount),
6138 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6139 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
6140 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141
Casey Schauflere20b0432015-05-02 15:11:36 -07006142 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006143 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006144
Casey Schauflere20b0432015-05-02 15:11:36 -07006145 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6146 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6147 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6148 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6149 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6150 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6151 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6152 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6153 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6154 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6155 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6156 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6157 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6158 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6159 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6160 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6161 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6162 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6163 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6164 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6165 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6166 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6167 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6168 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6169 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006170 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006171 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172
Casey Schauflere20b0432015-05-02 15:11:36 -07006173 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6174 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6175 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6176 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6177 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6178 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6179 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6180 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6181 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6182 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6183 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6184 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006185
Casey Schauflere20b0432015-05-02 15:11:36 -07006186 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Casey Schauflere20b0432015-05-02 15:11:36 -07006188 LSM_HOOK_INIT(task_create, selinux_task_create),
6189 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6190 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6191 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6192 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
6193 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6194 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6195 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Jeff Vander Stoep61d612ea2016-04-05 13:06:27 -07006196 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006197 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6198 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6199 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6200 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6201 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6202 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6203 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
6204 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6205 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6206 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6207 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6208 LSM_HOOK_INIT(task_kill, selinux_task_kill),
6209 LSM_HOOK_INIT(task_wait, selinux_task_wait),
6210 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006211
Casey Schauflere20b0432015-05-02 15:11:36 -07006212 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6213 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214
Casey Schauflere20b0432015-05-02 15:11:36 -07006215 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6216 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217
Casey Schauflere20b0432015-05-02 15:11:36 -07006218 LSM_HOOK_INIT(msg_queue_alloc_security,
6219 selinux_msg_queue_alloc_security),
6220 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6221 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6222 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6223 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6224 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Casey Schauflere20b0432015-05-02 15:11:36 -07006226 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6227 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6228 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6229 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6230 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006231
Casey Schauflere20b0432015-05-02 15:11:36 -07006232 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6233 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6234 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6235 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6236 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237
Casey Schauflere20b0432015-05-02 15:11:36 -07006238 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006239
Casey Schauflere20b0432015-05-02 15:11:36 -07006240 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6241 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242
Casey Schauflere20b0432015-05-02 15:11:36 -07006243 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6244 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6245 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6246 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006247 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006248 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6249 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6250 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251
Casey Schauflere20b0432015-05-02 15:11:36 -07006252 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6253 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006254
Casey Schauflere20b0432015-05-02 15:11:36 -07006255 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6256 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6257 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6258 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6259 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6260 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6261 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6262 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6263 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6264 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6265 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6266 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6267 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6268 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6269 LSM_HOOK_INIT(socket_getpeersec_stream,
6270 selinux_socket_getpeersec_stream),
6271 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6272 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6273 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6274 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6275 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6276 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6277 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6278 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6279 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6280 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6281 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6282 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6283 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6284 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6285 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6286 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6287 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6288 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6289 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006290
6291#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006292 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6293 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6294 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6295 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6296 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6297 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6298 selinux_xfrm_state_alloc_acquire),
6299 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6300 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6301 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6302 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6303 selinux_xfrm_state_pol_flow_match),
6304 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006305#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006306
6307#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006308 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6309 LSM_HOOK_INIT(key_free, selinux_key_free),
6310 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6311 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006312#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006313
6314#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006315 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6316 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6317 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6318 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006319#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320};
6321
6322static __init int selinux_init(void)
6323{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006324 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006325 selinux_enabled = 0;
6326 return 0;
6327 }
6328
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329 if (!selinux_enabled) {
6330 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6331 return 0;
6332 }
6333
6334 printk(KERN_INFO "SELinux: Initializing.\n");
6335
6336 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006337 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006339 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6340
James Morris7cae7e22006-03-22 00:09:22 -08006341 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6342 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006343 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006344 file_security_cache = kmem_cache_create("selinux_file_security",
6345 sizeof(struct file_security_struct),
6346 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347 avc_init();
6348
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006349 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350
Paul Moore615e51f2014-06-26 14:33:56 -04006351 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6352 panic("SELinux: Unable to register AVC netcache callback\n");
6353
Eric Paris828dfe12008-04-17 13:17:49 -04006354 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006355 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006356 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006357 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006358
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359 return 0;
6360}
6361
Al Viroe8c26252010-03-23 06:36:54 -04006362static void delayed_superblock_init(struct super_block *sb, void *unused)
6363{
6364 superblock_doinit(sb, NULL);
6365}
6366
Linus Torvalds1da177e2005-04-16 15:20:36 -07006367void selinux_complete_init(void)
6368{
Eric Parisfadcdb42007-02-22 18:11:31 -05006369 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006370
6371 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006372 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006373 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374}
6375
6376/* SELinux requires early initialization in order to label
6377 all processes and objects when they are created. */
6378security_initcall(selinux_init);
6379
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006380#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006381
Jiri Pirko25db6be2014-09-03 17:42:13 +02006382static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006383 {
6384 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006385 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006386 .hooknum = NF_INET_POST_ROUTING,
6387 .priority = NF_IP_PRI_SELINUX_LAST,
6388 },
6389 {
6390 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006391 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006392 .hooknum = NF_INET_FORWARD,
6393 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006394 },
6395 {
6396 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006397 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006398 .hooknum = NF_INET_LOCAL_OUT,
6399 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006400 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04006401#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006402 {
6403 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006404 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006405 .hooknum = NF_INET_POST_ROUTING,
6406 .priority = NF_IP6_PRI_SELINUX_LAST,
6407 },
6408 {
6409 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006410 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006411 .hooknum = NF_INET_FORWARD,
6412 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006413 },
Huw Davies2917f572016-06-27 15:06:15 -04006414 {
6415 .hook = selinux_ipv6_output,
6416 .pf = NFPROTO_IPV6,
6417 .hooknum = NF_INET_LOCAL_OUT,
6418 .priority = NF_IP6_PRI_SELINUX_FIRST,
6419 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006421};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006422
6423static int __init selinux_nf_ip_init(void)
6424{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006425 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426
6427 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006428 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006429
6430 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6431
Jiri Pirko25db6be2014-09-03 17:42:13 +02006432 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006433 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006434 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435
Jiri Pirko25db6be2014-09-03 17:42:13 +02006436 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006437}
6438
6439__initcall(selinux_nf_ip_init);
6440
6441#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6442static void selinux_nf_ip_exit(void)
6443{
Eric Parisfadcdb42007-02-22 18:11:31 -05006444 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445
Jiri Pirko25db6be2014-09-03 17:42:13 +02006446 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447}
6448#endif
6449
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006450#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451
6452#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6453#define selinux_nf_ip_exit()
6454#endif
6455
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006456#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457
6458#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006459static int selinux_disabled;
6460
Linus Torvalds1da177e2005-04-16 15:20:36 -07006461int selinux_disable(void)
6462{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463 if (ss_initialized) {
6464 /* Not permitted after initial policy load. */
6465 return -EINVAL;
6466 }
6467
6468 if (selinux_disabled) {
6469 /* Only do this once. */
6470 return -EINVAL;
6471 }
6472
6473 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6474
6475 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006476 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006478 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479
Eric Parisaf8ff042009-09-20 21:23:01 -04006480 /* Try to destroy the avc node cache */
6481 avc_disable();
6482
Linus Torvalds1da177e2005-04-16 15:20:36 -07006483 /* Unregister netfilter hooks. */
6484 selinux_nf_ip_exit();
6485
6486 /* Unregister selinuxfs. */
6487 exit_sel_fs();
6488
6489 return 0;
6490}
6491#endif