blob: 70b8ac1893e44a1fe10e4e6b62554f2a46e8fa22 [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>
Chenbo Feng9b629132017-10-18 13:00:25 -070086#include <linux/bpf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88#include "avc.h"
89#include "objsec.h"
90#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050091#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040092#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080093#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050094#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020095#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100096#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Paul Moored621d352008-01-29 08:43:36 -050098/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100099static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400102int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104static int __init enforcing_setup(char *str)
105{
Eric Parisf5269712008-05-14 11:27:45 -0400106 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900107 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400108 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 return 1;
110}
111__setup("enforcing=", enforcing_setup);
112#endif
113
114#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
115int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
116
117static int __init selinux_enabled_setup(char *str)
118{
Eric Parisf5269712008-05-14 11:27:45 -0400119 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900120 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400121 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 return 1;
123}
124__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400125#else
126int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127#endif
128
Christoph Lametere18b8902006-12-06 20:33:20 -0800129static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400130static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800131
Paul Moored621d352008-01-29 08:43:36 -0500132/**
133 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
134 *
135 * Description:
136 * This function checks the SECMARK reference counter to see if any SECMARK
137 * targets are currently configured, if the reference counter is greater than
138 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400139 * enabled, false (0) if SECMARK is disabled. If the always_check_network
140 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500141 *
142 */
143static int selinux_secmark_enabled(void)
144{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400145 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
146}
147
148/**
149 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
150 *
151 * Description:
152 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
153 * (1) if any are enabled or false (0) if neither are enabled. If the
154 * always_check_network policy capability is enabled, peer labeling
155 * is always considered enabled.
156 *
157 */
158static int selinux_peerlbl_enabled(void)
159{
160 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500161}
162
Paul Moore615e51f2014-06-26 14:33:56 -0400163static int selinux_netcache_avc_callback(u32 event)
164{
165 if (event == AVC_CALLBACK_RESET) {
166 sel_netif_flush();
167 sel_netnode_flush();
168 sel_netport_flush();
169 synchronize_net();
170 }
171 return 0;
172}
173
David Howellsd84f4f92008-11-14 10:39:23 +1100174/*
175 * initialise the security for the init task
176 */
177static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
David Howells3b11a1d2008-11-14 10:39:26 +1100179 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 struct task_security_struct *tsec;
181
James Morris89d155e2005-10-30 14:59:21 -0800182 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100184 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
David Howellsd84f4f92008-11-14 10:39:23 +1100186 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100187 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189
David Howells275bb412008-11-14 10:39:19 +1100190/*
David Howells88e67f32008-11-14 10:39:21 +1100191 * get the security ID of a set of credentials
192 */
193static inline u32 cred_sid(const struct cred *cred)
194{
195 const struct task_security_struct *tsec;
196
197 tsec = cred->security;
198 return tsec->sid;
199}
200
201/*
David Howells3b11a1d2008-11-14 10:39:26 +1100202 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100203 */
204static inline u32 task_sid(const struct task_struct *task)
205{
David Howells275bb412008-11-14 10:39:19 +1100206 u32 sid;
207
208 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100209 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100210 rcu_read_unlock();
211 return sid;
212}
213
214/*
David Howells3b11a1d2008-11-14 10:39:26 +1100215 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100216 */
217static inline u32 current_sid(void)
218{
Paul Moore5fb49872010-04-22 14:46:19 -0400219 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100220
221 return tsec->sid;
222}
223
David Howells88e67f32008-11-14 10:39:21 +1100224/* Allocate and free functions for each kind of security blob. */
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226static int inode_alloc_security(struct inode *inode)
227{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100229 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
Josef Bacika02fe132008-04-04 09:35:05 +1100231 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 if (!isec)
233 return -ENOMEM;
234
Eric Paris23970742006-09-25 23:32:01 -0700235 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 isec->inode = inode;
238 isec->sid = SECINITSID_UNLABELED;
239 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100240 isec->task_sid = sid;
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
251 * allowed; when set to false, returns ERR_PTR(-ECHILD) when the label is
252 * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
253 * when no dentry is available, set it to NULL instead.
254 */
255static int __inode_security_revalidate(struct inode *inode,
256 struct dentry *opt_dentry,
257 bool may_sleep)
258{
259 struct inode_security_struct *isec = inode->i_security;
260
261 might_sleep_if(may_sleep);
262
Paul Moore1ac424762016-04-18 16:41:38 -0400263 if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500264 if (!may_sleep)
265 return -ECHILD;
266
267 /*
268 * Try reloading the inode security label. This will fail if
269 * @opt_dentry is NULL and no dentry for this inode can be
270 * found; in that case, continue using the old label.
271 */
272 inode_doinit_with_dentry(inode, opt_dentry);
273 }
274 return 0;
275}
276
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500277static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
278{
279 return inode->i_security;
280}
281
282static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
283{
284 int error;
285
286 error = __inode_security_revalidate(inode, NULL, !rcu);
287 if (error)
288 return ERR_PTR(error);
289 return inode->i_security;
290}
291
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500292/*
293 * Get the security label of an inode.
294 */
295static struct inode_security_struct *inode_security(struct inode *inode)
296{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500297 __inode_security_revalidate(inode, NULL, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500298 return inode->i_security;
299}
300
Paul Moore2c971652016-04-19 16:36:28 -0400301static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
302{
303 struct inode *inode = d_backing_inode(dentry);
304
305 return inode->i_security;
306}
307
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500308/*
309 * Get the security label of a dentry's backing inode.
310 */
311static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
312{
313 struct inode *inode = d_backing_inode(dentry);
314
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -0500315 __inode_security_revalidate(inode, dentry, true);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500316 return inode->i_security;
317}
318
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500319static void inode_free_rcu(struct rcu_head *head)
320{
321 struct inode_security_struct *isec;
322
323 isec = container_of(head, struct inode_security_struct, rcu);
324 kmem_cache_free(sel_inode_cache, isec);
325}
326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327static void inode_free_security(struct inode *inode)
328{
329 struct inode_security_struct *isec = inode->i_security;
330 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
331
Waiman Long9629d042015-07-10 17:19:56 -0400332 /*
333 * As not all inode security structures are in a list, we check for
334 * empty list outside of the lock to make sure that we won't waste
335 * time taking a lock doing nothing.
336 *
337 * The list_del_init() function can be safely called more than once.
338 * It should not be possible for this function to be called with
339 * concurrent list_add(), but for better safety against future changes
340 * in the code, we use list_empty_careful() here.
341 */
342 if (!list_empty_careful(&isec->list)) {
343 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400345 spin_unlock(&sbsec->isec_lock);
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500348 /*
349 * The inode may still be referenced in a path walk and
350 * a call to selinux_inode_permission() can be made
351 * after inode_free_security() is called. Ideally, the VFS
352 * wouldn't do this, but fixing that is a much harder
353 * job. For now, simply free the i_security via RCU, and
354 * leave the current inode->i_security pointer intact.
355 * The inode will be freed after the RCU grace period too.
356 */
357 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
360static int file_alloc_security(struct file *file)
361{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100363 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Sangwoo63205652015-10-21 17:44:30 -0400365 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (!fsec)
367 return -ENOMEM;
368
David Howells275bb412008-11-14 10:39:19 +1100369 fsec->sid = sid;
370 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 file->f_security = fsec;
372
373 return 0;
374}
375
376static void file_free_security(struct file *file)
377{
378 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400380 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
382
383static int superblock_alloc_security(struct super_block *sb)
384{
385 struct superblock_security_struct *sbsec;
386
James Morris89d155e2005-10-30 14:59:21 -0800387 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 if (!sbsec)
389 return -ENOMEM;
390
Eric Parisbc7e9822006-09-25 23:32:02 -0700391 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 INIT_LIST_HEAD(&sbsec->isec_head);
393 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 sbsec->sb = sb;
395 sbsec->sid = SECINITSID_UNLABELED;
396 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700397 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 sb->s_security = sbsec;
399
400 return 0;
401}
402
403static void superblock_free_security(struct super_block *sb)
404{
405 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 sb->s_security = NULL;
407 kfree(sbsec);
408}
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410static inline int inode_doinit(struct inode *inode)
411{
412 return inode_doinit_with_dentry(inode, NULL);
413}
414
415enum {
Eric Paris31e87932007-09-19 17:19:12 -0400416 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 Opt_context = 1,
418 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500419 Opt_defcontext = 3,
420 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500421 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400422 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423};
424
Eric Parisd355987f2012-08-24 15:58:53 -0400425#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
426
Steven Whitehousea447c092008-10-13 10:46:57 +0100427static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400428 {Opt_context, CONTEXT_STR "%s"},
429 {Opt_fscontext, FSCONTEXT_STR "%s"},
430 {Opt_defcontext, DEFCONTEXT_STR "%s"},
431 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500432 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400433 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434};
435
436#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
437
Eric Parisc312feb2006-07-10 04:43:53 -0700438static int may_context_mount_sb_relabel(u32 sid,
439 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100440 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700441{
David Howells275bb412008-11-14 10:39:19 +1100442 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700443 int rc;
444
445 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
446 FILESYSTEM__RELABELFROM, NULL);
447 if (rc)
448 return rc;
449
450 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
451 FILESYSTEM__RELABELTO, NULL);
452 return rc;
453}
454
Eric Paris08089252006-07-10 04:43:55 -0700455static int may_context_mount_inode_relabel(u32 sid,
456 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100457 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700458{
David Howells275bb412008-11-14 10:39:19 +1100459 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700460 int rc;
461 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
462 FILESYSTEM__RELABELFROM, NULL);
463 if (rc)
464 return rc;
465
466 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
467 FILESYSTEM__ASSOCIATE, NULL);
468 return rc;
469}
470
Eric Parisb43e7252012-10-10 14:27:35 -0400471static int selinux_is_sblabel_mnt(struct super_block *sb)
472{
473 struct superblock_security_struct *sbsec = sb->s_security;
474
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500475 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
476 sbsec->behavior == SECURITY_FS_USE_TRANS ||
477 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400478 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500479 /* Special handling. Genfs but also in-core setxattr handler */
480 !strcmp(sb->s_type->name, "sysfs") ||
481 !strcmp(sb->s_type->name, "pstore") ||
482 !strcmp(sb->s_type->name, "debugfs") ||
Yongqin Liu93f1d0b2016-04-28 13:53:36 +0800483 !strcmp(sb->s_type->name, "tracefs") ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500484 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400485}
486
Eric Parisc9180a52007-11-30 13:00:35 -0500487static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
489 struct superblock_security_struct *sbsec = sb->s_security;
490 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000491 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 int rc = 0;
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
495 /* Make sure that the xattr handler exists and that no
496 error other than -ENODATA is returned by getxattr on
497 the root directory. -ENODATA is ok, as this may be
498 the first boot of the SELinux kernel before we have
499 assigned xattr values to the filesystem. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200500 if (!(root_inode->i_opflags & IOP_XATTR)) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800501 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
502 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 rc = -EOPNOTSUPP;
504 goto out;
505 }
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +0200506
507 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (rc < 0 && rc != -ENODATA) {
509 if (rc == -EOPNOTSUPP)
510 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800511 "%s) has no security xattr handler\n",
512 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 else
514 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800515 "%s) getxattr errno %d\n", sb->s_id,
516 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 goto out;
518 }
519 }
520
Eric Pariseadcabc2012-08-24 15:59:14 -0400521 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400522 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400523 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500526 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 /* Initialize any other inodes associated with the superblock, e.g.
529 inodes created prior to initial policy load or inodes created
530 during get_sb by a pseudo filesystem that directly
531 populates itself. */
532 spin_lock(&sbsec->isec_lock);
533next_inode:
534 if (!list_empty(&sbsec->isec_head)) {
535 struct inode_security_struct *isec =
536 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500537 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400539 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 spin_unlock(&sbsec->isec_lock);
541 inode = igrab(inode);
542 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500543 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 inode_doinit(inode);
545 iput(inode);
546 }
547 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 goto next_inode;
549 }
550 spin_unlock(&sbsec->isec_lock);
551out:
Eric Parisc9180a52007-11-30 13:00:35 -0500552 return rc;
553}
554
555/*
556 * This function should allow an FS to ask what it's mount security
557 * options were so it can use those later for submounts, displaying
558 * mount options, or whatever.
559 */
560static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500561 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500562{
563 int rc = 0, i;
564 struct superblock_security_struct *sbsec = sb->s_security;
565 char *context = NULL;
566 u32 len;
567 char tmp;
568
Eric Parise0007522008-03-05 10:31:54 -0500569 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500570
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500571 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500572 return -EINVAL;
573
574 if (!ss_initialized)
575 return -EINVAL;
576
Eric Parisaf8e50c2012-08-24 15:59:00 -0400577 /* make sure we always check enough bits to cover the mask */
578 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
579
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500580 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500581 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400582 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500583 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500584 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500585 tmp >>= 1;
586 }
David P. Quigley11689d42009-01-16 09:22:03 -0500587 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400588 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500589 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500590
Eric Parise0007522008-03-05 10:31:54 -0500591 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
592 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500593 rc = -ENOMEM;
594 goto out_free;
595 }
596
Eric Parise0007522008-03-05 10:31:54 -0500597 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
598 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500599 rc = -ENOMEM;
600 goto out_free;
601 }
602
603 i = 0;
604 if (sbsec->flags & FSCONTEXT_MNT) {
605 rc = security_sid_to_context(sbsec->sid, &context, &len);
606 if (rc)
607 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500608 opts->mnt_opts[i] = context;
609 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500610 }
611 if (sbsec->flags & CONTEXT_MNT) {
612 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
613 if (rc)
614 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500615 opts->mnt_opts[i] = context;
616 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500617 }
618 if (sbsec->flags & DEFCONTEXT_MNT) {
619 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
620 if (rc)
621 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500622 opts->mnt_opts[i] = context;
623 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500624 }
625 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500626 struct dentry *root = sbsec->sb->s_root;
627 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500628
629 rc = security_sid_to_context(isec->sid, &context, &len);
630 if (rc)
631 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500632 opts->mnt_opts[i] = context;
633 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500634 }
Eric Paris12f348b2012-10-09 10:56:25 -0400635 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500636 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400637 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500638 }
Eric Parisc9180a52007-11-30 13:00:35 -0500639
Eric Parise0007522008-03-05 10:31:54 -0500640 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500641
642 return 0;
643
644out_free:
Eric Parise0007522008-03-05 10:31:54 -0500645 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500646 return rc;
647}
648
649static int bad_option(struct superblock_security_struct *sbsec, char flag,
650 u32 old_sid, u32 new_sid)
651{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500652 char mnt_flags = sbsec->flags & SE_MNTMASK;
653
Eric Parisc9180a52007-11-30 13:00:35 -0500654 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500655 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500656 if (!(sbsec->flags & flag) ||
657 (old_sid != new_sid))
658 return 1;
659
660 /* check if we were passed the same options twice,
661 * aka someone passed context=a,context=b
662 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500663 if (!(sbsec->flags & SE_SBINITIALIZED))
664 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500665 return 1;
666 return 0;
667}
Eric Parise0007522008-03-05 10:31:54 -0500668
Eric Parisc9180a52007-11-30 13:00:35 -0500669/*
670 * Allow filesystems with binary mount data to explicitly set mount point
671 * labeling information.
672 */
Eric Parise0007522008-03-05 10:31:54 -0500673static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400674 struct security_mnt_opts *opts,
675 unsigned long kern_flags,
676 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500677{
David Howells275bb412008-11-14 10:39:19 +1100678 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500679 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500680 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800681 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500682 struct dentry *root = sbsec->sb->s_root;
Paul Moore2c971652016-04-19 16:36:28 -0400683 struct inode_security_struct *root_isec;
Eric Parisc9180a52007-11-30 13:00:35 -0500684 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
685 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500686 char **mount_options = opts->mnt_opts;
687 int *flags = opts->mnt_opts_flags;
688 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500689
690 mutex_lock(&sbsec->lock);
691
692 if (!ss_initialized) {
693 if (!num_opts) {
694 /* Defer initialization until selinux_complete_init,
695 after the initial policy is loaded and the security
696 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500697 goto out;
698 }
699 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400700 printk(KERN_WARNING "SELinux: Unable to set superblock options "
701 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500702 goto out;
703 }
David Quigley649f6e72013-05-22 12:50:36 -0400704 if (kern_flags && !set_kern_flags) {
705 /* Specifying internal flags without providing a place to
706 * place the results is not allowed */
707 rc = -EINVAL;
708 goto out;
709 }
Eric Parisc9180a52007-11-30 13:00:35 -0500710
711 /*
Eric Parise0007522008-03-05 10:31:54 -0500712 * Binary mount data FS will come through this function twice. Once
713 * from an explicit call and once from the generic calls from the vfs.
714 * Since the generic VFS calls will not contain any security mount data
715 * we need to skip the double mount verification.
716 *
717 * This does open a hole in which we will not notice if the first
718 * mount using this sb set explict options and a second mount using
719 * this sb does not set any security options. (The first options
720 * will be used for both mounts)
721 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500722 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500723 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400724 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500725
Paul Moore2c971652016-04-19 16:36:28 -0400726 root_isec = backing_inode_security_novalidate(root);
727
Eric Parise0007522008-03-05 10:31:54 -0500728 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500729 * parse the mount options, check if they are valid sids.
730 * also check if someone is trying to mount the same sb more
731 * than once with different security options.
732 */
733 for (i = 0; i < num_opts; i++) {
734 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500735
Eric Paris12f348b2012-10-09 10:56:25 -0400736 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500737 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400738 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500739 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400740 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800741 "(%s) failed for (dev %s, type %s) errno=%d\n",
742 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500743 goto out;
744 }
745 switch (flags[i]) {
746 case FSCONTEXT_MNT:
747 fscontext_sid = sid;
748
749 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
750 fscontext_sid))
751 goto out_double_mount;
752
753 sbsec->flags |= FSCONTEXT_MNT;
754 break;
755 case CONTEXT_MNT:
756 context_sid = sid;
757
758 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
759 context_sid))
760 goto out_double_mount;
761
762 sbsec->flags |= CONTEXT_MNT;
763 break;
764 case ROOTCONTEXT_MNT:
765 rootcontext_sid = sid;
766
767 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
768 rootcontext_sid))
769 goto out_double_mount;
770
771 sbsec->flags |= ROOTCONTEXT_MNT;
772
773 break;
774 case DEFCONTEXT_MNT:
775 defcontext_sid = sid;
776
777 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
778 defcontext_sid))
779 goto out_double_mount;
780
781 sbsec->flags |= DEFCONTEXT_MNT;
782
783 break;
784 default:
785 rc = -EINVAL;
786 goto out;
787 }
788 }
789
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500790 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500791 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500792 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500793 goto out_double_mount;
794 rc = 0;
795 goto out;
796 }
797
James Morris089be432008-07-15 18:32:49 +1000798 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400799 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
800
Stephen Smalley8e014722015-06-04 16:22:17 -0400801 if (!strcmp(sb->s_type->name, "debugfs") ||
Jeff Vander Stoep8bdee6782017-06-20 09:35:33 -0700802 !strcmp(sb->s_type->name, "tracefs") ||
Stephen Smalley8e014722015-06-04 16:22:17 -0400803 !strcmp(sb->s_type->name, "sysfs") ||
804 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400805 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500806
David Quigleyeb9ae682013-05-22 12:50:37 -0400807 if (!sbsec->behavior) {
808 /*
809 * Determine the labeling behavior to use for this
810 * filesystem type.
811 */
Paul Moore98f700f2013-09-18 13:52:20 -0400812 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400813 if (rc) {
814 printk(KERN_WARNING
815 "%s: security_fs_use(%s) returned %d\n",
816 __func__, sb->s_type->name, rc);
817 goto out;
818 }
Eric Parisc9180a52007-11-30 13:00:35 -0500819 }
Seth Forsheeaad82892016-04-26 14:36:20 -0500820
821 /*
822 * If this is a user namespace mount, no contexts are allowed
823 * on the command line and security labels must be ignored.
824 */
825 if (sb->s_user_ns != &init_user_ns) {
826 if (context_sid || fscontext_sid || rootcontext_sid ||
827 defcontext_sid) {
828 rc = -EACCES;
829 goto out;
830 }
831 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
832 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
833 rc = security_transition_sid(current_sid(), current_sid(),
834 SECCLASS_FILE, NULL,
835 &sbsec->mntpoint_sid);
836 if (rc)
837 goto out;
838 }
839 goto out_set_opts;
840 }
841
Eric Parisc9180a52007-11-30 13:00:35 -0500842 /* sets the context of the superblock for the fs being mounted. */
843 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100844 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500845 if (rc)
846 goto out;
847
848 sbsec->sid = fscontext_sid;
849 }
850
851 /*
852 * Switch to using mount point labeling behavior.
853 * sets the label used on all file below the mountpoint, and will set
854 * the superblock context if not already set.
855 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400856 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
857 sbsec->behavior = SECURITY_FS_USE_NATIVE;
858 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
859 }
860
Eric Parisc9180a52007-11-30 13:00:35 -0500861 if (context_sid) {
862 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100863 rc = may_context_mount_sb_relabel(context_sid, sbsec,
864 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500865 if (rc)
866 goto out;
867 sbsec->sid = context_sid;
868 } else {
David Howells275bb412008-11-14 10:39:19 +1100869 rc = may_context_mount_inode_relabel(context_sid, sbsec,
870 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500871 if (rc)
872 goto out;
873 }
874 if (!rootcontext_sid)
875 rootcontext_sid = context_sid;
876
877 sbsec->mntpoint_sid = context_sid;
878 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
879 }
880
881 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100882 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
883 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500884 if (rc)
885 goto out;
886
887 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500888 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500889 }
890
891 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400892 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
893 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500894 rc = -EINVAL;
895 printk(KERN_WARNING "SELinux: defcontext option is "
896 "invalid for this filesystem type\n");
897 goto out;
898 }
899
900 if (defcontext_sid != sbsec->def_sid) {
901 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100902 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500903 if (rc)
904 goto out;
905 }
906
907 sbsec->def_sid = defcontext_sid;
908 }
909
Seth Forsheeaad82892016-04-26 14:36:20 -0500910out_set_opts:
Eric Parisc9180a52007-11-30 13:00:35 -0500911 rc = sb_finish_set_opts(sb);
912out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700913 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500915out_double_mount:
916 rc = -EINVAL;
917 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800918 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500919 goto out;
920}
921
Jeff Layton094f7b62013-04-01 08:14:24 -0400922static int selinux_cmp_sb_context(const struct super_block *oldsb,
923 const struct super_block *newsb)
924{
925 struct superblock_security_struct *old = oldsb->s_security;
926 struct superblock_security_struct *new = newsb->s_security;
927 char oldflags = old->flags & SE_MNTMASK;
928 char newflags = new->flags & SE_MNTMASK;
929
930 if (oldflags != newflags)
931 goto mismatch;
932 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
933 goto mismatch;
934 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
935 goto mismatch;
936 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
937 goto mismatch;
938 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500939 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
940 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400941 if (oldroot->sid != newroot->sid)
942 goto mismatch;
943 }
944 return 0;
945mismatch:
946 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
947 "different security settings for (dev %s, "
948 "type %s)\n", newsb->s_id, newsb->s_type->name);
949 return -EBUSY;
950}
951
952static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500953 struct super_block *newsb)
954{
955 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
956 struct superblock_security_struct *newsbsec = newsb->s_security;
957
958 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
959 int set_context = (oldsbsec->flags & CONTEXT_MNT);
960 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
961
Eric Paris0f5e6422008-04-21 16:24:11 -0400962 /*
963 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400964 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400965 */
Al Viroe8c26252010-03-23 06:36:54 -0400966 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400967 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500968
Eric Parisc9180a52007-11-30 13:00:35 -0500969 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500970 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500971
Jeff Layton094f7b62013-04-01 08:14:24 -0400972 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500973 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400974 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400975
Eric Parisc9180a52007-11-30 13:00:35 -0500976 mutex_lock(&newsbsec->lock);
977
978 newsbsec->flags = oldsbsec->flags;
979
980 newsbsec->sid = oldsbsec->sid;
981 newsbsec->def_sid = oldsbsec->def_sid;
982 newsbsec->behavior = oldsbsec->behavior;
983
984 if (set_context) {
985 u32 sid = oldsbsec->mntpoint_sid;
986
987 if (!set_fscontext)
988 newsbsec->sid = sid;
989 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500990 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500991 newisec->sid = sid;
992 }
993 newsbsec->mntpoint_sid = sid;
994 }
995 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500996 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
997 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500998
999 newisec->sid = oldisec->sid;
1000 }
1001
1002 sb_finish_set_opts(newsb);
1003 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -04001004 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001005}
1006
Adrian Bunk2e1479d2008-03-17 22:29:23 +02001007static int selinux_parse_opts_str(char *options,
1008 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -05001009{
Eric Parise0007522008-03-05 10:31:54 -05001010 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -05001011 char *context = NULL, *defcontext = NULL;
1012 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -05001013 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001014
Eric Parise0007522008-03-05 10:31:54 -05001015 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -05001016
1017 /* Standard string-based options. */
1018 while ((p = strsep(&options, "|")) != NULL) {
1019 int token;
1020 substring_t args[MAX_OPT_ARGS];
1021
1022 if (!*p)
1023 continue;
1024
1025 token = match_token(p, tokens, args);
1026
1027 switch (token) {
1028 case Opt_context:
1029 if (context || defcontext) {
1030 rc = -EINVAL;
1031 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1032 goto out_err;
1033 }
1034 context = match_strdup(&args[0]);
1035 if (!context) {
1036 rc = -ENOMEM;
1037 goto out_err;
1038 }
1039 break;
1040
1041 case Opt_fscontext:
1042 if (fscontext) {
1043 rc = -EINVAL;
1044 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1045 goto out_err;
1046 }
1047 fscontext = match_strdup(&args[0]);
1048 if (!fscontext) {
1049 rc = -ENOMEM;
1050 goto out_err;
1051 }
1052 break;
1053
1054 case Opt_rootcontext:
1055 if (rootcontext) {
1056 rc = -EINVAL;
1057 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1058 goto out_err;
1059 }
1060 rootcontext = match_strdup(&args[0]);
1061 if (!rootcontext) {
1062 rc = -ENOMEM;
1063 goto out_err;
1064 }
1065 break;
1066
1067 case Opt_defcontext:
1068 if (context || defcontext) {
1069 rc = -EINVAL;
1070 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1071 goto out_err;
1072 }
1073 defcontext = match_strdup(&args[0]);
1074 if (!defcontext) {
1075 rc = -ENOMEM;
1076 goto out_err;
1077 }
1078 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001079 case Opt_labelsupport:
1080 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001081 default:
1082 rc = -EINVAL;
1083 printk(KERN_WARNING "SELinux: unknown mount option\n");
1084 goto out_err;
1085
1086 }
1087 }
1088
Eric Parise0007522008-03-05 10:31:54 -05001089 rc = -ENOMEM;
1090 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1091 if (!opts->mnt_opts)
1092 goto out_err;
1093
1094 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1095 if (!opts->mnt_opts_flags) {
1096 kfree(opts->mnt_opts);
1097 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001098 }
1099
Eric Parise0007522008-03-05 10:31:54 -05001100 if (fscontext) {
1101 opts->mnt_opts[num_mnt_opts] = fscontext;
1102 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1103 }
1104 if (context) {
1105 opts->mnt_opts[num_mnt_opts] = context;
1106 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1107 }
1108 if (rootcontext) {
1109 opts->mnt_opts[num_mnt_opts] = rootcontext;
1110 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1111 }
1112 if (defcontext) {
1113 opts->mnt_opts[num_mnt_opts] = defcontext;
1114 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1115 }
1116
1117 opts->num_mnt_opts = num_mnt_opts;
1118 return 0;
1119
Eric Parisc9180a52007-11-30 13:00:35 -05001120out_err:
1121 kfree(context);
1122 kfree(defcontext);
1123 kfree(fscontext);
1124 kfree(rootcontext);
1125 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126}
Eric Parise0007522008-03-05 10:31:54 -05001127/*
1128 * string mount options parsing and call set the sbsec
1129 */
1130static int superblock_doinit(struct super_block *sb, void *data)
1131{
1132 int rc = 0;
1133 char *options = data;
1134 struct security_mnt_opts opts;
1135
1136 security_init_mnt_opts(&opts);
1137
1138 if (!data)
1139 goto out;
1140
1141 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1142
1143 rc = selinux_parse_opts_str(options, &opts);
1144 if (rc)
1145 goto out_err;
1146
1147out:
David Quigley649f6e72013-05-22 12:50:36 -04001148 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001149
1150out_err:
1151 security_free_mnt_opts(&opts);
1152 return rc;
1153}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Adrian Bunk3583a712008-07-22 20:21:23 +03001155static void selinux_write_opts(struct seq_file *m,
1156 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001157{
1158 int i;
1159 char *prefix;
1160
1161 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001162 char *has_comma;
1163
1164 if (opts->mnt_opts[i])
1165 has_comma = strchr(opts->mnt_opts[i], ',');
1166 else
1167 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001168
1169 switch (opts->mnt_opts_flags[i]) {
1170 case CONTEXT_MNT:
1171 prefix = CONTEXT_STR;
1172 break;
1173 case FSCONTEXT_MNT:
1174 prefix = FSCONTEXT_STR;
1175 break;
1176 case ROOTCONTEXT_MNT:
1177 prefix = ROOTCONTEXT_STR;
1178 break;
1179 case DEFCONTEXT_MNT:
1180 prefix = DEFCONTEXT_STR;
1181 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001182 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001183 seq_putc(m, ',');
1184 seq_puts(m, LABELSUPP_STR);
1185 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001186 default:
1187 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001188 return;
Eric Paris2069f452008-07-04 09:47:13 +10001189 };
1190 /* we need a comma before each option */
1191 seq_putc(m, ',');
1192 seq_puts(m, prefix);
1193 if (has_comma)
1194 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001195 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001196 if (has_comma)
1197 seq_putc(m, '\"');
1198 }
1199}
1200
1201static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1202{
1203 struct security_mnt_opts opts;
1204 int rc;
1205
1206 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001207 if (rc) {
1208 /* before policy load we may get EINVAL, don't show anything */
1209 if (rc == -EINVAL)
1210 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001211 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001212 }
Eric Paris2069f452008-07-04 09:47:13 +10001213
1214 selinux_write_opts(m, &opts);
1215
1216 security_free_mnt_opts(&opts);
1217
1218 return rc;
1219}
1220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221static inline u16 inode_mode_to_security_class(umode_t mode)
1222{
1223 switch (mode & S_IFMT) {
1224 case S_IFSOCK:
1225 return SECCLASS_SOCK_FILE;
1226 case S_IFLNK:
1227 return SECCLASS_LNK_FILE;
1228 case S_IFREG:
1229 return SECCLASS_FILE;
1230 case S_IFBLK:
1231 return SECCLASS_BLK_FILE;
1232 case S_IFDIR:
1233 return SECCLASS_DIR;
1234 case S_IFCHR:
1235 return SECCLASS_CHR_FILE;
1236 case S_IFIFO:
1237 return SECCLASS_FIFO_FILE;
1238
1239 }
1240
1241 return SECCLASS_FILE;
1242}
1243
James Morris13402582005-09-30 14:24:34 -04001244static inline int default_protocol_stream(int protocol)
1245{
1246 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1247}
1248
1249static inline int default_protocol_dgram(int protocol)
1250{
1251 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1252}
1253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1255{
1256 switch (family) {
1257 case PF_UNIX:
1258 switch (type) {
1259 case SOCK_STREAM:
1260 case SOCK_SEQPACKET:
1261 return SECCLASS_UNIX_STREAM_SOCKET;
1262 case SOCK_DGRAM:
1263 return SECCLASS_UNIX_DGRAM_SOCKET;
1264 }
1265 break;
1266 case PF_INET:
1267 case PF_INET6:
1268 switch (type) {
1269 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001270 if (default_protocol_stream(protocol))
1271 return SECCLASS_TCP_SOCKET;
1272 else
1273 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001275 if (default_protocol_dgram(protocol))
1276 return SECCLASS_UDP_SOCKET;
1277 else
1278 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001279 case SOCK_DCCP:
1280 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001281 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return SECCLASS_RAWIP_SOCKET;
1283 }
1284 break;
1285 case PF_NETLINK:
1286 switch (protocol) {
1287 case NETLINK_ROUTE:
1288 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001289 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1291 case NETLINK_NFLOG:
1292 return SECCLASS_NETLINK_NFLOG_SOCKET;
1293 case NETLINK_XFRM:
1294 return SECCLASS_NETLINK_XFRM_SOCKET;
1295 case NETLINK_SELINUX:
1296 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001297 case NETLINK_ISCSI:
1298 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 case NETLINK_AUDIT:
1300 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001301 case NETLINK_FIB_LOOKUP:
1302 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1303 case NETLINK_CONNECTOR:
1304 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1305 case NETLINK_NETFILTER:
1306 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 case NETLINK_DNRTMSG:
1308 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001309 case NETLINK_KOBJECT_UEVENT:
1310 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001311 case NETLINK_GENERIC:
1312 return SECCLASS_NETLINK_GENERIC_SOCKET;
1313 case NETLINK_SCSITRANSPORT:
1314 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1315 case NETLINK_RDMA:
1316 return SECCLASS_NETLINK_RDMA_SOCKET;
1317 case NETLINK_CRYPTO:
1318 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 default:
1320 return SECCLASS_NETLINK_SOCKET;
1321 }
1322 case PF_PACKET:
1323 return SECCLASS_PACKET_SOCKET;
1324 case PF_KEY:
1325 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001326 case PF_APPLETALK:
1327 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
1329
1330 return SECCLASS_SOCKET;
1331}
1332
Stephen Smalley134509d2015-06-04 16:22:17 -04001333static int selinux_genfs_get_sid(struct dentry *dentry,
1334 u16 tclass,
1335 u16 flags,
1336 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001338 int rc;
Al Virofc640052016-04-10 01:33:30 -04001339 struct super_block *sb = dentry->d_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001340 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Eric Paris828dfe12008-04-17 13:17:49 -04001342 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 if (!buffer)
1344 return -ENOMEM;
1345
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001346 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1347 if (IS_ERR(path))
1348 rc = PTR_ERR(path);
1349 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001350 if (flags & SE_SBPROC) {
1351 /* each process gets a /proc/PID/ entry. Strip off the
1352 * PID part to get a valid selinux labeling.
1353 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1354 while (path[1] >= '0' && path[1] <= '9') {
1355 path[1] = '/';
1356 path++;
1357 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001358 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001359 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 free_page((unsigned long)buffer);
1362 return rc;
1363}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365/* The inode's security attributes must be initialized before first use. */
1366static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1367{
1368 struct superblock_security_struct *sbsec = NULL;
1369 struct inode_security_struct *isec = inode->i_security;
1370 u32 sid;
1371 struct dentry *dentry;
1372#define INITCONTEXTLEN 255
1373 char *context = NULL;
1374 unsigned len = 0;
1375 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001377 if (isec->initialized == LABEL_INITIALIZED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 goto out;
1379
Eric Paris23970742006-09-25 23:32:01 -07001380 mutex_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001381 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001382 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
1384 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001385 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 /* Defer initialization until selinux_complete_init,
1387 after the initial policy is loaded and the security
1388 server is ready to handle calls. */
1389 spin_lock(&sbsec->isec_lock);
1390 if (list_empty(&isec->list))
1391 list_add(&isec->list, &sbsec->isec_head);
1392 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001393 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 }
1395
1396 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001397 case SECURITY_FS_USE_NATIVE:
1398 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 case SECURITY_FS_USE_XATTR:
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001400 if (!(inode->i_opflags & IOP_XATTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 isec->sid = sbsec->def_sid;
1402 break;
1403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 /* Need a dentry, since the xattr API requires one.
1405 Life would be simpler if we could just pass the inode. */
1406 if (opt_dentry) {
1407 /* Called from d_instantiate or d_splice_alias. */
1408 dentry = dget(opt_dentry);
1409 } else {
1410 /* Called from selinux_complete_init, try to find a dentry. */
1411 dentry = d_find_alias(inode);
1412 }
1413 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001414 /*
1415 * this is can be hit on boot when a file is accessed
1416 * before the policy is loaded. When we load policy we
1417 * may find inodes that have no dentry on the
1418 * sbsec->isec_head list. No reason to complain as these
1419 * will get fixed up the next time we go through
1420 * inode_doinit with a dentry, before these inodes could
1421 * be used again by userspace.
1422 */
Eric Paris23970742006-09-25 23:32:01 -07001423 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425
1426 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001427 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (!context) {
1429 rc = -ENOMEM;
1430 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001431 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001433 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001434 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001436 kfree(context);
1437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 /* Need a larger buffer. Query for the right size. */
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001439 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 if (rc < 0) {
1441 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001442 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001445 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (!context) {
1447 rc = -ENOMEM;
1448 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001449 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001451 context[len] = '\0';
Andreas Gruenbacher5d6c3192016-09-29 17:48:42 +02001452 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 }
1454 dput(dentry);
1455 if (rc < 0) {
1456 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001457 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001458 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 -rc, inode->i_sb->s_id, inode->i_ino);
1460 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001461 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 }
1463 /* Map ENODATA to the default file SID */
1464 sid = sbsec->def_sid;
1465 rc = 0;
1466 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001467 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001468 sbsec->def_sid,
1469 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001471 char *dev = inode->i_sb->s_id;
1472 unsigned long ino = inode->i_ino;
1473
1474 if (rc == -EINVAL) {
1475 if (printk_ratelimit())
1476 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1477 "context=%s. This indicates you may need to relabel the inode or the "
1478 "filesystem in question.\n", ino, dev, context);
1479 } else {
1480 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1481 "returned %d for dev=%s ino=%ld\n",
1482 __func__, context, -rc, dev, ino);
1483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 kfree(context);
1485 /* Leave with the unlabeled SID */
1486 rc = 0;
1487 break;
1488 }
1489 }
1490 kfree(context);
1491 isec->sid = sid;
1492 break;
1493 case SECURITY_FS_USE_TASK:
1494 isec->sid = isec->task_sid;
1495 break;
1496 case SECURITY_FS_USE_TRANS:
1497 /* Default to the fs SID. */
1498 isec->sid = sbsec->sid;
1499
1500 /* Try to obtain a transition SID. */
1501 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001502 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1503 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001505 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 isec->sid = sid;
1507 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001508 case SECURITY_FS_USE_MNTPOINT:
1509 isec->sid = sbsec->mntpoint_sid;
1510 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001512 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 isec->sid = sbsec->sid;
1514
Stephen Smalley134509d2015-06-04 16:22:17 -04001515 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001516 /* We must have a dentry to determine the label on
1517 * procfs inodes */
1518 if (opt_dentry)
1519 /* Called from d_instantiate or
1520 * d_splice_alias. */
1521 dentry = dget(opt_dentry);
1522 else
1523 /* Called from selinux_complete_init, try to
1524 * find a dentry. */
1525 dentry = d_find_alias(inode);
1526 /*
1527 * This can be hit on boot when a file is accessed
1528 * before the policy is loaded. When we load policy we
1529 * may find inodes that have no dentry on the
1530 * sbsec->isec_head list. No reason to complain as
1531 * these will get fixed up the next time we go through
1532 * inode_doinit() with a dentry, before these inodes
1533 * could be used again by userspace.
1534 */
1535 if (!dentry)
1536 goto out_unlock;
1537 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001538 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1539 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001540 dput(dentry);
1541 if (rc)
1542 goto out_unlock;
1543 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
1545 break;
1546 }
1547
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001548 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
Eric Paris23970742006-09-25 23:32:01 -07001550out_unlock:
1551 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552out:
1553 if (isec->sclass == SECCLASS_FILE)
1554 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 return rc;
1556}
1557
1558/* Convert a Linux signal to an access vector. */
1559static inline u32 signal_to_av(int sig)
1560{
1561 u32 perm = 0;
1562
1563 switch (sig) {
1564 case SIGCHLD:
1565 /* Commonly granted from child to parent. */
1566 perm = PROCESS__SIGCHLD;
1567 break;
1568 case SIGKILL:
1569 /* Cannot be caught or ignored */
1570 perm = PROCESS__SIGKILL;
1571 break;
1572 case SIGSTOP:
1573 /* Cannot be caught or ignored */
1574 perm = PROCESS__SIGSTOP;
1575 break;
1576 default:
1577 /* All other signals. */
1578 perm = PROCESS__SIGNAL;
1579 break;
1580 }
1581
1582 return perm;
1583}
1584
David Howells275bb412008-11-14 10:39:19 +11001585/*
David Howellsd84f4f92008-11-14 10:39:23 +11001586 * Check permission between a pair of credentials
1587 * fork check, ptrace check, etc.
1588 */
1589static int cred_has_perm(const struct cred *actor,
1590 const struct cred *target,
1591 u32 perms)
1592{
1593 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1594
1595 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1596}
1597
1598/*
David Howells88e67f32008-11-14 10:39:21 +11001599 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001600 * fork check, ptrace check, etc.
1601 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001602 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001603 */
1604static int task_has_perm(const struct task_struct *tsk1,
1605 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 u32 perms)
1607{
David Howells275bb412008-11-14 10:39:19 +11001608 const struct task_security_struct *__tsec1, *__tsec2;
1609 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
David Howells275bb412008-11-14 10:39:19 +11001611 rcu_read_lock();
1612 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1613 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1614 rcu_read_unlock();
1615 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616}
1617
David Howells3b11a1d2008-11-14 10:39:26 +11001618/*
1619 * Check permission between current and another task, e.g. signal checks,
1620 * fork check, ptrace check, etc.
1621 * current is the actor and tsk2 is the target
1622 * - this uses current's subjective creds
1623 */
1624static int current_has_perm(const struct task_struct *tsk,
1625 u32 perms)
1626{
1627 u32 sid, tsid;
1628
1629 sid = current_sid();
1630 tsid = task_sid(tsk);
1631 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1632}
1633
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001634#if CAP_LAST_CAP > 63
1635#error Fix SELinux to handle capabilities > 63.
1636#endif
1637
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001639static int cred_has_capability(const struct cred *cred,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001640 int cap, int audit, bool initns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641{
Thomas Liu2bf49692009-07-14 12:14:09 -04001642 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001643 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001644 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001645 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001646 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001647 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
Eric Paris50c205f2012-04-04 15:01:43 -04001649 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 ad.u.cap = cap;
1651
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001652 switch (CAP_TO_INDEX(cap)) {
1653 case 0:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001654 sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001655 break;
1656 case 1:
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04001657 sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001658 break;
1659 default:
1660 printk(KERN_ERR
1661 "SELinux: out of range capability %d\n", cap);
1662 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001663 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001664 }
Eric Paris06112162008-11-11 22:02:50 +11001665
David Howells275bb412008-11-14 10:39:19 +11001666 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001667 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001668 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001669 if (rc2)
1670 return rc2;
1671 }
Eric Paris06112162008-11-11 22:02:50 +11001672 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673}
1674
1675/* Check whether a task is allowed to use a system operation. */
1676static int task_has_system(struct task_struct *tsk,
1677 u32 perms)
1678{
David Howells275bb412008-11-14 10:39:19 +11001679 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
David Howells275bb412008-11-14 10:39:19 +11001681 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 SECCLASS_SYSTEM, perms, NULL);
1683}
1684
1685/* Check whether a task has a particular permission to an inode.
1686 The 'adp' parameter is optional and allows other audit
1687 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001688static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 struct inode *inode,
1690 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001691 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001694 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
David Howellse0e81732009-09-02 09:13:40 +01001696 validate_creds(cred);
1697
Eric Paris828dfe12008-04-17 13:17:49 -04001698 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001699 return 0;
1700
David Howells88e67f32008-11-14 10:39:21 +11001701 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 isec = inode->i_security;
1703
Linus Torvalds19e49832013-10-04 12:54:11 -07001704 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705}
1706
1707/* Same as inode_has_perm, but pass explicit audit data containing
1708 the dentry to help the auditing code to more easily generate the
1709 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001710static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 struct dentry *dentry,
1712 u32 av)
1713{
David Howellsc6f493d2015-03-17 22:26:22 +00001714 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001715 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001716
Eric Paris50c205f2012-04-04 15:01:43 -04001717 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001718 ad.u.dentry = dentry;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001719 __inode_security_revalidate(inode, dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001720 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001721}
1722
1723/* Same as inode_has_perm, but pass explicit audit data containing
1724 the path to help the auditing code to more easily generate the
1725 pathname if needed. */
1726static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001727 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001728 u32 av)
1729{
David Howellsc6f493d2015-03-17 22:26:22 +00001730 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001731 struct common_audit_data ad;
1732
Eric Paris50c205f2012-04-04 15:01:43 -04001733 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001734 ad.u.path = *path;
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05001735 __inode_security_revalidate(inode, path->dentry, true);
Linus Torvalds19e49832013-10-04 12:54:11 -07001736 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737}
1738
David Howells13f8e982013-06-13 23:37:55 +01001739/* Same as path_has_perm, but uses the inode from the file struct. */
1740static inline int file_path_has_perm(const struct cred *cred,
1741 struct file *file,
1742 u32 av)
1743{
1744 struct common_audit_data ad;
1745
Vivek Goyal43af5de2016-09-09 11:37:49 -04001746 ad.type = LSM_AUDIT_DATA_FILE;
1747 ad.u.file = file;
Linus Torvalds19e49832013-10-04 12:54:11 -07001748 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001749}
1750
Chenbo Feng0521e0b2017-10-18 13:00:26 -07001751#ifdef CONFIG_BPF_SYSCALL
1752static int bpf_fd_pass(struct file *file, u32 sid);
1753#endif
1754
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755/* Check whether a task can use an open file descriptor to
1756 access an inode in a given way. Check access to the
1757 descriptor itself, and then use dentry_has_perm to
1758 check a particular permission to the file.
1759 Access to the descriptor is implicitly granted if it
1760 has the same SID as the process. If av is zero, then
1761 access to the file is not checked, e.g. for cases
1762 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001763static int file_has_perm(const struct cred *cred,
1764 struct file *file,
1765 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001768 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001769 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001770 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 int rc;
1772
Vivek Goyal43af5de2016-09-09 11:37:49 -04001773 ad.type = LSM_AUDIT_DATA_FILE;
1774 ad.u.file = file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
David Howells275bb412008-11-14 10:39:19 +11001776 if (sid != fsec->sid) {
1777 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 SECCLASS_FD,
1779 FD__USE,
1780 &ad);
1781 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001782 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 }
1784
Chenbo Feng0521e0b2017-10-18 13:00:26 -07001785#ifdef CONFIG_BPF_SYSCALL
1786 rc = bpf_fd_pass(file, cred_sid(cred));
1787 if (rc)
1788 return rc;
1789#endif
1790
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001792 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001794 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
David Howells88e67f32008-11-14 10:39:21 +11001796out:
1797 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798}
1799
David Howellsc3c188b2015-07-10 17:19:58 -04001800/*
1801 * Determine the label for an inode that might be unioned.
1802 */
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001803static int
1804selinux_determine_inode_label(const struct task_security_struct *tsec,
1805 struct inode *dir,
1806 const struct qstr *name, u16 tclass,
1807 u32 *_new_isid)
David Howellsc3c188b2015-07-10 17:19:58 -04001808{
1809 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
David Howellsc3c188b2015-07-10 17:19:58 -04001810
1811 if ((sbsec->flags & SE_SBINITIALIZED) &&
1812 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1813 *_new_isid = sbsec->mntpoint_sid;
1814 } else if ((sbsec->flags & SBLABEL_MNT) &&
1815 tsec->create_sid) {
1816 *_new_isid = tsec->create_sid;
1817 } else {
Paul Moore20cdef82016-04-04 14:14:42 -04001818 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001819 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1820 name, _new_isid);
1821 }
1822
1823 return 0;
1824}
1825
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826/* Check whether a task can create a file. */
1827static int may_create(struct inode *dir,
1828 struct dentry *dentry,
1829 u16 tclass)
1830{
Paul Moore5fb49872010-04-22 14:46:19 -04001831 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 struct inode_security_struct *dsec;
1833 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001834 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001835 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 int rc;
1837
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001838 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 sbsec = dir->i_sb->s_security;
1840
David Howells275bb412008-11-14 10:39:19 +11001841 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001842
Eric Paris50c205f2012-04-04 15:01:43 -04001843 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001844 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
David Howells275bb412008-11-14 10:39:19 +11001846 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 DIR__ADD_NAME | DIR__SEARCH,
1848 &ad);
1849 if (rc)
1850 return rc;
1851
Vivek Goyalc957f6d2016-07-13 10:44:51 -04001852 rc = selinux_determine_inode_label(current_security(), dir,
1853 &dentry->d_name, tclass, &newsid);
David Howellsc3c188b2015-07-10 17:19:58 -04001854 if (rc)
1855 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
David Howells275bb412008-11-14 10:39:19 +11001857 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 if (rc)
1859 return rc;
1860
1861 return avc_has_perm(newsid, sbsec->sid,
1862 SECCLASS_FILESYSTEM,
1863 FILESYSTEM__ASSOCIATE, &ad);
1864}
1865
Michael LeMay4eb582c2006-06-26 00:24:57 -07001866/* Check whether a task can create a key. */
1867static int may_create_key(u32 ksid,
1868 struct task_struct *ctx)
1869{
David Howells275bb412008-11-14 10:39:19 +11001870 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001871
David Howells275bb412008-11-14 10:39:19 +11001872 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001873}
1874
Eric Paris828dfe12008-04-17 13:17:49 -04001875#define MAY_LINK 0
1876#define MAY_UNLINK 1
1877#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
1879/* Check whether a task can link, unlink, or rmdir a file/directory. */
1880static int may_link(struct inode *dir,
1881 struct dentry *dentry,
1882 int kind)
1883
1884{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001886 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001887 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 u32 av;
1889 int rc;
1890
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001891 dsec = inode_security(dir);
1892 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
Eric Paris50c205f2012-04-04 15:01:43 -04001894 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001895 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
1897 av = DIR__SEARCH;
1898 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001899 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 if (rc)
1901 return rc;
1902
1903 switch (kind) {
1904 case MAY_LINK:
1905 av = FILE__LINK;
1906 break;
1907 case MAY_UNLINK:
1908 av = FILE__UNLINK;
1909 break;
1910 case MAY_RMDIR:
1911 av = DIR__RMDIR;
1912 break;
1913 default:
Eric Paris744ba352008-04-17 11:52:44 -04001914 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1915 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 return 0;
1917 }
1918
David Howells275bb412008-11-14 10:39:19 +11001919 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 return rc;
1921}
1922
1923static inline int may_rename(struct inode *old_dir,
1924 struct dentry *old_dentry,
1925 struct inode *new_dir,
1926 struct dentry *new_dentry)
1927{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001929 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001930 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 u32 av;
1932 int old_is_dir, new_is_dir;
1933 int rc;
1934
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001935 old_dsec = inode_security(old_dir);
1936 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001937 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001938 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939
Eric Paris50c205f2012-04-04 15:01:43 -04001940 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Eric Parisa2694342011-04-25 13:10:27 -04001942 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001943 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1945 if (rc)
1946 return rc;
David Howells275bb412008-11-14 10:39:19 +11001947 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 old_isec->sclass, FILE__RENAME, &ad);
1949 if (rc)
1950 return rc;
1951 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001952 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 old_isec->sclass, DIR__REPARENT, &ad);
1954 if (rc)
1955 return rc;
1956 }
1957
Eric Parisa2694342011-04-25 13:10:27 -04001958 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001960 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001962 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 if (rc)
1964 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001965 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001966 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001967 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001968 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 new_isec->sclass,
1970 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1971 if (rc)
1972 return rc;
1973 }
1974
1975 return 0;
1976}
1977
1978/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001979static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 struct super_block *sb,
1981 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001982 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001985 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001988 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989}
1990
1991/* Convert a Linux mode and permission mask to an access vector. */
1992static inline u32 file_mask_to_av(int mode, int mask)
1993{
1994 u32 av = 0;
1995
Al Virodba19c62011-07-25 20:49:29 -04001996 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 if (mask & MAY_EXEC)
1998 av |= FILE__EXECUTE;
1999 if (mask & MAY_READ)
2000 av |= FILE__READ;
2001
2002 if (mask & MAY_APPEND)
2003 av |= FILE__APPEND;
2004 else if (mask & MAY_WRITE)
2005 av |= FILE__WRITE;
2006
2007 } else {
2008 if (mask & MAY_EXEC)
2009 av |= DIR__SEARCH;
2010 if (mask & MAY_WRITE)
2011 av |= DIR__WRITE;
2012 if (mask & MAY_READ)
2013 av |= DIR__READ;
2014 }
2015
2016 return av;
2017}
2018
2019/* Convert a Linux file to an access vector. */
2020static inline u32 file_to_av(struct file *file)
2021{
2022 u32 av = 0;
2023
2024 if (file->f_mode & FMODE_READ)
2025 av |= FILE__READ;
2026 if (file->f_mode & FMODE_WRITE) {
2027 if (file->f_flags & O_APPEND)
2028 av |= FILE__APPEND;
2029 else
2030 av |= FILE__WRITE;
2031 }
Stephen Smalley0794c662008-03-17 08:55:18 -04002032 if (!av) {
2033 /*
2034 * Special file opened with flags 3 for ioctl-only use.
2035 */
2036 av = FILE__IOCTL;
2037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
2039 return av;
2040}
2041
Eric Paris8b6a5a32008-10-29 17:06:46 -04002042/*
2043 * Convert a file to an access vector and include the correct open
2044 * open permission.
2045 */
2046static inline u32 open_file_to_av(struct file *file)
2047{
2048 u32 av = file_to_av(file);
Stephen Smalleyb983b2a2017-05-12 12:41:24 -04002049 struct inode *inode = file_inode(file);
Eric Paris8b6a5a32008-10-29 17:06:46 -04002050
Stephen Smalleyb983b2a2017-05-12 12:41:24 -04002051 if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
Eric Paris49b7b8d2010-07-23 11:44:09 -04002052 av |= FILE__OPEN;
2053
Eric Paris8b6a5a32008-10-29 17:06:46 -04002054 return av;
2055}
2056
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057/* Hook functions begin here. */
2058
Stephen Smalley79af7302015-01-21 10:54:10 -05002059static int selinux_binder_set_context_mgr(struct task_struct *mgr)
2060{
2061 u32 mysid = current_sid();
2062 u32 mgrsid = task_sid(mgr);
2063
2064 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
2065 BINDER__SET_CONTEXT_MGR, NULL);
2066}
2067
2068static int selinux_binder_transaction(struct task_struct *from,
2069 struct task_struct *to)
2070{
2071 u32 mysid = current_sid();
2072 u32 fromsid = task_sid(from);
2073 u32 tosid = task_sid(to);
2074 int rc;
2075
2076 if (mysid != fromsid) {
2077 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2078 BINDER__IMPERSONATE, NULL);
2079 if (rc)
2080 return rc;
2081 }
2082
2083 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2084 NULL);
2085}
2086
2087static int selinux_binder_transfer_binder(struct task_struct *from,
2088 struct task_struct *to)
2089{
2090 u32 fromsid = task_sid(from);
2091 u32 tosid = task_sid(to);
2092
2093 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2094 NULL);
2095}
2096
2097static int selinux_binder_transfer_file(struct task_struct *from,
2098 struct task_struct *to,
2099 struct file *file)
2100{
2101 u32 sid = task_sid(to);
2102 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002103 struct dentry *dentry = file->f_path.dentry;
Paul Moore20cdef82016-04-04 14:14:42 -04002104 struct inode_security_struct *isec;
Stephen Smalley79af7302015-01-21 10:54:10 -05002105 struct common_audit_data ad;
2106 int rc;
2107
2108 ad.type = LSM_AUDIT_DATA_PATH;
2109 ad.u.path = file->f_path;
2110
2111 if (sid != fsec->sid) {
2112 rc = avc_has_perm(sid, fsec->sid,
2113 SECCLASS_FD,
2114 FD__USE,
2115 &ad);
2116 if (rc)
2117 return rc;
2118 }
2119
Chenbo Feng0521e0b2017-10-18 13:00:26 -07002120#ifdef CONFIG_BPF_SYSCALL
2121 rc = bpf_fd_pass(file, sid);
2122 if (rc)
2123 return rc;
2124#endif
2125
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002126 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002127 return 0;
2128
Paul Moore20cdef82016-04-04 14:14:42 -04002129 isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002130 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2131 &ad);
2132}
2133
Ingo Molnar9e488582009-05-07 19:26:19 +10002134static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002135 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136{
Eric Paris69f594a2012-01-03 12:25:15 -05002137 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002138 u32 sid = current_sid();
2139 u32 csid = task_sid(child);
2140 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002141 }
2142
David Howells3b11a1d2008-11-14 10:39:26 +11002143 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002144}
2145
2146static int selinux_ptrace_traceme(struct task_struct *parent)
2147{
David Howells5cd9c582008-08-14 11:37:28 +01002148 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149}
2150
2151static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002152 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002154 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155}
2156
David Howellsd84f4f92008-11-14 10:39:23 +11002157static int selinux_capset(struct cred *new, const struct cred *old,
2158 const kernel_cap_t *effective,
2159 const kernel_cap_t *inheritable,
2160 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161{
David Howellsd84f4f92008-11-14 10:39:23 +11002162 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163}
2164
James Morris5626d3e2009-01-30 10:05:06 +11002165/*
2166 * (This comment used to live with the selinux_task_setuid hook,
2167 * which was removed).
2168 *
2169 * Since setuid only affects the current process, and since the SELinux
2170 * controls are not based on the Linux identity attributes, SELinux does not
2171 * need to control this operation. However, SELinux does control the use of
2172 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2173 */
2174
Eric Paris6a9de492012-01-03 12:25:14 -05002175static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2176 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177{
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002178 return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179}
2180
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2182{
David Howells88e67f32008-11-14 10:39:21 +11002183 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 int rc = 0;
2185
2186 if (!sb)
2187 return 0;
2188
2189 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002190 case Q_SYNC:
2191 case Q_QUOTAON:
2192 case Q_QUOTAOFF:
2193 case Q_SETINFO:
2194 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002195 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002196 break;
2197 case Q_GETFMT:
2198 case Q_GETINFO:
2199 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002200 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002201 break;
2202 default:
2203 rc = 0; /* let the kernel handle invalid cmds */
2204 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 }
2206 return rc;
2207}
2208
2209static int selinux_quota_on(struct dentry *dentry)
2210{
David Howells88e67f32008-11-14 10:39:21 +11002211 const struct cred *cred = current_cred();
2212
Eric Paris2875fa02011-04-28 16:04:24 -04002213 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214}
2215
Eric Paris12b30522010-11-15 18:36:29 -05002216static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218 int rc;
2219
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002221 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2222 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002223 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2224 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002225 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2226 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2227 /* Set level of messages printed to console */
2228 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002229 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2230 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002231 case SYSLOG_ACTION_CLOSE: /* Close log */
2232 case SYSLOG_ACTION_OPEN: /* Open log */
2233 case SYSLOG_ACTION_READ: /* Read from log */
2234 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2235 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002236 default:
2237 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2238 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 }
2240 return rc;
2241}
2242
2243/*
2244 * Check that a process has enough memory to allocate a new virtual
2245 * mapping. 0 means there is enough memory for the allocation to
2246 * succeed and -ENOMEM implies there is not.
2247 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 * Do not audit the selinux permission check, as this is applied to all
2249 * processes that allocate mappings.
2250 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002251static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252{
2253 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002255 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04002256 SECURITY_CAP_NOAUDIT, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if (rc == 0)
2258 cap_sys_admin = 1;
2259
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002260 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261}
2262
2263/* binprm security operations */
2264
Paul Moore0c6181c2016-03-30 21:41:21 -04002265static u32 ptrace_parent_sid(struct task_struct *task)
2266{
2267 u32 sid = 0;
2268 struct task_struct *tracer;
2269
2270 rcu_read_lock();
2271 tracer = ptrace_parent(task);
2272 if (tracer)
2273 sid = task_sid(tracer);
2274 rcu_read_unlock();
2275
2276 return sid;
2277}
2278
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002279static int check_nnp_nosuid(const struct linux_binprm *bprm,
2280 const struct task_security_struct *old_tsec,
2281 const struct task_security_struct *new_tsec)
2282{
2283 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
Andy Lutomirski380cf5b2016-06-23 16:41:05 -05002284 int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002285 int rc;
2286
2287 if (!nnp && !nosuid)
2288 return 0; /* neither NNP nor nosuid */
2289
2290 if (new_tsec->sid == old_tsec->sid)
2291 return 0; /* No change in credentials */
2292
2293 /*
2294 * The only transitions we permit under NNP or nosuid
2295 * are transitions to bounded SIDs, i.e. SIDs that are
2296 * guaranteed to only be allowed a subset of the permissions
2297 * of the current SID.
2298 */
2299 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2300 if (rc) {
2301 /*
2302 * On failure, preserve the errno values for NNP vs nosuid.
2303 * NNP: Operation not permitted for caller.
2304 * nosuid: Permission denied to file.
2305 */
2306 if (nnp)
2307 return -EPERM;
2308 else
2309 return -EACCES;
2310 }
2311 return 0;
2312}
2313
David Howellsa6f76f22008-11-14 10:39:24 +11002314static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315{
David Howellsa6f76f22008-11-14 10:39:24 +11002316 const struct task_security_struct *old_tsec;
2317 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002319 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002320 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 int rc;
2322
David Howellsa6f76f22008-11-14 10:39:24 +11002323 /* SELinux context only depends on initial program or script and not
2324 * the script interpreter */
2325 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 return 0;
2327
David Howellsa6f76f22008-11-14 10:39:24 +11002328 old_tsec = current_security();
2329 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002330 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
2332 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002333 new_tsec->sid = old_tsec->sid;
2334 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Michael LeMay28eba5b2006-06-27 02:53:42 -07002336 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002337 new_tsec->create_sid = 0;
2338 new_tsec->keycreate_sid = 0;
2339 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
David Howellsa6f76f22008-11-14 10:39:24 +11002341 if (old_tsec->exec_sid) {
2342 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002344 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002345
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002346 /* Fail on NNP or nosuid if not an allowed transition. */
2347 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2348 if (rc)
2349 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 } else {
2351 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002352 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002353 SECCLASS_PROCESS, NULL,
2354 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 if (rc)
2356 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002357
2358 /*
2359 * Fallback to old SID on NNP or nosuid if not an allowed
2360 * transition.
2361 */
2362 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2363 if (rc)
2364 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 }
2366
Vivek Goyal43af5de2016-09-09 11:37:49 -04002367 ad.type = LSM_AUDIT_DATA_FILE;
2368 ad.u.file = bprm->file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
David Howellsa6f76f22008-11-14 10:39:24 +11002370 if (new_tsec->sid == old_tsec->sid) {
2371 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2373 if (rc)
2374 return rc;
2375 } else {
2376 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002377 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2379 if (rc)
2380 return rc;
2381
David Howellsa6f76f22008-11-14 10:39:24 +11002382 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2384 if (rc)
2385 return rc;
2386
David Howellsa6f76f22008-11-14 10:39:24 +11002387 /* Check for shared state */
2388 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2389 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2390 SECCLASS_PROCESS, PROCESS__SHARE,
2391 NULL);
2392 if (rc)
2393 return -EPERM;
2394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
David Howellsa6f76f22008-11-14 10:39:24 +11002396 /* Make sure that anyone attempting to ptrace over a task that
2397 * changes its SID has the appropriate permit */
2398 if (bprm->unsafe &
2399 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
Paul Moore0c6181c2016-03-30 21:41:21 -04002400 u32 ptsid = ptrace_parent_sid(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002401 if (ptsid != 0) {
2402 rc = avc_has_perm(ptsid, new_tsec->sid,
2403 SECCLASS_PROCESS,
2404 PROCESS__PTRACE, NULL);
2405 if (rc)
2406 return -EPERM;
2407 }
2408 }
2409
2410 /* Clear any possibly unsafe personality bits on exec: */
2411 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 }
2413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 return 0;
2415}
2416
Eric Paris828dfe12008-04-17 13:17:49 -04002417static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418{
Paul Moore5fb49872010-04-22 14:46:19 -04002419 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002420 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 int atsecure = 0;
2422
David Howells275bb412008-11-14 10:39:19 +11002423 sid = tsec->sid;
2424 osid = tsec->osid;
2425
2426 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 /* Enable secure mode for SIDs transitions unless
2428 the noatsecure permission is granted between
2429 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002430 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002431 SECCLASS_PROCESS,
2432 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 }
2434
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002435 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436}
2437
Al Viroc3c073f2012-08-21 22:32:06 -04002438static int match_file(const void *p, struct file *file, unsigned fd)
2439{
2440 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2441}
2442
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002444static inline void flush_unauthorized_files(const struct cred *cred,
2445 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002448 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002449 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002450 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002452 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 if (tty) {
Peter Hurley4a510962016-01-09 21:35:23 -08002454 spin_lock(&tty->files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002455 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002456 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002457
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002459 Use file_path_has_perm on the tty path directly
2460 rather than using file_has_perm, as this particular
2461 open file may belong to another process and we are
2462 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002463 file_priv = list_first_entry(&tty->tty_files,
2464 struct tty_file_private, list);
2465 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002466 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002467 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 }
Peter Hurley4a510962016-01-09 21:35:23 -08002469 spin_unlock(&tty->files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002470 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002472 /* Reset controlling tty. */
2473 if (drop_tty)
2474 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
2476 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002477 n = iterate_fd(files, 0, match_file, cred);
2478 if (!n) /* none found? */
2479 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Al Viroc3c073f2012-08-21 22:32:06 -04002481 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002482 if (IS_ERR(devnull))
2483 devnull = NULL;
2484 /* replace all the matching ones with this */
2485 do {
2486 replace_fd(n - 1, devnull, 0);
2487 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2488 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002489 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490}
2491
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492/*
David Howellsa6f76f22008-11-14 10:39:24 +11002493 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 */
David Howellsa6f76f22008-11-14 10:39:24 +11002495static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496{
David Howellsa6f76f22008-11-14 10:39:24 +11002497 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 int rc, i;
2500
David Howellsa6f76f22008-11-14 10:39:24 +11002501 new_tsec = bprm->cred->security;
2502 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 return;
2504
2505 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002506 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507
David Howellsa6f76f22008-11-14 10:39:24 +11002508 /* Always clear parent death signal on SID transitions. */
2509 current->pdeath_signal = 0;
2510
2511 /* Check whether the new SID can inherit resource limits from the old
2512 * SID. If not, reset all soft limits to the lower of the current
2513 * task's hard limit and the init task's soft limit.
2514 *
2515 * Note that the setting of hard limits (even to lower them) can be
2516 * controlled by the setrlimit check. The inclusion of the init task's
2517 * soft limit into the computation is to avoid resetting soft limits
2518 * higher than the default soft limit for cases where the default is
2519 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2520 */
2521 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2522 PROCESS__RLIMITINH, NULL);
2523 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002524 /* protect against do_prlimit() */
2525 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002526 for (i = 0; i < RLIM_NLIMITS; i++) {
2527 rlim = current->signal->rlim + i;
2528 initrlim = init_task.signal->rlim + i;
2529 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2530 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002531 task_unlock(current);
2532 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002533 }
2534}
2535
2536/*
2537 * Clean up the process immediately after the installation of new credentials
2538 * due to exec
2539 */
2540static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2541{
2542 const struct task_security_struct *tsec = current_security();
2543 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002544 u32 osid, sid;
2545 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002546
David Howellsa6f76f22008-11-14 10:39:24 +11002547 osid = tsec->osid;
2548 sid = tsec->sid;
2549
2550 if (sid == osid)
2551 return;
2552
2553 /* Check whether the new SID can inherit signal state from the old SID.
2554 * If not, clear itimers to avoid subsequent signal generation and
2555 * flush and unblock signals.
2556 *
2557 * This must occur _after_ the task SID has been updated so that any
2558 * kill done after the flush will be checked against the new SID.
2559 */
2560 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 if (rc) {
2562 memset(&itimer, 0, sizeof itimer);
2563 for (i = 0; i < 3; i++)
2564 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002566 if (!fatal_signal_pending(current)) {
2567 flush_sigqueue(&current->pending);
2568 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002569 flush_signal_handlers(current, 1);
2570 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002571 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 spin_unlock_irq(&current->sighand->siglock);
2574 }
2575
David Howellsa6f76f22008-11-14 10:39:24 +11002576 /* Wake up the parent if it is waiting so that it can recheck
2577 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002578 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002579 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002580 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581}
2582
2583/* superblock security operations */
2584
2585static int selinux_sb_alloc_security(struct super_block *sb)
2586{
2587 return superblock_alloc_security(sb);
2588}
2589
2590static void selinux_sb_free_security(struct super_block *sb)
2591{
2592 superblock_free_security(sb);
2593}
2594
2595static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2596{
2597 if (plen > olen)
2598 return 0;
2599
2600 return !memcmp(prefix, option, plen);
2601}
2602
2603static inline int selinux_option(char *option, int len)
2604{
Eric Paris832cbd92008-04-01 13:24:09 -04002605 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2606 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2607 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002608 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2609 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610}
2611
2612static inline void take_option(char **to, char *from, int *first, int len)
2613{
2614 if (!*first) {
2615 **to = ',';
2616 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002617 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 *first = 0;
2619 memcpy(*to, from, len);
2620 *to += len;
2621}
2622
Eric Paris828dfe12008-04-17 13:17:49 -04002623static inline void take_selinux_option(char **to, char *from, int *first,
2624 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002625{
2626 int current_size = 0;
2627
2628 if (!*first) {
2629 **to = '|';
2630 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002631 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002632 *first = 0;
2633
2634 while (current_size < len) {
2635 if (*from != '"') {
2636 **to = *from;
2637 *to += 1;
2638 }
2639 from += 1;
2640 current_size += 1;
2641 }
2642}
2643
Eric Parise0007522008-03-05 10:31:54 -05002644static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645{
2646 int fnosec, fsec, rc = 0;
2647 char *in_save, *in_curr, *in_end;
2648 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002649 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
2651 in_curr = orig;
2652 sec_curr = copy;
2653
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2655 if (!nosec) {
2656 rc = -ENOMEM;
2657 goto out;
2658 }
2659
2660 nosec_save = nosec;
2661 fnosec = fsec = 1;
2662 in_save = in_end = orig;
2663
2664 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002665 if (*in_end == '"')
2666 open_quote = !open_quote;
2667 if ((*in_end == ',' && open_quote == 0) ||
2668 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 int len = in_end - in_curr;
2670
2671 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002672 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 else
2674 take_option(&nosec, in_curr, &fnosec, len);
2675
2676 in_curr = in_end + 1;
2677 }
2678 } while (*in_end++);
2679
Eric Paris6931dfc2005-06-30 02:58:51 -07002680 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002681 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682out:
2683 return rc;
2684}
2685
Eric Paris026eb162011-03-03 16:09:14 -05002686static int selinux_sb_remount(struct super_block *sb, void *data)
2687{
2688 int rc, i, *flags;
2689 struct security_mnt_opts opts;
2690 char *secdata, **mount_options;
2691 struct superblock_security_struct *sbsec = sb->s_security;
2692
2693 if (!(sbsec->flags & SE_SBINITIALIZED))
2694 return 0;
2695
2696 if (!data)
2697 return 0;
2698
2699 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2700 return 0;
2701
2702 security_init_mnt_opts(&opts);
2703 secdata = alloc_secdata();
2704 if (!secdata)
2705 return -ENOMEM;
2706 rc = selinux_sb_copy_data(data, secdata);
2707 if (rc)
2708 goto out_free_secdata;
2709
2710 rc = selinux_parse_opts_str(secdata, &opts);
2711 if (rc)
2712 goto out_free_secdata;
2713
2714 mount_options = opts.mnt_opts;
2715 flags = opts.mnt_opts_flags;
2716
2717 for (i = 0; i < opts.num_mnt_opts; i++) {
2718 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002719
Eric Paris12f348b2012-10-09 10:56:25 -04002720 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002721 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002722 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002723 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002724 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002725 "(%s) failed for (dev %s, type %s) errno=%d\n",
2726 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002727 goto out_free_opts;
2728 }
2729 rc = -EINVAL;
2730 switch (flags[i]) {
2731 case FSCONTEXT_MNT:
2732 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2733 goto out_bad_option;
2734 break;
2735 case CONTEXT_MNT:
2736 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2737 goto out_bad_option;
2738 break;
2739 case ROOTCONTEXT_MNT: {
2740 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002741 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002742
2743 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2744 goto out_bad_option;
2745 break;
2746 }
2747 case DEFCONTEXT_MNT:
2748 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2749 goto out_bad_option;
2750 break;
2751 default:
2752 goto out_free_opts;
2753 }
2754 }
2755
2756 rc = 0;
2757out_free_opts:
2758 security_free_mnt_opts(&opts);
2759out_free_secdata:
2760 free_secdata(secdata);
2761 return rc;
2762out_bad_option:
2763 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002764 "during remount (dev %s, type=%s)\n", sb->s_id,
2765 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002766 goto out_free_opts;
2767}
2768
James Morris12204e22008-12-19 10:44:42 +11002769static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770{
David Howells88e67f32008-11-14 10:39:21 +11002771 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002772 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 int rc;
2774
2775 rc = superblock_doinit(sb, data);
2776 if (rc)
2777 return rc;
2778
James Morris74192242008-12-19 11:41:10 +11002779 /* Allow all mounts performed by the kernel */
2780 if (flags & MS_KERNMOUNT)
2781 return 0;
2782
Eric Paris50c205f2012-04-04 15:01:43 -04002783 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002784 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002785 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786}
2787
David Howells726c3342006-06-23 02:02:58 -07002788static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789{
David Howells88e67f32008-11-14 10:39:21 +11002790 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002791 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
Eric Paris50c205f2012-04-04 15:01:43 -04002793 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002794 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002795 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796}
2797
Al Viro808d4e32012-10-11 11:42:01 -04002798static int selinux_mount(const char *dev_name,
Al Viro8a04c432016-03-25 14:52:53 -04002799 const struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002800 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002801 unsigned long flags,
2802 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803{
David Howells88e67f32008-11-14 10:39:21 +11002804 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
2806 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002807 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002808 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 else
Eric Paris2875fa02011-04-28 16:04:24 -04002810 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811}
2812
2813static int selinux_umount(struct vfsmount *mnt, int flags)
2814{
David Howells88e67f32008-11-14 10:39:21 +11002815 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
David Howells88e67f32008-11-14 10:39:21 +11002817 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002818 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819}
2820
2821/* inode security operations */
2822
2823static int selinux_inode_alloc_security(struct inode *inode)
2824{
2825 return inode_alloc_security(inode);
2826}
2827
2828static void selinux_inode_free_security(struct inode *inode)
2829{
2830 inode_free_security(inode);
2831}
2832
David Quigleyd47be3d2013-05-22 12:50:34 -04002833static int selinux_dentry_init_security(struct dentry *dentry, int mode,
Al Viro4f3ccd72016-07-20 16:06:15 -04002834 const struct qstr *name, void **ctx,
David Quigleyd47be3d2013-05-22 12:50:34 -04002835 u32 *ctxlen)
2836{
David Quigleyd47be3d2013-05-22 12:50:34 -04002837 u32 newsid;
2838 int rc;
2839
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002840 rc = selinux_determine_inode_label(current_security(),
2841 d_inode(dentry->d_parent), name,
David Howellsc3c188b2015-07-10 17:19:58 -04002842 inode_mode_to_security_class(mode),
2843 &newsid);
2844 if (rc)
2845 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002846
2847 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2848}
2849
Vivek Goyala518b0a2016-07-13 10:44:53 -04002850static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
2851 struct qstr *name,
2852 const struct cred *old,
2853 struct cred *new)
2854{
2855 u32 newsid;
2856 int rc;
2857 struct task_security_struct *tsec;
2858
2859 rc = selinux_determine_inode_label(old->security,
2860 d_inode(dentry->d_parent), name,
2861 inode_mode_to_security_class(mode),
2862 &newsid);
2863 if (rc)
2864 return rc;
2865
2866 tsec = new->security;
2867 tsec->create_sid = newsid;
2868 return 0;
2869}
2870
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002871static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002872 const struct qstr *qstr,
2873 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002874 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002875{
Paul Moore5fb49872010-04-22 14:46:19 -04002876 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002877 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002878 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002879 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002880 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002881
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002882 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002883
David Howells275bb412008-11-14 10:39:19 +11002884 sid = tsec->sid;
2885 newsid = tsec->create_sid;
2886
Vivek Goyalc957f6d2016-07-13 10:44:51 -04002887 rc = selinux_determine_inode_label(current_security(),
David Howellsc3c188b2015-07-10 17:19:58 -04002888 dir, qstr,
2889 inode_mode_to_security_class(inode->i_mode),
2890 &newsid);
2891 if (rc)
2892 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002893
Eric Paris296fddf2006-09-25 23:32:00 -07002894 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002895 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002896 struct inode_security_struct *isec = inode->i_security;
2897 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2898 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002899 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002900 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002901
Eric Paris12f348b2012-10-09 10:56:25 -04002902 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002903 return -EOPNOTSUPP;
2904
Tetsuo Handa95489062013-07-25 05:44:02 +09002905 if (name)
2906 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002907
2908 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002909 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002910 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002911 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002912 *value = context;
2913 *len = clen;
2914 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002915
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002916 return 0;
2917}
2918
Al Viro4acdaf22011-07-26 01:42:34 -04002919static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920{
2921 return may_create(dir, dentry, SECCLASS_FILE);
2922}
2923
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2925{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 return may_link(dir, old_dentry, MAY_LINK);
2927}
2928
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2930{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 return may_link(dir, dentry, MAY_UNLINK);
2932}
2933
2934static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2935{
2936 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2937}
2938
Al Viro18bb1db2011-07-26 01:41:39 -04002939static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
2941 return may_create(dir, dentry, SECCLASS_DIR);
2942}
2943
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2945{
2946 return may_link(dir, dentry, MAY_RMDIR);
2947}
2948
Al Viro1a67aaf2011-07-26 01:52:52 -04002949static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2952}
2953
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002955 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956{
2957 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2958}
2959
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960static int selinux_inode_readlink(struct dentry *dentry)
2961{
David Howells88e67f32008-11-14 10:39:21 +11002962 const struct cred *cred = current_cred();
2963
Eric Paris2875fa02011-04-28 16:04:24 -04002964 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965}
2966
NeilBrownbda0be72015-03-23 13:37:39 +11002967static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2968 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969{
David Howells88e67f32008-11-14 10:39:21 +11002970 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002971 struct common_audit_data ad;
2972 struct inode_security_struct *isec;
2973 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
NeilBrownbda0be72015-03-23 13:37:39 +11002975 validate_creds(cred);
2976
2977 ad.type = LSM_AUDIT_DATA_DENTRY;
2978 ad.u.dentry = dentry;
2979 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05002980 isec = inode_security_rcu(inode, rcu);
2981 if (IS_ERR(isec))
2982 return PTR_ERR(isec);
NeilBrownbda0be72015-03-23 13:37:39 +11002983
2984 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2985 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986}
2987
Eric Parisd4cf970d2012-04-04 15:01:42 -04002988static noinline int audit_inode_permission(struct inode *inode,
2989 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002990 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002991 unsigned flags)
2992{
2993 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002994 struct inode_security_struct *isec = inode->i_security;
2995 int rc;
2996
Eric Paris50c205f2012-04-04 15:01:43 -04002997 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002998 ad.u.inode = inode;
2999
3000 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07003001 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04003002 if (rc)
3003 return rc;
3004 return 0;
3005}
3006
Al Viroe74f71e2011-06-20 19:38:15 -04003007static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008{
David Howells88e67f32008-11-14 10:39:21 +11003009 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04003010 u32 perms;
3011 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04003012 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04003013 struct inode_security_struct *isec;
3014 u32 sid;
3015 struct av_decision avd;
3016 int rc, rc2;
3017 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
Eric Parisb782e0a2010-07-23 11:44:03 -04003019 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04003020 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
3021
Eric Parisb782e0a2010-07-23 11:44:03 -04003022 /* No permission to check. Existence test. */
3023 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
Eric Paris2e334052012-04-04 15:01:42 -04003026 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04003027
Eric Paris2e334052012-04-04 15:01:42 -04003028 if (unlikely(IS_PRIVATE(inode)))
3029 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04003030
3031 perms = file_mask_to_av(inode->i_mode, mask);
3032
Eric Paris2e334052012-04-04 15:01:42 -04003033 sid = cred_sid(cred);
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05003034 isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
3035 if (IS_ERR(isec))
3036 return PTR_ERR(isec);
Eric Paris2e334052012-04-04 15:01:42 -04003037
3038 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
3039 audited = avc_audit_required(perms, &avd, rc,
3040 from_access ? FILE__AUDIT_ACCESS : 0,
3041 &denied);
3042 if (likely(!audited))
3043 return rc;
3044
Stephen Smalley626b9742014-04-29 11:29:04 -07003045 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04003046 if (rc2)
3047 return rc2;
3048 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049}
3050
3051static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3052{
David Howells88e67f32008-11-14 10:39:21 +11003053 const struct cred *cred = current_cred();
Stephen Smalleyb983b2a2017-05-12 12:41:24 -04003054 struct inode *inode = d_backing_inode(dentry);
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003055 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04003056 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003058 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
3059 if (ia_valid & ATTR_FORCE) {
3060 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
3061 ATTR_FORCE);
3062 if (!ia_valid)
3063 return 0;
3064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Amerigo Wangbc6a6002009-08-20 19:29:02 -07003066 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
3067 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04003068 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Stephen Smalleyb983b2a2017-05-12 12:41:24 -04003070 if (selinux_policycap_openperm &&
3071 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3072 (ia_valid & ATTR_SIZE) &&
3073 !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04003074 av |= FILE__OPEN;
3075
3076 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077}
3078
Al Viro3f7036a2015-03-08 19:28:30 -04003079static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080{
Al Viro3f7036a2015-03-08 19:28:30 -04003081 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082}
3083
David Howells8f0cfa52008-04-29 00:59:41 -07003084static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07003085{
David Howells88e67f32008-11-14 10:39:21 +11003086 const struct cred *cred = current_cred();
3087
Serge E. Hallynb5376772007-10-16 23:31:36 -07003088 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3089 sizeof XATTR_SECURITY_PREFIX - 1)) {
3090 if (!strcmp(name, XATTR_NAME_CAPS)) {
3091 if (!capable(CAP_SETFCAP))
3092 return -EPERM;
3093 } else if (!capable(CAP_SYS_ADMIN)) {
3094 /* A different attribute in the security namespace.
3095 Restrict to administrator. */
3096 return -EPERM;
3097 }
3098 }
3099
3100 /* Not an attribute we recognize, so just check the
3101 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04003102 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003103}
3104
David Howells8f0cfa52008-04-29 00:59:41 -07003105static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3106 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107{
David Howellsc6f493d2015-03-17 22:26:22 +00003108 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003109 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04003111 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11003112 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 int rc = 0;
3114
Serge E. Hallynb5376772007-10-16 23:31:36 -07003115 if (strcmp(name, XATTR_NAME_SELINUX))
3116 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117
3118 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003119 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 return -EOPNOTSUPP;
3121
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003122 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 return -EPERM;
3124
Eric Paris50c205f2012-04-04 15:01:43 -04003125 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003126 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Paul Moore20cdef82016-04-04 14:14:42 -04003128 isec = backing_inode_security(dentry);
David Howells275bb412008-11-14 10:39:19 +11003129 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 FILE__RELABELFROM, &ad);
3131 if (rc)
3132 return rc;
3133
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003134 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003135 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003136 if (!capable(CAP_MAC_ADMIN)) {
3137 struct audit_buffer *ab;
3138 size_t audit_size;
3139 const char *str;
3140
3141 /* We strip a nul only if it is at the end, otherwise the
3142 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003143 if (value) {
3144 str = value;
3145 if (str[size - 1] == '\0')
3146 audit_size = size - 1;
3147 else
3148 audit_size = size;
3149 } else {
3150 str = "";
3151 audit_size = 0;
3152 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003153 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3154 audit_log_format(ab, "op=setxattr invalid_context=");
3155 audit_log_n_untrustedstring(ab, value, audit_size);
3156 audit_log_end(ab);
3157
Stephen Smalley12b29f32008-05-07 13:03:20 -04003158 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003159 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003160 rc = security_context_to_sid_force(value, size, &newsid);
3161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 if (rc)
3163 return rc;
3164
David Howells275bb412008-11-14 10:39:19 +11003165 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 FILE__RELABELTO, &ad);
3167 if (rc)
3168 return rc;
3169
David Howells275bb412008-11-14 10:39:19 +11003170 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003171 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 if (rc)
3173 return rc;
3174
3175 return avc_has_perm(newsid,
3176 sbsec->sid,
3177 SECCLASS_FILESYSTEM,
3178 FILESYSTEM__ASSOCIATE,
3179 &ad);
3180}
3181
David Howells8f0cfa52008-04-29 00:59:41 -07003182static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003183 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003184 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185{
David Howellsc6f493d2015-03-17 22:26:22 +00003186 struct inode *inode = d_backing_inode(dentry);
Paul Moore20cdef82016-04-04 14:14:42 -04003187 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 u32 newsid;
3189 int rc;
3190
3191 if (strcmp(name, XATTR_NAME_SELINUX)) {
3192 /* Not an attribute we recognize, so nothing to do. */
3193 return;
3194 }
3195
Stephen Smalley12b29f32008-05-07 13:03:20 -04003196 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003198 printk(KERN_ERR "SELinux: unable to map context to SID"
3199 "for (%s, %lu), rc=%d\n",
3200 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 return;
3202 }
3203
Paul Moore20cdef82016-04-04 14:14:42 -04003204 isec = backing_inode_security(dentry);
David Quigleyaa9c2662013-05-22 12:50:44 -04003205 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003207 isec->initialized = LABEL_INITIALIZED;
David Quigleyaa9c2662013-05-22 12:50:44 -04003208
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209 return;
3210}
3211
David Howells8f0cfa52008-04-29 00:59:41 -07003212static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213{
David Howells88e67f32008-11-14 10:39:21 +11003214 const struct cred *cred = current_cred();
3215
Eric Paris2875fa02011-04-28 16:04:24 -04003216 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217}
3218
Eric Paris828dfe12008-04-17 13:17:49 -04003219static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220{
David Howells88e67f32008-11-14 10:39:21 +11003221 const struct cred *cred = current_cred();
3222
Eric Paris2875fa02011-04-28 16:04:24 -04003223 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224}
3225
David Howells8f0cfa52008-04-29 00:59:41 -07003226static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003228 if (strcmp(name, XATTR_NAME_SELINUX))
3229 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
3231 /* No one is allowed to remove a SELinux security label.
3232 You can change the label, but all data must be labeled. */
3233 return -EACCES;
3234}
3235
James Morrisd381d8a2005-10-30 14:59:22 -08003236/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003237 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003238 *
3239 * Permission check is handled by selinux_inode_getxattr hook.
3240 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003241static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
David P. Quigley42492592008-02-04 22:29:39 -08003243 u32 size;
3244 int error;
3245 char *context = NULL;
Paul Moore20cdef82016-04-04 14:14:42 -04003246 struct inode_security_struct *isec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003248 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3249 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003251 /*
3252 * If the caller has CAP_MAC_ADMIN, then get the raw context
3253 * value even if it is not defined by current policy; otherwise,
3254 * use the in-core value under current policy.
3255 * Use the non-auditing forms of the permission checks since
3256 * getxattr may be called by unprivileged processes commonly
3257 * and lack of permission just means that we fall back to the
3258 * in-core context value, not a denial.
3259 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003260 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3261 SECURITY_CAP_NOAUDIT);
3262 if (!error)
3263 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003264 SECURITY_CAP_NOAUDIT, true);
Paul Moore20cdef82016-04-04 14:14:42 -04003265 isec = inode_security(inode);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003266 if (!error)
3267 error = security_sid_to_context_force(isec->sid, &context,
3268 &size);
3269 else
3270 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003271 if (error)
3272 return error;
3273 error = size;
3274 if (alloc) {
3275 *buffer = context;
3276 goto out_nofree;
3277 }
3278 kfree(context);
3279out_nofree:
3280 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281}
3282
3283static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003284 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285{
Paul Moore2c971652016-04-19 16:36:28 -04003286 struct inode_security_struct *isec = inode_security_novalidate(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 u32 newsid;
3288 int rc;
3289
3290 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3291 return -EOPNOTSUPP;
3292
3293 if (!value || !size)
3294 return -EACCES;
3295
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003296 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 if (rc)
3298 return rc;
3299
David Quigleyaa9c2662013-05-22 12:50:44 -04003300 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003302 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303 return 0;
3304}
3305
3306static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3307{
3308 const int len = sizeof(XATTR_NAME_SELINUX);
3309 if (buffer && len <= buffer_size)
3310 memcpy(buffer, XATTR_NAME_SELINUX, len);
3311 return len;
3312}
3313
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003314static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003315{
Andreas Gruenbachere817c2f2016-02-18 12:04:08 +01003316 struct inode_security_struct *isec = inode_security_novalidate(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003317 *secid = isec->sid;
3318}
3319
Vivek Goyal56909eb2016-07-13 10:44:48 -04003320static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
3321{
3322 u32 sid;
3323 struct task_security_struct *tsec;
3324 struct cred *new_creds = *new;
3325
3326 if (new_creds == NULL) {
3327 new_creds = prepare_creds();
3328 if (!new_creds)
3329 return -ENOMEM;
3330 }
3331
3332 tsec = new_creds->security;
3333 /* Get label from overlay inode and set it in create_sid */
3334 selinux_inode_getsecid(d_inode(src), &sid);
3335 tsec->create_sid = sid;
3336 *new = new_creds;
3337 return 0;
3338}
3339
Vivek Goyal19472b62016-07-13 10:44:50 -04003340static int selinux_inode_copy_up_xattr(const char *name)
3341{
3342 /* The copy_up hook above sets the initial context on an inode, but we
3343 * don't then want to overwrite it by blindly copying all the lower
3344 * xattrs up. Instead, we have to filter out SELinux-related xattrs.
3345 */
3346 if (strcmp(name, XATTR_NAME_SELINUX) == 0)
3347 return 1; /* Discard */
3348 /*
3349 * Any other attribute apart from SELINUX is not claimed, supported
3350 * by selinux.
3351 */
3352 return -EOPNOTSUPP;
3353}
3354
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355/* file security operations */
3356
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003357static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358{
David Howells88e67f32008-11-14 10:39:21 +11003359 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003360 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3363 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3364 mask |= MAY_APPEND;
3365
Paul Moore389fb8002009-03-27 17:10:34 -04003366 return file_has_perm(cred, file,
3367 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368}
3369
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003370static int selinux_file_permission(struct file *file, int mask)
3371{
Al Viro496ad9a2013-01-23 17:07:38 -05003372 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003373 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003374 struct inode_security_struct *isec;
Stephen Smalley20dda182009-06-22 14:54:53 -04003375 u32 sid = current_sid();
3376
Paul Moore389fb8002009-03-27 17:10:34 -04003377 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003378 /* No permission to check. Existence test. */
3379 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003380
Andreas Gruenbacherb1973672016-01-05 23:12:33 +01003381 isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003382 if (sid == fsec->sid && fsec->isid == isec->sid &&
3383 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003384 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003385 return 0;
3386
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003387 return selinux_revalidate_file_permission(file, mask);
3388}
3389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390static int selinux_file_alloc_security(struct file *file)
3391{
3392 return file_alloc_security(file);
3393}
3394
3395static void selinux_file_free_security(struct file *file)
3396{
3397 file_free_security(file);
3398}
3399
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003400/*
3401 * Check whether a task has the ioctl permission and cmd
3402 * operation to an inode.
3403 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003404static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003405 u32 requested, u16 cmd)
3406{
3407 struct common_audit_data ad;
3408 struct file_security_struct *fsec = file->f_security;
3409 struct inode *inode = file_inode(file);
Paul Moore20cdef82016-04-04 14:14:42 -04003410 struct inode_security_struct *isec;
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003411 struct lsm_ioctlop_audit ioctl;
3412 u32 ssid = cred_sid(cred);
3413 int rc;
3414 u8 driver = cmd >> 8;
3415 u8 xperm = cmd & 0xff;
3416
3417 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3418 ad.u.op = &ioctl;
3419 ad.u.op->cmd = cmd;
3420 ad.u.op->path = file->f_path;
3421
3422 if (ssid != fsec->sid) {
3423 rc = avc_has_perm(ssid, fsec->sid,
3424 SECCLASS_FD,
3425 FD__USE,
3426 &ad);
3427 if (rc)
3428 goto out;
3429 }
3430
3431 if (unlikely(IS_PRIVATE(inode)))
3432 return 0;
3433
Paul Moore20cdef82016-04-04 14:14:42 -04003434 isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003435 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3436 requested, driver, xperm, &ad);
3437out:
3438 return rc;
3439}
3440
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3442 unsigned long arg)
3443{
David Howells88e67f32008-11-14 10:39:21 +11003444 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003445 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446
Eric Paris0b24dcb2011-02-25 15:39:20 -05003447 switch (cmd) {
3448 case FIONREAD:
3449 /* fall through */
3450 case FIBMAP:
3451 /* fall through */
3452 case FIGETBSZ:
3453 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003454 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003455 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003456 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003457 error = file_has_perm(cred, file, FILE__GETATTR);
3458 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
Al Viro2f99c362012-03-23 16:04:05 -04003460 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003461 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003462 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003463 error = file_has_perm(cred, file, FILE__SETATTR);
3464 break;
3465
3466 /* sys_ioctl() checks */
3467 case FIONBIO:
3468 /* fall through */
3469 case FIOASYNC:
3470 error = file_has_perm(cred, file, 0);
3471 break;
3472
3473 case KDSKBENT:
3474 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003475 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
Stephen Smalley8e4ff6f2016-04-08 13:52:00 -04003476 SECURITY_CAP_AUDIT, true);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003477 break;
3478
3479 /* default case assumes that the command will go
3480 * to the file's ioctl() function.
3481 */
3482 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003483 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003484 }
3485 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486}
3487
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003488static int default_noexec;
3489
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3491{
David Howells88e67f32008-11-14 10:39:21 +11003492 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003493 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003494
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003495 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003496 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3497 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 /*
3499 * We are making executable an anonymous mapping or a
3500 * private file mapping that will also be writable.
3501 * This has an additional check.
3502 */
David Howellsd84f4f92008-11-14 10:39:23 +11003503 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003505 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508 if (file) {
3509 /* read access is always possible with a mapping */
3510 u32 av = FILE__READ;
3511
3512 /* write access only matters if the mapping is shared */
3513 if (shared && (prot & PROT_WRITE))
3514 av |= FILE__WRITE;
3515
3516 if (prot & PROT_EXEC)
3517 av |= FILE__EXECUTE;
3518
David Howells88e67f32008-11-14 10:39:21 +11003519 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 }
David Howellsd84f4f92008-11-14 10:39:23 +11003521
3522error:
3523 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524}
3525
Al Viroe5467852012-05-30 13:30:51 -04003526static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003528 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003529
3530 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3531 u32 sid = current_sid();
3532 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3533 MEMPROTECT__MMAP_ZERO, NULL);
3534 }
3535
3536 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003537}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
Al Viroe5467852012-05-30 13:30:51 -04003539static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3540 unsigned long prot, unsigned long flags)
3541{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 if (selinux_checkreqprot)
3543 prot = reqprot;
3544
3545 return file_map_prot_check(file, prot,
3546 (flags & MAP_TYPE) == MAP_SHARED);
3547}
3548
3549static int selinux_file_mprotect(struct vm_area_struct *vma,
3550 unsigned long reqprot,
3551 unsigned long prot)
3552{
David Howells88e67f32008-11-14 10:39:21 +11003553 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554
3555 if (selinux_checkreqprot)
3556 prot = reqprot;
3557
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003558 if (default_noexec &&
3559 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003560 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003561 if (vma->vm_start >= vma->vm_mm->start_brk &&
3562 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003563 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003564 } else if (!vma->vm_file &&
Stephen Smalleyc2316dbf2016-04-08 13:55:03 -04003565 ((vma->vm_start <= vma->vm_mm->start_stack &&
3566 vma->vm_end >= vma->vm_mm->start_stack) ||
Andy Lutomirskid17af502016-09-30 10:58:58 -07003567 vma_is_stack_for_current(vma))) {
David Howells3b11a1d2008-11-14 10:39:26 +11003568 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003569 } else if (vma->vm_file && vma->anon_vma) {
3570 /*
3571 * We are making executable a file mapping that has
3572 * had some COW done. Since pages might have been
3573 * written, check ability to execute the possibly
3574 * modified content. This typically should only
3575 * occur for text relocations.
3576 */
David Howellsd84f4f92008-11-14 10:39:23 +11003577 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003578 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003579 if (rc)
3580 return rc;
3581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
3583 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3584}
3585
3586static int selinux_file_lock(struct file *file, unsigned int cmd)
3587{
David Howells88e67f32008-11-14 10:39:21 +11003588 const struct cred *cred = current_cred();
3589
3590 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591}
3592
3593static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3594 unsigned long arg)
3595{
David Howells88e67f32008-11-14 10:39:21 +11003596 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 int err = 0;
3598
3599 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003600 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003601 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003602 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003604 }
3605 /* fall through */
3606 case F_SETOWN:
3607 case F_SETSIG:
3608 case F_GETFL:
3609 case F_GETOWN:
3610 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003611 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003612 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003613 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003614 break;
3615 case F_GETLK:
3616 case F_SETLK:
3617 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003618 case F_OFD_GETLK:
3619 case F_OFD_SETLK:
3620 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003622 case F_GETLK64:
3623 case F_SETLK64:
3624 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625#endif
David Howells88e67f32008-11-14 10:39:21 +11003626 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003627 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 }
3629
3630 return err;
3631}
3632
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003633static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 struct file_security_struct *fsec;
3636
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003638 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639}
3640
3641static int selinux_file_send_sigiotask(struct task_struct *tsk,
3642 struct fown_struct *fown, int signum)
3643{
Eric Paris828dfe12008-04-17 13:17:49 -04003644 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003645 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 struct file_security_struct *fsec;
3648
3649 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003650 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 fsec = file->f_security;
3653
3654 if (!signum)
3655 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3656 else
3657 perm = signal_to_av(signum);
3658
David Howells275bb412008-11-14 10:39:19 +11003659 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 SECCLASS_PROCESS, perm, NULL);
3661}
3662
3663static int selinux_file_receive(struct file *file)
3664{
David Howells88e67f32008-11-14 10:39:21 +11003665 const struct cred *cred = current_cred();
3666
3667 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668}
3669
Eric Paris83d49852012-04-04 13:45:40 -04003670static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003671{
3672 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003673 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003674
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003675 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003676 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003677 /*
3678 * Save inode label and policy sequence number
3679 * at open-time so that selinux_file_permission
3680 * can determine whether revalidation is necessary.
3681 * Task label is already saved in the file security
3682 * struct as its SID.
3683 */
3684 fsec->isid = isec->sid;
3685 fsec->pseqno = avc_policy_seqno();
3686 /*
3687 * Since the inode label or policy seqno may have changed
3688 * between the selinux_inode_permission check and the saving
3689 * of state above, recheck that access is still permitted.
3690 * Otherwise, access might never be revalidated against the
3691 * new inode label or new policy.
3692 * This check is not redundant - do not remove.
3693 */
David Howells13f8e982013-06-13 23:37:55 +01003694 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003695}
3696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697/* task security operations */
3698
3699static int selinux_task_create(unsigned long clone_flags)
3700{
David Howells3b11a1d2008-11-14 10:39:26 +11003701 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702}
3703
David Howellsf1752ee2008-11-14 10:39:17 +11003704/*
David Howellsee18d642009-09-02 09:14:21 +01003705 * allocate the SELinux part of blank credentials
3706 */
3707static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3708{
3709 struct task_security_struct *tsec;
3710
3711 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3712 if (!tsec)
3713 return -ENOMEM;
3714
3715 cred->security = tsec;
3716 return 0;
3717}
3718
3719/*
David Howellsf1752ee2008-11-14 10:39:17 +11003720 * detach and free the LSM part of a set of credentials
3721 */
3722static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723{
David Howellsf1752ee2008-11-14 10:39:17 +11003724 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003725
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003726 /*
3727 * cred->security == NULL if security_cred_alloc_blank() or
3728 * security_prepare_creds() returned an error.
3729 */
3730 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003731 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003732 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733}
3734
David Howellsd84f4f92008-11-14 10:39:23 +11003735/*
3736 * prepare a new set of credentials for modification
3737 */
3738static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3739 gfp_t gfp)
3740{
3741 const struct task_security_struct *old_tsec;
3742 struct task_security_struct *tsec;
3743
3744 old_tsec = old->security;
3745
3746 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3747 if (!tsec)
3748 return -ENOMEM;
3749
3750 new->security = tsec;
3751 return 0;
3752}
3753
3754/*
David Howellsee18d642009-09-02 09:14:21 +01003755 * transfer the SELinux data to a blank set of creds
3756 */
3757static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3758{
3759 const struct task_security_struct *old_tsec = old->security;
3760 struct task_security_struct *tsec = new->security;
3761
3762 *tsec = *old_tsec;
3763}
3764
3765/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003766 * set the security data for a kernel service
3767 * - all the creation contexts are set to unlabelled
3768 */
3769static int selinux_kernel_act_as(struct cred *new, u32 secid)
3770{
3771 struct task_security_struct *tsec = new->security;
3772 u32 sid = current_sid();
3773 int ret;
3774
3775 ret = avc_has_perm(sid, secid,
3776 SECCLASS_KERNEL_SERVICE,
3777 KERNEL_SERVICE__USE_AS_OVERRIDE,
3778 NULL);
3779 if (ret == 0) {
3780 tsec->sid = secid;
3781 tsec->create_sid = 0;
3782 tsec->keycreate_sid = 0;
3783 tsec->sockcreate_sid = 0;
3784 }
3785 return ret;
3786}
3787
3788/*
3789 * set the file creation context in a security record to the same as the
3790 * objective context of the specified inode
3791 */
3792static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3793{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003794 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003795 struct task_security_struct *tsec = new->security;
3796 u32 sid = current_sid();
3797 int ret;
3798
3799 ret = avc_has_perm(sid, isec->sid,
3800 SECCLASS_KERNEL_SERVICE,
3801 KERNEL_SERVICE__CREATE_FILES_AS,
3802 NULL);
3803
3804 if (ret == 0)
3805 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003806 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003807}
3808
Eric Parisdd8dbf22009-11-03 16:35:32 +11003809static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003810{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003811 u32 sid;
3812 struct common_audit_data ad;
3813
3814 sid = task_sid(current);
3815
Eric Paris50c205f2012-04-04 15:01:43 -04003816 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003817 ad.u.kmod_name = kmod_name;
3818
3819 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3820 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003821}
3822
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07003823static int selinux_kernel_module_from_file(struct file *file)
3824{
3825 struct common_audit_data ad;
3826 struct inode_security_struct *isec;
3827 struct file_security_struct *fsec;
3828 u32 sid = current_sid();
3829 int rc;
3830
3831 /* init_module */
3832 if (file == NULL)
3833 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
3834 SYSTEM__MODULE_LOAD, NULL);
3835
3836 /* finit_module */
Paul Moore20cdef82016-04-04 14:14:42 -04003837
Vivek Goyal43af5de2016-09-09 11:37:49 -04003838 ad.type = LSM_AUDIT_DATA_FILE;
3839 ad.u.file = file;
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07003840
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07003841 fsec = file->f_security;
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07003842 if (sid != fsec->sid) {
3843 rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
3844 if (rc)
3845 return rc;
3846 }
3847
Paul Moore20cdef82016-04-04 14:14:42 -04003848 isec = inode_security(file_inode(file));
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07003849 return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
3850 SYSTEM__MODULE_LOAD, &ad);
3851}
3852
3853static int selinux_kernel_read_file(struct file *file,
3854 enum kernel_read_file_id id)
3855{
3856 int rc = 0;
3857
3858 switch (id) {
3859 case READING_MODULE:
3860 rc = selinux_kernel_module_from_file(file);
3861 break;
3862 default:
3863 break;
3864 }
3865
3866 return rc;
3867}
3868
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3870{
David Howells3b11a1d2008-11-14 10:39:26 +11003871 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872}
3873
3874static int selinux_task_getpgid(struct task_struct *p)
3875{
David Howells3b11a1d2008-11-14 10:39:26 +11003876 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877}
3878
3879static int selinux_task_getsid(struct task_struct *p)
3880{
David Howells3b11a1d2008-11-14 10:39:26 +11003881 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882}
3883
David Quigleyf9008e42006-06-30 01:55:46 -07003884static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3885{
David Howells275bb412008-11-14 10:39:19 +11003886 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003887}
3888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889static int selinux_task_setnice(struct task_struct *p, int nice)
3890{
David Howells3b11a1d2008-11-14 10:39:26 +11003891 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892}
3893
James Morris03e68062006-06-23 02:03:58 -07003894static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3895{
David Howells3b11a1d2008-11-14 10:39:26 +11003896 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003897}
3898
David Quigleya1836a42006-06-30 01:55:49 -07003899static int selinux_task_getioprio(struct task_struct *p)
3900{
David Howells3b11a1d2008-11-14 10:39:26 +11003901 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003902}
3903
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003904static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3905 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003907 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908
3909 /* Control the ability to change the hard limit (whether
3910 lowering or raising it), so that the hard limit can
3911 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003912 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003914 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
3916 return 0;
3917}
3918
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003919static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920{
David Howells3b11a1d2008-11-14 10:39:26 +11003921 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922}
3923
3924static int selinux_task_getscheduler(struct task_struct *p)
3925{
David Howells3b11a1d2008-11-14 10:39:26 +11003926 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927}
3928
David Quigley35601542006-06-23 02:04:01 -07003929static int selinux_task_movememory(struct task_struct *p)
3930{
David Howells3b11a1d2008-11-14 10:39:26 +11003931 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003932}
3933
David Quigleyf9008e42006-06-30 01:55:46 -07003934static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3935 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936{
3937 u32 perm;
3938 int rc;
3939
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 if (!sig)
3941 perm = PROCESS__SIGNULL; /* null signal; existence test */
3942 else
3943 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003944 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003945 rc = avc_has_perm(secid, task_sid(p),
3946 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003947 else
David Howells3b11a1d2008-11-14 10:39:26 +11003948 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003949 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950}
3951
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952static int selinux_task_wait(struct task_struct *p)
3953{
Eric Paris8a535142007-10-22 16:10:31 -04003954 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955}
3956
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957static void selinux_task_to_inode(struct task_struct *p,
3958 struct inode *inode)
3959{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003961 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
David Howells275bb412008-11-14 10:39:19 +11003963 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003964 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965}
3966
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003968static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003969 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970{
3971 int offset, ihlen, ret = -EINVAL;
3972 struct iphdr _iph, *ih;
3973
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003974 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3976 if (ih == NULL)
3977 goto out;
3978
3979 ihlen = ih->ihl * 4;
3980 if (ihlen < sizeof(_iph))
3981 goto out;
3982
Eric Paris48c62af2012-04-02 13:15:44 -04003983 ad->u.net->v4info.saddr = ih->saddr;
3984 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 ret = 0;
3986
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003987 if (proto)
3988 *proto = ih->protocol;
3989
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003991 case IPPROTO_TCP: {
3992 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Eric Paris828dfe12008-04-17 13:17:49 -04003994 if (ntohs(ih->frag_off) & IP_OFFSET)
3995 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 offset += ihlen;
3998 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3999 if (th == NULL)
4000 break;
4001
Eric Paris48c62af2012-04-02 13:15:44 -04004002 ad->u.net->sport = th->source;
4003 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004005 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006
Eric Paris828dfe12008-04-17 13:17:49 -04004007 case IPPROTO_UDP: {
4008 struct udphdr _udph, *uh;
4009
4010 if (ntohs(ih->frag_off) & IP_OFFSET)
4011 break;
4012
4013 offset += ihlen;
4014 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4015 if (uh == NULL)
4016 break;
4017
Eric Paris48c62af2012-04-02 13:15:44 -04004018 ad->u.net->sport = uh->source;
4019 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04004020 break;
4021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
James Morris2ee92d42006-11-13 16:09:01 -08004023 case IPPROTO_DCCP: {
4024 struct dccp_hdr _dccph, *dh;
4025
4026 if (ntohs(ih->frag_off) & IP_OFFSET)
4027 break;
4028
4029 offset += ihlen;
4030 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4031 if (dh == NULL)
4032 break;
4033
Eric Paris48c62af2012-04-02 13:15:44 -04004034 ad->u.net->sport = dh->dccph_sport;
4035 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004036 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004037 }
James Morris2ee92d42006-11-13 16:09:01 -08004038
Eric Paris828dfe12008-04-17 13:17:49 -04004039 default:
4040 break;
4041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042out:
4043 return ret;
4044}
4045
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004046#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
4048/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004049static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04004050 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051{
4052 u8 nexthdr;
4053 int ret = -EINVAL, offset;
4054 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08004055 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03004057 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
4059 if (ip6 == NULL)
4060 goto out;
4061
Eric Paris48c62af2012-04-02 13:15:44 -04004062 ad->u.net->v6info.saddr = ip6->saddr;
4063 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 ret = 0;
4065
4066 nexthdr = ip6->nexthdr;
4067 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08004068 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 if (offset < 0)
4070 goto out;
4071
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004072 if (proto)
4073 *proto = nexthdr;
4074
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 switch (nexthdr) {
4076 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04004077 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
4079 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
4080 if (th == NULL)
4081 break;
4082
Eric Paris48c62af2012-04-02 13:15:44 -04004083 ad->u.net->sport = th->source;
4084 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 break;
4086 }
4087
4088 case IPPROTO_UDP: {
4089 struct udphdr _udph, *uh;
4090
4091 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
4092 if (uh == NULL)
4093 break;
4094
Eric Paris48c62af2012-04-02 13:15:44 -04004095 ad->u.net->sport = uh->source;
4096 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 break;
4098 }
4099
James Morris2ee92d42006-11-13 16:09:01 -08004100 case IPPROTO_DCCP: {
4101 struct dccp_hdr _dccph, *dh;
4102
4103 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
4104 if (dh == NULL)
4105 break;
4106
Eric Paris48c62af2012-04-02 13:15:44 -04004107 ad->u.net->sport = dh->dccph_sport;
4108 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08004109 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004110 }
James Morris2ee92d42006-11-13 16:09:01 -08004111
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 /* includes fragments */
4113 default:
4114 break;
4115 }
4116out:
4117 return ret;
4118}
4119
4120#endif /* IPV6 */
4121
Thomas Liu2bf49692009-07-14 12:14:09 -04004122static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10004123 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
David Howellscf9481e2008-07-27 21:31:07 +10004125 char *addrp;
4126 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Eric Paris48c62af2012-04-02 13:15:44 -04004128 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004130 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004131 if (ret)
4132 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004133 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
4134 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004135 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04004137#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06004139 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10004140 if (ret)
4141 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04004142 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
4143 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10004144 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145#endif /* IPV6 */
4146 default:
David Howellscf9481e2008-07-27 21:31:07 +10004147 addrp = NULL;
4148 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 }
4150
David Howellscf9481e2008-07-27 21:31:07 +10004151parse_error:
4152 printk(KERN_WARNING
4153 "SELinux: failure in selinux_parse_skb(),"
4154 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10004156
4157okay:
4158 if (_addrp)
4159 *_addrp = addrp;
4160 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161}
4162
Paul Moore4f6a9932007-03-01 14:35:22 -05004163/**
Paul Moore220deb92008-01-29 08:38:23 -05004164 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05004165 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05004166 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05004167 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05004168 *
4169 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05004170 * Check the various different forms of network peer labeling and determine
4171 * the peer label/SID for the packet; most of the magic actually occurs in
4172 * the security server function security_net_peersid_cmp(). The function
4173 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
4174 * or -EACCES if @sid is invalid due to inconsistencies with the different
4175 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05004176 *
4177 */
Paul Moore220deb92008-01-29 08:38:23 -05004178static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05004179{
Paul Moore71f1cb02008-01-29 08:51:16 -05004180 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05004181 u32 xfrm_sid;
4182 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05004183 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05004184
Paul Moore817eff72013-12-10 14:57:54 -05004185 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04004186 if (unlikely(err))
4187 return -EACCES;
4188 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
4189 if (unlikely(err))
4190 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05004191
Paul Moore71f1cb02008-01-29 08:51:16 -05004192 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
4193 if (unlikely(err)) {
4194 printk(KERN_WARNING
4195 "SELinux: failure in selinux_skb_peerlbl_sid(),"
4196 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05004197 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05004198 }
Paul Moore220deb92008-01-29 08:38:23 -05004199
4200 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004201}
4202
Paul Moore446b8022013-12-04 16:10:51 -05004203/**
4204 * selinux_conn_sid - Determine the child socket label for a connection
4205 * @sk_sid: the parent socket's SID
4206 * @skb_sid: the packet's SID
4207 * @conn_sid: the resulting connection SID
4208 *
4209 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4210 * combined with the MLS information from @skb_sid in order to create
4211 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4212 * of @sk_sid. Returns zero on success, negative values on failure.
4213 *
4214 */
4215static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4216{
4217 int err = 0;
4218
4219 if (skb_sid != SECSID_NULL)
4220 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4221 else
4222 *conn_sid = sk_sid;
4223
4224 return err;
4225}
4226
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004228
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004229static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4230 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004231{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004232 if (tsec->sockcreate_sid > SECSID_NULL) {
4233 *socksid = tsec->sockcreate_sid;
4234 return 0;
4235 }
4236
4237 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4238 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004239}
4240
Paul Moore253bfae2010-04-22 14:46:19 -04004241static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242{
Paul Moore253bfae2010-04-22 14:46:19 -04004243 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004244 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004245 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004246 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
Paul Moore253bfae2010-04-22 14:46:19 -04004248 if (sksec->sid == SECINITSID_KERNEL)
4249 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Eric Paris50c205f2012-04-04 15:01:43 -04004251 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004252 ad.u.net = &net;
4253 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Paul Moore253bfae2010-04-22 14:46:19 -04004255 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256}
4257
4258static int selinux_socket_create(int family, int type,
4259 int protocol, int kern)
4260{
Paul Moore5fb49872010-04-22 14:46:19 -04004261 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004262 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004263 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004264 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
4266 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004267 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268
David Howells275bb412008-11-14 10:39:19 +11004269 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004270 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4271 if (rc)
4272 return rc;
4273
Paul Moored4f2d972010-04-22 14:46:18 -04004274 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275}
4276
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004277static int selinux_socket_post_create(struct socket *sock, int family,
4278 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279{
Paul Moore5fb49872010-04-22 14:46:19 -04004280 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004281 struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004282 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004283 int err = 0;
4284
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004285 isec->sclass = socket_type_to_security_class(family, type, protocol);
4286
David Howells275bb412008-11-14 10:39:19 +11004287 if (kern)
4288 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004289 else {
4290 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4291 if (err)
4292 return err;
4293 }
David Howells275bb412008-11-14 10:39:19 +11004294
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004295 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004297 if (sock->sk) {
4298 sksec = sock->sk->sk_security;
4299 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004300 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004301 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004302 }
4303
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004304 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305}
4306
4307/* Range of port numbers used to automatically bind.
4308 Need to determine whether we should perform a name_bind
4309 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
4311static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4312{
Paul Moore253bfae2010-04-22 14:46:19 -04004313 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 u16 family;
4315 int err;
4316
Paul Moore253bfae2010-04-22 14:46:19 -04004317 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 if (err)
4319 goto out;
4320
4321 /*
4322 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004323 * Multiple address binding for SCTP is not supported yet: we just
4324 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 */
Paul Moore253bfae2010-04-22 14:46:19 -04004326 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 if (family == PF_INET || family == PF_INET6) {
4328 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004329 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004330 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004331 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 struct sockaddr_in *addr4 = NULL;
4333 struct sockaddr_in6 *addr6 = NULL;
4334 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004335 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 if (family == PF_INET) {
Alexander Potapenkob243aa82017-03-06 19:46:14 +01004338 if (addrlen < sizeof(struct sockaddr_in)) {
4339 err = -EINVAL;
4340 goto out;
4341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 addr4 = (struct sockaddr_in *)address;
4343 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 addrp = (char *)&addr4->sin_addr.s_addr;
4345 } else {
Alexander Potapenkob243aa82017-03-06 19:46:14 +01004346 if (addrlen < SIN6_LEN_RFC2133) {
4347 err = -EINVAL;
4348 goto out;
4349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 addr6 = (struct sockaddr_in6 *)address;
4351 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 addrp = (char *)&addr6->sin6_addr.s6_addr;
4353 }
4354
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004355 if (snum) {
4356 int low, high;
4357
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004358 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004359
4360 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004361 err = sel_netport_sid(sk->sk_protocol,
4362 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004363 if (err)
4364 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004365 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004366 ad.u.net = &net;
4367 ad.u.net->sport = htons(snum);
4368 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004369 err = avc_has_perm(sksec->sid, sid,
4370 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004371 SOCKET__NAME_BIND, &ad);
4372 if (err)
4373 goto out;
4374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 }
Eric Paris828dfe12008-04-17 13:17:49 -04004376
Paul Moore253bfae2010-04-22 14:46:19 -04004377 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004378 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379 node_perm = TCP_SOCKET__NODE_BIND;
4380 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004381
James Morris13402582005-09-30 14:24:34 -04004382 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 node_perm = UDP_SOCKET__NODE_BIND;
4384 break;
James Morris2ee92d42006-11-13 16:09:01 -08004385
4386 case SECCLASS_DCCP_SOCKET:
4387 node_perm = DCCP_SOCKET__NODE_BIND;
4388 break;
4389
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 default:
4391 node_perm = RAWIP_SOCKET__NODE_BIND;
4392 break;
4393 }
Eric Paris828dfe12008-04-17 13:17:49 -04004394
Paul Moore224dfbd2008-01-29 08:38:13 -05004395 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 if (err)
4397 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004398
Eric Paris50c205f2012-04-04 15:01:43 -04004399 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004400 ad.u.net = &net;
4401 ad.u.net->sport = htons(snum);
4402 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
4404 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004405 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 else
Eric Paris48c62af2012-04-02 13:15:44 -04004407 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
Paul Moore253bfae2010-04-22 14:46:19 -04004409 err = avc_has_perm(sksec->sid, sid,
4410 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 if (err)
4412 goto out;
4413 }
4414out:
4415 return err;
4416}
4417
4418static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4419{
Paul Moore014ab192008-10-10 10:16:33 -04004420 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004421 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 int err;
4423
Paul Moore253bfae2010-04-22 14:46:19 -04004424 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 if (err)
4426 return err;
4427
4428 /*
James Morris2ee92d42006-11-13 16:09:01 -08004429 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 */
Paul Moore253bfae2010-04-22 14:46:19 -04004431 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4432 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004433 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004434 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 struct sockaddr_in *addr4 = NULL;
4436 struct sockaddr_in6 *addr6 = NULL;
4437 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004438 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
4440 if (sk->sk_family == PF_INET) {
4441 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004442 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 return -EINVAL;
4444 snum = ntohs(addr4->sin_port);
4445 } else {
4446 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004447 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 return -EINVAL;
4449 snum = ntohs(addr6->sin6_port);
4450 }
4451
Paul Moore3e112172008-04-10 10:48:14 -04004452 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 if (err)
4454 goto out;
4455
Paul Moore253bfae2010-04-22 14:46:19 -04004456 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004457 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4458
Eric Paris50c205f2012-04-04 15:01:43 -04004459 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004460 ad.u.net = &net;
4461 ad.u.net->dport = htons(snum);
4462 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004463 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 if (err)
4465 goto out;
4466 }
4467
Paul Moore014ab192008-10-10 10:16:33 -04004468 err = selinux_netlbl_socket_connect(sk, address);
4469
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470out:
4471 return err;
4472}
4473
4474static int selinux_socket_listen(struct socket *sock, int backlog)
4475{
Paul Moore253bfae2010-04-22 14:46:19 -04004476 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477}
4478
4479static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4480{
4481 int err;
4482 struct inode_security_struct *isec;
4483 struct inode_security_struct *newisec;
4484
Paul Moore253bfae2010-04-22 14:46:19 -04004485 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 if (err)
4487 return err;
4488
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004489 newisec = inode_security_novalidate(SOCK_INODE(newsock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004491 isec = inode_security_novalidate(SOCK_INODE(sock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 newisec->sclass = isec->sclass;
4493 newisec->sid = isec->sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004494 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495
4496 return 0;
4497}
4498
4499static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004500 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501{
Paul Moore253bfae2010-04-22 14:46:19 -04004502 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503}
4504
4505static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4506 int size, int flags)
4507{
Paul Moore253bfae2010-04-22 14:46:19 -04004508 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509}
4510
4511static int selinux_socket_getsockname(struct socket *sock)
4512{
Paul Moore253bfae2010-04-22 14:46:19 -04004513 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514}
4515
4516static int selinux_socket_getpeername(struct socket *sock)
4517{
Paul Moore253bfae2010-04-22 14:46:19 -04004518 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519}
4520
Eric Paris828dfe12008-04-17 13:17:49 -04004521static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522{
Paul Mooref8687af2006-10-30 15:22:15 -08004523 int err;
4524
Paul Moore253bfae2010-04-22 14:46:19 -04004525 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004526 if (err)
4527 return err;
4528
4529 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530}
4531
4532static int selinux_socket_getsockopt(struct socket *sock, int level,
4533 int optname)
4534{
Paul Moore253bfae2010-04-22 14:46:19 -04004535 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536}
4537
4538static int selinux_socket_shutdown(struct socket *sock, int how)
4539{
Paul Moore253bfae2010-04-22 14:46:19 -04004540 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541}
4542
David S. Miller3610cda2011-01-05 15:38:53 -08004543static int selinux_socket_unix_stream_connect(struct sock *sock,
4544 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 struct sock *newsk)
4546{
David S. Miller3610cda2011-01-05 15:38:53 -08004547 struct sk_security_struct *sksec_sock = sock->sk_security;
4548 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004549 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004550 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004551 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 int err;
4553
Eric Paris50c205f2012-04-04 15:01:43 -04004554 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004555 ad.u.net = &net;
4556 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557
Paul Moore4d1e2452010-04-22 14:46:18 -04004558 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4559 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4561 if (err)
4562 return err;
4563
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004565 sksec_new->peer_sid = sksec_sock->sid;
4566 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4567 &sksec_new->sid);
4568 if (err)
4569 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004570
Paul Moore4d1e2452010-04-22 14:46:18 -04004571 /* connecting socket */
4572 sksec_sock->peer_sid = sksec_new->sid;
4573
4574 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575}
4576
4577static int selinux_socket_unix_may_send(struct socket *sock,
4578 struct socket *other)
4579{
Paul Moore253bfae2010-04-22 14:46:19 -04004580 struct sk_security_struct *ssec = sock->sk->sk_security;
4581 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004582 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004583 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584
Eric Paris50c205f2012-04-04 15:01:43 -04004585 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004586 ad.u.net = &net;
4587 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Paul Moore253bfae2010-04-22 14:46:19 -04004589 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4590 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591}
4592
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004593static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4594 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004595 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004596{
4597 int err;
4598 u32 if_sid;
4599 u32 node_sid;
4600
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004601 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004602 if (err)
4603 return err;
4604 err = avc_has_perm(peer_sid, if_sid,
4605 SECCLASS_NETIF, NETIF__INGRESS, ad);
4606 if (err)
4607 return err;
4608
4609 err = sel_netnode_sid(addrp, family, &node_sid);
4610 if (err)
4611 return err;
4612 return avc_has_perm(peer_sid, node_sid,
4613 SECCLASS_NODE, NODE__RECVFROM, ad);
4614}
4615
Paul Moore220deb92008-01-29 08:38:23 -05004616static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004617 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004618{
Paul Moore277d3422008-12-31 12:54:11 -05004619 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004620 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004621 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004622 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004623 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004624 char *addrp;
4625
Eric Paris50c205f2012-04-04 15:01:43 -04004626 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004627 ad.u.net = &net;
4628 ad.u.net->netif = skb->skb_iif;
4629 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004630 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4631 if (err)
4632 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004633
Paul Moore58bfbb52009-03-27 17:10:41 -04004634 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004635 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004636 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004637 if (err)
4638 return err;
4639 }
Paul Moore220deb92008-01-29 08:38:23 -05004640
Steffen Klassertb9679a72011-02-23 12:55:21 +01004641 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4642 if (err)
4643 return err;
4644 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004645
James Morris4e5ab4c2006-06-09 00:33:33 -07004646 return err;
4647}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004648
James Morris4e5ab4c2006-06-09 00:33:33 -07004649static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4650{
Paul Moore220deb92008-01-29 08:38:23 -05004651 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004652 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004653 u16 family = sk->sk_family;
4654 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004655 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004656 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004657 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004658 u8 secmark_active;
4659 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004660
James Morris4e5ab4c2006-06-09 00:33:33 -07004661 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004662 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004663
4664 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004665 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004666 family = PF_INET;
4667
Paul Moored8395c82008-10-10 10:16:30 -04004668 /* If any sort of compatibility mode is enabled then handoff processing
4669 * to the selinux_sock_rcv_skb_compat() function to deal with the
4670 * special handling. We do this in an attempt to keep this function
4671 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004672 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004673 return selinux_sock_rcv_skb_compat(sk, skb, family);
4674
4675 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004676 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004677 if (!secmark_active && !peerlbl_active)
4678 return 0;
4679
Eric Paris50c205f2012-04-04 15:01:43 -04004680 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004681 ad.u.net = &net;
4682 ad.u.net->netif = skb->skb_iif;
4683 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004684 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004685 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004686 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004687
Paul Moored8395c82008-10-10 10:16:30 -04004688 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004689 u32 peer_sid;
4690
4691 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4692 if (err)
4693 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004694 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4695 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004696 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004697 selinux_netlbl_err(skb, family, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004698 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004699 }
Paul Moored621d352008-01-29 08:43:36 -05004700 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4701 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004702 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04004703 selinux_netlbl_err(skb, family, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004704 return err;
4705 }
Paul Moored621d352008-01-29 08:43:36 -05004706 }
4707
Paul Moored8395c82008-10-10 10:16:30 -04004708 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004709 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4710 PACKET__RECV, &ad);
4711 if (err)
4712 return err;
4713 }
4714
Paul Moored621d352008-01-29 08:43:36 -05004715 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716}
4717
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004718static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4719 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720{
4721 int err = 0;
4722 char *scontext;
4723 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004724 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004725 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
Paul Moore253bfae2010-04-22 14:46:19 -04004727 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4728 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004729 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004730 if (peer_sid == SECSID_NULL)
4731 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004733 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004735 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736
4737 if (scontext_len > len) {
4738 err = -ERANGE;
4739 goto out_len;
4740 }
4741
4742 if (copy_to_user(optval, scontext, scontext_len))
4743 err = -EFAULT;
4744
4745out_len:
4746 if (put_user(scontext_len, optlen))
4747 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749 return err;
4750}
4751
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004752static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004753{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004754 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004755 u16 family;
Paul Moore899134f2016-03-28 15:19:10 -04004756 struct inode_security_struct *isec;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004757
Paul Mooreaa862902008-10-10 10:16:29 -04004758 if (skb && skb->protocol == htons(ETH_P_IP))
4759 family = PF_INET;
4760 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4761 family = PF_INET6;
4762 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004763 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004764 else
4765 goto out;
4766
Paul Moore899134f2016-03-28 15:19:10 -04004767 if (sock && family == PF_UNIX) {
4768 isec = inode_security_novalidate(SOCK_INODE(sock));
4769 peer_secid = isec->sid;
4770 } else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004771 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004772
Paul Moore75e22912008-01-29 08:38:04 -05004773out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004774 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004775 if (peer_secid == SECSID_NULL)
4776 return -EINVAL;
4777 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004778}
4779
Al Viro7d877f32005-10-21 03:20:43 -04004780static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781{
Paul Moore84914b72010-04-22 14:46:18 -04004782 struct sk_security_struct *sksec;
4783
4784 sksec = kzalloc(sizeof(*sksec), priority);
4785 if (!sksec)
4786 return -ENOMEM;
4787
4788 sksec->peer_sid = SECINITSID_UNLABELED;
4789 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004790 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004791 selinux_netlbl_sk_security_reset(sksec);
4792 sk->sk_security = sksec;
4793
4794 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795}
4796
4797static void selinux_sk_free_security(struct sock *sk)
4798{
Paul Moore84914b72010-04-22 14:46:18 -04004799 struct sk_security_struct *sksec = sk->sk_security;
4800
4801 sk->sk_security = NULL;
4802 selinux_netlbl_sk_security_free(sksec);
4803 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804}
4805
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004806static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4807{
Eric Parisdd3e7832010-04-07 15:08:46 -04004808 struct sk_security_struct *sksec = sk->sk_security;
4809 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004810
Eric Parisdd3e7832010-04-07 15:08:46 -04004811 newsksec->sid = sksec->sid;
4812 newsksec->peer_sid = sksec->peer_sid;
4813 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004814
Eric Parisdd3e7832010-04-07 15:08:46 -04004815 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004816}
4817
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004818static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004819{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004820 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004821 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004822 else {
4823 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004824
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004825 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004826 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004827}
4828
Eric Paris828dfe12008-04-17 13:17:49 -04004829static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004830{
Andreas Gruenbacher5d226df2015-12-24 11:09:40 -05004831 struct inode_security_struct *isec =
4832 inode_security_novalidate(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004833 struct sk_security_struct *sksec = sk->sk_security;
4834
Paul Moore2873ead2014-07-28 10:42:48 -04004835 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4836 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004837 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004838 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004839}
4840
Adrian Bunk9a673e52006-08-15 00:03:53 -07004841static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4842 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004843{
4844 struct sk_security_struct *sksec = sk->sk_security;
4845 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004846 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004847 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004848 u32 peersid;
4849
Paul Mooreaa862902008-10-10 10:16:29 -04004850 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004851 if (err)
4852 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004853 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4854 if (err)
4855 return err;
4856 req->secid = connsid;
4857 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004858
Paul Moore389fb8002009-03-27 17:10:34 -04004859 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004860}
4861
Adrian Bunk9a673e52006-08-15 00:03:53 -07004862static void selinux_inet_csk_clone(struct sock *newsk,
4863 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004864{
4865 struct sk_security_struct *newsksec = newsk->sk_security;
4866
4867 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004868 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004869 /* NOTE: Ideally, we should also get the isec->sid for the
4870 new socket in sync, but we don't have the isec available yet.
4871 So we will wait until sock_graft to do it, by which
4872 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004873
Paul Moore9f2ad662006-11-17 17:38:53 -05004874 /* We don't need to take any sort of lock here as we are the only
4875 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004876 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004877}
4878
Paul Moore014ab192008-10-10 10:16:33 -04004879static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004880{
Paul Mooreaa862902008-10-10 10:16:29 -04004881 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004882 struct sk_security_struct *sksec = sk->sk_security;
4883
Paul Mooreaa862902008-10-10 10:16:29 -04004884 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4885 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4886 family = PF_INET;
4887
4888 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004889}
4890
Eric Paris2606fd12010-10-13 16:24:41 -04004891static int selinux_secmark_relabel_packet(u32 sid)
4892{
4893 const struct task_security_struct *__tsec;
4894 u32 tsid;
4895
4896 __tsec = current_security();
4897 tsid = __tsec->sid;
4898
4899 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4900}
4901
4902static void selinux_secmark_refcount_inc(void)
4903{
4904 atomic_inc(&selinux_secmark_refcount);
4905}
4906
4907static void selinux_secmark_refcount_dec(void)
4908{
4909 atomic_dec(&selinux_secmark_refcount);
4910}
4911
Adrian Bunk9a673e52006-08-15 00:03:53 -07004912static void selinux_req_classify_flow(const struct request_sock *req,
4913 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004914{
David S. Miller1d28f422011-03-12 00:29:39 -05004915 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004916}
4917
Paul Moore5dbbaf22013-01-14 07:12:19 +00004918static int selinux_tun_dev_alloc_security(void **security)
4919{
4920 struct tun_security_struct *tunsec;
4921
4922 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4923 if (!tunsec)
4924 return -ENOMEM;
4925 tunsec->sid = current_sid();
4926
4927 *security = tunsec;
4928 return 0;
4929}
4930
4931static void selinux_tun_dev_free_security(void *security)
4932{
4933 kfree(security);
4934}
4935
Paul Mooreed6d76e2009-08-28 18:12:49 -04004936static int selinux_tun_dev_create(void)
4937{
4938 u32 sid = current_sid();
4939
4940 /* we aren't taking into account the "sockcreate" SID since the socket
4941 * that is being created here is not a socket in the traditional sense,
4942 * instead it is a private sock, accessible only to the kernel, and
4943 * representing a wide range of network traffic spanning multiple
4944 * connections unlike traditional sockets - check the TUN driver to
4945 * get a better understanding of why this socket is special */
4946
4947 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4948 NULL);
4949}
4950
Paul Moore5dbbaf22013-01-14 07:12:19 +00004951static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004952{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004953 struct tun_security_struct *tunsec = security;
4954
4955 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4956 TUN_SOCKET__ATTACH_QUEUE, NULL);
4957}
4958
4959static int selinux_tun_dev_attach(struct sock *sk, void *security)
4960{
4961 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004962 struct sk_security_struct *sksec = sk->sk_security;
4963
4964 /* we don't currently perform any NetLabel based labeling here and it
4965 * isn't clear that we would want to do so anyway; while we could apply
4966 * labeling without the support of the TUN user the resulting labeled
4967 * traffic from the other end of the connection would almost certainly
4968 * cause confusion to the TUN user that had no idea network labeling
4969 * protocols were being used */
4970
Paul Moore5dbbaf22013-01-14 07:12:19 +00004971 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004972 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004973
4974 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004975}
4976
Paul Moore5dbbaf22013-01-14 07:12:19 +00004977static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004978{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004979 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004980 u32 sid = current_sid();
4981 int err;
4982
Paul Moore5dbbaf22013-01-14 07:12:19 +00004983 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004984 TUN_SOCKET__RELABELFROM, NULL);
4985 if (err)
4986 return err;
4987 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4988 TUN_SOCKET__RELABELTO, NULL);
4989 if (err)
4990 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004991 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004992
4993 return 0;
4994}
4995
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4997{
4998 int err = 0;
4999 u32 perm;
5000 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04005001 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04005002
Hong zhi guo77954982013-03-27 06:49:35 +00005003 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004 err = -EINVAL;
5005 goto out;
5006 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07005007 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04005008
Paul Moore253bfae2010-04-22 14:46:19 -04005009 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010 if (err) {
5011 if (err == -EINVAL) {
Vladis Dronov76319942015-12-24 11:09:41 -05005012 pr_warn_ratelimited("SELinux: unrecognized netlink"
5013 " message: protocol=%hu nlmsg_type=%hu sclass=%s"
5014 " pig=%d comm=%s\n",
Marek Milkoviccded3ff2015-06-04 16:22:16 -04005015 sk->sk_protocol, nlh->nlmsg_type,
Vladis Dronov76319942015-12-24 11:09:41 -05005016 secclass_map[sksec->sclass - 1].name,
5017 task_pid_nr(current), current->comm);
Eric Paris39c9aed2008-11-05 09:34:42 -05005018 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019 err = 0;
5020 }
5021
5022 /* Ignore */
5023 if (err == -ENOENT)
5024 err = 0;
5025 goto out;
5026 }
5027
Paul Moore253bfae2010-04-22 14:46:19 -04005028 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029out:
5030 return err;
5031}
5032
5033#ifdef CONFIG_NETFILTER
5034
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005035static unsigned int selinux_ip_forward(struct sk_buff *skb,
5036 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005037 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038{
Paul Mooredfaebe92008-10-10 10:16:31 -04005039 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005040 char *addrp;
5041 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04005042 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005043 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005044 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04005045 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005046 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005047
Paul Mooreeffad8d2008-01-29 08:49:27 -05005048 if (!selinux_policycap_netpeer)
5049 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005050
Paul Mooreeffad8d2008-01-29 08:49:27 -05005051 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04005052 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005053 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005054 if (!secmark_active && !peerlbl_active)
5055 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005056
Paul Moored8395c82008-10-10 10:16:30 -04005057 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
5058 return NF_DROP;
5059
Eric Paris50c205f2012-04-04 15:01:43 -04005060 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005061 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005062 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04005063 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005064 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
5065 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066
Paul Mooredfaebe92008-10-10 10:16:31 -04005067 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005068 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
5069 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04005070 if (err) {
Huw Daviesa04e71f2016-06-27 15:06:16 -04005071 selinux_netlbl_err(skb, family, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005072 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04005073 }
5074 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05005075
5076 if (secmark_active)
5077 if (avc_has_perm(peer_sid, skb->secmark,
5078 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
5079 return NF_DROP;
5080
Paul Moore948bf852008-10-10 10:16:32 -04005081 if (netlbl_active)
5082 /* we do this in the FORWARD path and not the POST_ROUTING
5083 * path because we want to make sure we apply the necessary
5084 * labeling before IPsec is applied so we can leverage AH
5085 * protection */
5086 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
5087 return NF_DROP;
5088
Paul Mooreeffad8d2008-01-29 08:49:27 -05005089 return NF_ACCEPT;
5090}
5091
Eric W. Biederman06198b32015-09-18 14:33:06 -05005092static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005093 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005094 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005095{
David S. Miller238e54c2015-04-03 20:32:56 -04005096 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005097}
5098
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005099#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005100static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005101 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005102 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005103{
David S. Miller238e54c2015-04-03 20:32:56 -04005104 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005105}
5106#endif /* IPV6 */
5107
Paul Moore948bf852008-10-10 10:16:32 -04005108static unsigned int selinux_ip_output(struct sk_buff *skb,
5109 u16 family)
5110{
Paul Moore47180062013-12-04 16:10:45 -05005111 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04005112 u32 sid;
5113
5114 if (!netlbl_enabled())
5115 return NF_ACCEPT;
5116
5117 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
5118 * because we want to make sure we apply the necessary labeling
5119 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05005120 sk = skb->sk;
5121 if (sk) {
5122 struct sk_security_struct *sksec;
5123
Eric Dumazete446f9d2015-10-08 05:01:55 -07005124 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05005125 /* if the socket is the listening state then this
5126 * packet is a SYN-ACK packet which means it needs to
5127 * be labeled based on the connection/request_sock and
5128 * not the parent socket. unfortunately, we can't
5129 * lookup the request_sock yet as it isn't queued on
5130 * the parent socket until after the SYN-ACK is sent.
5131 * the "solution" is to simply pass the packet as-is
5132 * as any IP option based labeling should be copied
5133 * from the initial connection request (in the IP
5134 * layer). it is far from ideal, but until we get a
5135 * security label in the packet itself this is the
5136 * best we can do. */
5137 return NF_ACCEPT;
5138
5139 /* standard practice, label using the parent socket */
5140 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04005141 sid = sksec->sid;
5142 } else
5143 sid = SECINITSID_KERNEL;
5144 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
5145 return NF_DROP;
5146
5147 return NF_ACCEPT;
5148}
5149
Eric W. Biederman06198b32015-09-18 14:33:06 -05005150static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04005151 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005152 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04005153{
5154 return selinux_ip_output(skb, PF_INET);
5155}
5156
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005157#if IS_ENABLED(CONFIG_IPV6)
Huw Davies2917f572016-06-27 15:06:15 -04005158static unsigned int selinux_ipv6_output(void *priv,
5159 struct sk_buff *skb,
5160 const struct nf_hook_state *state)
5161{
5162 return selinux_ip_output(skb, PF_INET6);
5163}
5164#endif /* IPV6 */
5165
Paul Mooreeffad8d2008-01-29 08:49:27 -05005166static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5167 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04005168 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07005169{
Eric Dumazet54abc682015-11-08 10:54:07 -08005170 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005171 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005172 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005173 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04005174 char *addrp;
5175 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07005176
Paul Mooreeffad8d2008-01-29 08:49:27 -05005177 if (sk == NULL)
5178 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005179 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07005180
Eric Paris50c205f2012-04-04 15:01:43 -04005181 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005182 ad.u.net = &net;
5183 ad.u.net->netif = ifindex;
5184 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005185 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
5186 return NF_DROP;
5187
Paul Moore58bfbb52009-03-27 17:10:41 -04005188 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05005189 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04005190 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00005191 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005192
Steffen Klassertb9679a72011-02-23 12:55:21 +01005193 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
5194 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07005195
Paul Mooreeffad8d2008-01-29 08:49:27 -05005196 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197}
5198
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005199static unsigned int selinux_ip_postroute(struct sk_buff *skb,
5200 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005201 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005203 u32 secmark_perm;
5204 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005205 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005206 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04005207 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04005208 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05005209 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005210 u8 secmark_active;
5211 u8 peerlbl_active;
5212
Paul Mooreeffad8d2008-01-29 08:49:27 -05005213 /* If any sort of compatibility mode is enabled then handoff processing
5214 * to the selinux_ip_postroute_compat() function to deal with the
5215 * special handling. We do this in an attempt to keep this function
5216 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04005217 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04005218 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05005219
Paul Mooreeffad8d2008-01-29 08:49:27 -05005220 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005221 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005222 if (!secmark_active && !peerlbl_active)
5223 return NF_ACCEPT;
5224
Eric Dumazet54abc682015-11-08 10:54:07 -08005225 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005226
Paul Mooreeffad8d2008-01-29 08:49:27 -05005227#ifdef CONFIG_XFRM
5228 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5229 * packet transformation so allow the packet to pass without any checks
5230 * since we'll have another chance to perform access control checks
5231 * when the packet is on it's final way out.
5232 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005233 * is NULL, in this case go ahead and apply access control.
5234 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5235 * TCP listening state we cannot wait until the XFRM processing
5236 * is done as we will miss out on the SA label if we do;
5237 * unfortunately, this means more work, but it is only once per
5238 * connection. */
5239 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005240 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005241 return NF_ACCEPT;
5242#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005243
Paul Moored8395c82008-10-10 10:16:30 -04005244 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005245 /* Without an associated socket the packet is either coming
5246 * from the kernel or it is being forwarded; check the packet
5247 * to determine which and if the packet is being forwarded
5248 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005249 if (skb->skb_iif) {
5250 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005251 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005252 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005253 } else {
5254 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005255 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005256 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005257 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005258 /* Locally generated packet but the associated socket is in the
5259 * listening state which means this is a SYN-ACK packet. In
5260 * this particular case the correct security label is assigned
5261 * to the connection/request_sock but unfortunately we can't
5262 * query the request_sock as it isn't queued on the parent
5263 * socket until after the SYN-ACK packet is sent; the only
5264 * viable choice is to regenerate the label like we do in
5265 * selinux_inet_conn_request(). See also selinux_ip_output()
5266 * for similar problems. */
5267 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005268 struct sk_security_struct *sksec;
5269
Eric Dumazete446f9d2015-10-08 05:01:55 -07005270 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005271 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5272 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005273 /* At this point, if the returned skb peerlbl is SECSID_NULL
5274 * and the packet has been through at least one XFRM
5275 * transformation then we must be dealing with the "final"
5276 * form of labeled IPsec packet; since we've already applied
5277 * all of our access controls on this packet we can safely
5278 * pass the packet. */
5279 if (skb_sid == SECSID_NULL) {
5280 switch (family) {
5281 case PF_INET:
5282 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5283 return NF_ACCEPT;
5284 break;
5285 case PF_INET6:
5286 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5287 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005288 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005289 default:
5290 return NF_DROP_ERR(-ECONNREFUSED);
5291 }
5292 }
Paul Moore446b8022013-12-04 16:10:51 -05005293 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5294 return NF_DROP;
5295 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005296 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005297 /* Locally generated packet, fetch the security label from the
5298 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005299 struct sk_security_struct *sksec = sk->sk_security;
5300 peer_sid = sksec->sid;
5301 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005302 }
5303
Eric Paris50c205f2012-04-04 15:01:43 -04005304 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005305 ad.u.net = &net;
5306 ad.u.net->netif = ifindex;
5307 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005308 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005309 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005310
Paul Mooreeffad8d2008-01-29 08:49:27 -05005311 if (secmark_active)
5312 if (avc_has_perm(peer_sid, skb->secmark,
5313 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005314 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005315
5316 if (peerlbl_active) {
5317 u32 if_sid;
5318 u32 node_sid;
5319
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005320 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005321 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005322 if (avc_has_perm(peer_sid, if_sid,
5323 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005324 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005325
5326 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005327 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005328 if (avc_has_perm(peer_sid, node_sid,
5329 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005330 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005331 }
5332
5333 return NF_ACCEPT;
5334}
5335
Eric W. Biederman06198b32015-09-18 14:33:06 -05005336static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005337 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005338 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005339{
David S. Miller238e54c2015-04-03 20:32:56 -04005340 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341}
5342
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04005343#if IS_ENABLED(CONFIG_IPV6)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005344static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005345 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005346 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347{
David S. Miller238e54c2015-04-03 20:32:56 -04005348 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350#endif /* IPV6 */
5351
5352#endif /* CONFIG_NETFILTER */
5353
Linus Torvalds1da177e2005-04-16 15:20:36 -07005354static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5355{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005356 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357}
5358
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359static int ipc_alloc_security(struct task_struct *task,
5360 struct kern_ipc_perm *perm,
5361 u16 sclass)
5362{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005364 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365
James Morris89d155e2005-10-30 14:59:21 -08005366 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 if (!isec)
5368 return -ENOMEM;
5369
David Howells275bb412008-11-14 10:39:19 +11005370 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005372 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 perm->security = isec;
5374
5375 return 0;
5376}
5377
5378static void ipc_free_security(struct kern_ipc_perm *perm)
5379{
5380 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 perm->security = NULL;
5382 kfree(isec);
5383}
5384
5385static int msg_msg_alloc_security(struct msg_msg *msg)
5386{
5387 struct msg_security_struct *msec;
5388
James Morris89d155e2005-10-30 14:59:21 -08005389 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 if (!msec)
5391 return -ENOMEM;
5392
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393 msec->sid = SECINITSID_UNLABELED;
5394 msg->security = msec;
5395
5396 return 0;
5397}
5398
5399static void msg_msg_free_security(struct msg_msg *msg)
5400{
5401 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
5403 msg->security = NULL;
5404 kfree(msec);
5405}
5406
5407static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005408 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005411 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005412 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414 isec = ipc_perms->security;
5415
Eric Paris50c205f2012-04-04 15:01:43 -04005416 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 ad.u.ipc_id = ipc_perms->key;
5418
David Howells275bb412008-11-14 10:39:19 +11005419 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420}
5421
5422static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5423{
5424 return msg_msg_alloc_security(msg);
5425}
5426
5427static void selinux_msg_msg_free_security(struct msg_msg *msg)
5428{
5429 msg_msg_free_security(msg);
5430}
5431
5432/* message queue security operations */
5433static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5434{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005436 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005437 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438 int rc;
5439
5440 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5441 if (rc)
5442 return rc;
5443
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444 isec = msq->q_perm.security;
5445
Eric Paris50c205f2012-04-04 15:01:43 -04005446 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005447 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448
David Howells275bb412008-11-14 10:39:19 +11005449 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005450 MSGQ__CREATE, &ad);
5451 if (rc) {
5452 ipc_free_security(&msq->q_perm);
5453 return rc;
5454 }
5455 return 0;
5456}
5457
5458static void selinux_msg_queue_free_security(struct msg_queue *msq)
5459{
5460 ipc_free_security(&msq->q_perm);
5461}
5462
5463static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5464{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005466 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005467 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469 isec = msq->q_perm.security;
5470
Eric Paris50c205f2012-04-04 15:01:43 -04005471 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472 ad.u.ipc_id = msq->q_perm.key;
5473
David Howells275bb412008-11-14 10:39:19 +11005474 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005475 MSGQ__ASSOCIATE, &ad);
5476}
5477
5478static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5479{
5480 int err;
5481 int perms;
5482
Eric Paris828dfe12008-04-17 13:17:49 -04005483 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 case IPC_INFO:
5485 case MSG_INFO:
5486 /* No specific object, just general system-wide information. */
5487 return task_has_system(current, SYSTEM__IPC_INFO);
5488 case IPC_STAT:
5489 case MSG_STAT:
5490 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5491 break;
5492 case IPC_SET:
5493 perms = MSGQ__SETATTR;
5494 break;
5495 case IPC_RMID:
5496 perms = MSGQ__DESTROY;
5497 break;
5498 default:
5499 return 0;
5500 }
5501
Stephen Smalley6af963f2005-05-01 08:58:39 -07005502 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 return err;
5504}
5505
5506static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5507{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508 struct ipc_security_struct *isec;
5509 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005510 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005511 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 int rc;
5513
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514 isec = msq->q_perm.security;
5515 msec = msg->security;
5516
5517 /*
5518 * First time through, need to assign label to the message
5519 */
5520 if (msec->sid == SECINITSID_UNLABELED) {
5521 /*
5522 * Compute new sid based on current process and
5523 * message queue this message will be stored in
5524 */
David Howells275bb412008-11-14 10:39:19 +11005525 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005526 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527 if (rc)
5528 return rc;
5529 }
5530
Eric Paris50c205f2012-04-04 15:01:43 -04005531 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532 ad.u.ipc_id = msq->q_perm.key;
5533
5534 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005535 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536 MSGQ__WRITE, &ad);
5537 if (!rc)
5538 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005539 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5540 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541 if (!rc)
5542 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005543 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5544 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545
5546 return rc;
5547}
5548
5549static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5550 struct task_struct *target,
5551 long type, int mode)
5552{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553 struct ipc_security_struct *isec;
5554 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005555 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005556 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 int rc;
5558
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559 isec = msq->q_perm.security;
5560 msec = msg->security;
5561
Eric Paris50c205f2012-04-04 15:01:43 -04005562 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005563 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564
David Howells275bb412008-11-14 10:39:19 +11005565 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 SECCLASS_MSGQ, MSGQ__READ, &ad);
5567 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005568 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005569 SECCLASS_MSG, MSG__RECEIVE, &ad);
5570 return rc;
5571}
5572
5573/* Shared Memory security operations */
5574static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5575{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005577 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005578 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579 int rc;
5580
5581 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5582 if (rc)
5583 return rc;
5584
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 isec = shp->shm_perm.security;
5586
Eric Paris50c205f2012-04-04 15:01:43 -04005587 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005588 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
David Howells275bb412008-11-14 10:39:19 +11005590 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005591 SHM__CREATE, &ad);
5592 if (rc) {
5593 ipc_free_security(&shp->shm_perm);
5594 return rc;
5595 }
5596 return 0;
5597}
5598
5599static void selinux_shm_free_security(struct shmid_kernel *shp)
5600{
5601 ipc_free_security(&shp->shm_perm);
5602}
5603
5604static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5605{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005607 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005608 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 isec = shp->shm_perm.security;
5611
Eric Paris50c205f2012-04-04 15:01:43 -04005612 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 ad.u.ipc_id = shp->shm_perm.key;
5614
David Howells275bb412008-11-14 10:39:19 +11005615 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616 SHM__ASSOCIATE, &ad);
5617}
5618
5619/* Note, at this point, shp is locked down */
5620static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5621{
5622 int perms;
5623 int err;
5624
Eric Paris828dfe12008-04-17 13:17:49 -04005625 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626 case IPC_INFO:
5627 case SHM_INFO:
5628 /* No specific object, just general system-wide information. */
5629 return task_has_system(current, SYSTEM__IPC_INFO);
5630 case IPC_STAT:
5631 case SHM_STAT:
5632 perms = SHM__GETATTR | SHM__ASSOCIATE;
5633 break;
5634 case IPC_SET:
5635 perms = SHM__SETATTR;
5636 break;
5637 case SHM_LOCK:
5638 case SHM_UNLOCK:
5639 perms = SHM__LOCK;
5640 break;
5641 case IPC_RMID:
5642 perms = SHM__DESTROY;
5643 break;
5644 default:
5645 return 0;
5646 }
5647
Stephen Smalley6af963f2005-05-01 08:58:39 -07005648 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649 return err;
5650}
5651
5652static int selinux_shm_shmat(struct shmid_kernel *shp,
5653 char __user *shmaddr, int shmflg)
5654{
5655 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656
5657 if (shmflg & SHM_RDONLY)
5658 perms = SHM__READ;
5659 else
5660 perms = SHM__READ | SHM__WRITE;
5661
Stephen Smalley6af963f2005-05-01 08:58:39 -07005662 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663}
5664
5665/* Semaphore security operations */
5666static int selinux_sem_alloc_security(struct sem_array *sma)
5667{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005669 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005670 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671 int rc;
5672
5673 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5674 if (rc)
5675 return rc;
5676
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677 isec = sma->sem_perm.security;
5678
Eric Paris50c205f2012-04-04 15:01:43 -04005679 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005680 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005681
David Howells275bb412008-11-14 10:39:19 +11005682 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683 SEM__CREATE, &ad);
5684 if (rc) {
5685 ipc_free_security(&sma->sem_perm);
5686 return rc;
5687 }
5688 return 0;
5689}
5690
5691static void selinux_sem_free_security(struct sem_array *sma)
5692{
5693 ipc_free_security(&sma->sem_perm);
5694}
5695
5696static int selinux_sem_associate(struct sem_array *sma, int semflg)
5697{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005699 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005700 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
Linus Torvalds1da177e2005-04-16 15:20:36 -07005702 isec = sma->sem_perm.security;
5703
Eric Paris50c205f2012-04-04 15:01:43 -04005704 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705 ad.u.ipc_id = sma->sem_perm.key;
5706
David Howells275bb412008-11-14 10:39:19 +11005707 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708 SEM__ASSOCIATE, &ad);
5709}
5710
5711/* Note, at this point, sma is locked down */
5712static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5713{
5714 int err;
5715 u32 perms;
5716
Eric Paris828dfe12008-04-17 13:17:49 -04005717 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718 case IPC_INFO:
5719 case SEM_INFO:
5720 /* No specific object, just general system-wide information. */
5721 return task_has_system(current, SYSTEM__IPC_INFO);
5722 case GETPID:
5723 case GETNCNT:
5724 case GETZCNT:
5725 perms = SEM__GETATTR;
5726 break;
5727 case GETVAL:
5728 case GETALL:
5729 perms = SEM__READ;
5730 break;
5731 case SETVAL:
5732 case SETALL:
5733 perms = SEM__WRITE;
5734 break;
5735 case IPC_RMID:
5736 perms = SEM__DESTROY;
5737 break;
5738 case IPC_SET:
5739 perms = SEM__SETATTR;
5740 break;
5741 case IPC_STAT:
5742 case SEM_STAT:
5743 perms = SEM__GETATTR | SEM__ASSOCIATE;
5744 break;
5745 default:
5746 return 0;
5747 }
5748
Stephen Smalley6af963f2005-05-01 08:58:39 -07005749 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750 return err;
5751}
5752
5753static int selinux_sem_semop(struct sem_array *sma,
5754 struct sembuf *sops, unsigned nsops, int alter)
5755{
5756 u32 perms;
5757
5758 if (alter)
5759 perms = SEM__READ | SEM__WRITE;
5760 else
5761 perms = SEM__READ;
5762
Stephen Smalley6af963f2005-05-01 08:58:39 -07005763 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764}
5765
5766static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5767{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768 u32 av = 0;
5769
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770 av = 0;
5771 if (flag & S_IRUGO)
5772 av |= IPC__UNIX_READ;
5773 if (flag & S_IWUGO)
5774 av |= IPC__UNIX_WRITE;
5775
5776 if (av == 0)
5777 return 0;
5778
Stephen Smalley6af963f2005-05-01 08:58:39 -07005779 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780}
5781
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005782static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5783{
5784 struct ipc_security_struct *isec = ipcp->security;
5785 *secid = isec->sid;
5786}
5787
Eric Paris828dfe12008-04-17 13:17:49 -04005788static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789{
5790 if (inode)
5791 inode_doinit_with_dentry(inode, dentry);
5792}
5793
5794static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005795 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005796{
David Howells275bb412008-11-14 10:39:19 +11005797 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005798 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005800 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801
5802 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005803 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804 if (error)
5805 return error;
5806 }
5807
David Howells275bb412008-11-14 10:39:19 +11005808 rcu_read_lock();
5809 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810
5811 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005812 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005814 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005816 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005818 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005819 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005820 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005821 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005822 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823 else
David Howells275bb412008-11-14 10:39:19 +11005824 goto invalid;
5825 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826
5827 if (!sid)
5828 return 0;
5829
Al Viro04ff9702007-03-12 16:17:58 +00005830 error = security_sid_to_context(sid, value, &len);
5831 if (error)
5832 return error;
5833 return len;
David Howells275bb412008-11-14 10:39:19 +11005834
5835invalid:
5836 rcu_read_unlock();
5837 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838}
5839
5840static int selinux_setprocattr(struct task_struct *p,
5841 char *name, void *value, size_t size)
5842{
5843 struct task_security_struct *tsec;
David Howellsd84f4f92008-11-14 10:39:23 +11005844 struct cred *new;
5845 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 int error;
5847 char *str = value;
5848
5849 if (current != p) {
5850 /* SELinux only allows a process to change its own
5851 security attributes. */
5852 return -EACCES;
5853 }
5854
5855 /*
5856 * Basic control over ability to set these attributes at all.
5857 * current == p, but we'll pass them separately in case the
5858 * above restriction is ever removed.
5859 */
5860 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005861 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005863 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005864 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005865 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005866 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005867 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005869 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870 else
5871 error = -EINVAL;
5872 if (error)
5873 return error;
5874
5875 /* Obtain a SID for the context, if one was specified. */
Stephen Smalley6cbaf7b2017-01-31 11:54:04 -05005876 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877 if (str[size-1] == '\n') {
5878 str[size-1] = 0;
5879 size--;
5880 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005881 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005882 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005883 if (!capable(CAP_MAC_ADMIN)) {
5884 struct audit_buffer *ab;
5885 size_t audit_size;
5886
5887 /* We strip a nul only if it is at the end, otherwise the
5888 * context contains a nul and we should audit that */
5889 if (str[size - 1] == '\0')
5890 audit_size = size - 1;
5891 else
5892 audit_size = size;
5893 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5894 audit_log_format(ab, "op=fscreate invalid_context=");
5895 audit_log_n_untrustedstring(ab, value, audit_size);
5896 audit_log_end(ab);
5897
Stephen Smalley12b29f32008-05-07 13:03:20 -04005898 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005899 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005900 error = security_context_to_sid_force(value, size,
5901 &sid);
5902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903 if (error)
5904 return error;
5905 }
5906
David Howellsd84f4f92008-11-14 10:39:23 +11005907 new = prepare_creds();
5908 if (!new)
5909 return -ENOMEM;
5910
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911 /* Permission checking based on the specified context is
5912 performed during the actual operation (execve,
5913 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005914 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 checks and may_create for the file creation checks. The
5916 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005917 tsec = new->security;
5918 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005920 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005922 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005923 error = may_create_key(sid, p);
5924 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005925 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005926 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005927 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005928 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005929 } else if (!strcmp(name, "current")) {
5930 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005932 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005933
David Howellsd84f4f92008-11-14 10:39:23 +11005934 /* Only allow single threaded processes to change context */
5935 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005936 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005937 error = security_bounded_transition(tsec->sid, sid);
5938 if (error)
5939 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
5942 /* Check permissions for the transition. */
5943 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005944 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005946 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
5948 /* Check for ptracing, and update the task SID if ok.
5949 Otherwise, leave SID unchanged and fail. */
Paul Moore0c6181c2016-03-30 21:41:21 -04005950 ptsid = ptrace_parent_sid(p);
5951 if (ptsid != 0) {
David Howellsd84f4f92008-11-14 10:39:23 +11005952 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5953 PROCESS__PTRACE, NULL);
5954 if (error)
5955 goto abort_change;
5956 }
5957
5958 tsec->sid = sid;
5959 } else {
5960 error = -EINVAL;
5961 goto abort_change;
5962 }
5963
5964 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005966
5967abort_change:
5968 abort_creds(new);
5969 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970}
5971
David Quigley746df9b2013-05-22 12:50:35 -04005972static int selinux_ismaclabel(const char *name)
5973{
5974 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5975}
5976
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005977static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5978{
5979 return security_sid_to_context(secid, secdata, seclen);
5980}
5981
David Howells7bf570d2008-04-29 20:52:51 +01005982static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005983{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005984 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005985}
5986
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005987static void selinux_release_secctx(char *secdata, u32 seclen)
5988{
Paul Moore088999e2007-08-01 11:12:58 -04005989 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005990}
5991
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05005992static void selinux_inode_invalidate_secctx(struct inode *inode)
5993{
5994 struct inode_security_struct *isec = inode->i_security;
5995
5996 mutex_lock(&isec->lock);
5997 isec->initialized = LABEL_INVALID;
5998 mutex_unlock(&isec->lock);
5999}
6000
David P. Quigley1ee65e32009-09-03 14:25:57 -04006001/*
6002 * called with inode->i_mutex locked
6003 */
6004static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
6005{
6006 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
6007}
6008
6009/*
6010 * called with inode->i_mutex locked
6011 */
6012static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
6013{
6014 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
6015}
6016
6017static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
6018{
6019 int len = 0;
6020 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
6021 ctx, true);
6022 if (len < 0)
6023 return len;
6024 *ctxlen = len;
6025 return 0;
6026}
Michael LeMayd7200242006-06-22 14:47:17 -07006027#ifdef CONFIG_KEYS
6028
David Howellsd84f4f92008-11-14 10:39:23 +11006029static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07006030 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07006031{
David Howellsd84f4f92008-11-14 10:39:23 +11006032 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07006033 struct key_security_struct *ksec;
6034
6035 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
6036 if (!ksec)
6037 return -ENOMEM;
6038
David Howellsd84f4f92008-11-14 10:39:23 +11006039 tsec = cred->security;
6040 if (tsec->keycreate_sid)
6041 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07006042 else
David Howellsd84f4f92008-11-14 10:39:23 +11006043 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006044
David Howells275bb412008-11-14 10:39:19 +11006045 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07006046 return 0;
6047}
6048
6049static void selinux_key_free(struct key *k)
6050{
6051 struct key_security_struct *ksec = k->security;
6052
6053 k->security = NULL;
6054 kfree(ksec);
6055}
6056
6057static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11006058 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00006059 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07006060{
6061 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07006062 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11006063 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07006064
6065 /* if no specific permissions are requested, we skip the
6066 permission check. No serious, additional covert channels
6067 appear to be created. */
6068 if (perm == 0)
6069 return 0;
6070
David Howellsd84f4f92008-11-14 10:39:23 +11006071 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11006072
6073 key = key_ref_to_ptr(key_ref);
6074 ksec = key->security;
6075
6076 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07006077}
6078
David Howells70a5bb72008-04-29 01:01:26 -07006079static int selinux_key_getsecurity(struct key *key, char **_buffer)
6080{
6081 struct key_security_struct *ksec = key->security;
6082 char *context = NULL;
6083 unsigned len;
6084 int rc;
6085
6086 rc = security_sid_to_context(ksec->sid, &context, &len);
6087 if (!rc)
6088 rc = len;
6089 *_buffer = context;
6090 return rc;
6091}
6092
Michael LeMayd7200242006-06-22 14:47:17 -07006093#endif
6094
Chenbo Feng9b629132017-10-18 13:00:25 -07006095#ifdef CONFIG_BPF_SYSCALL
6096static int selinux_bpf(int cmd, union bpf_attr *attr,
6097 unsigned int size)
6098{
6099 u32 sid = current_sid();
6100 int ret;
6101
6102 switch (cmd) {
6103 case BPF_MAP_CREATE:
6104 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
6105 NULL);
6106 break;
6107 case BPF_PROG_LOAD:
6108 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
6109 NULL);
6110 break;
6111 default:
6112 ret = 0;
6113 break;
6114 }
6115
6116 return ret;
6117}
6118
6119static u32 bpf_map_fmode_to_av(fmode_t fmode)
6120{
6121 u32 av = 0;
6122
6123 if (fmode & FMODE_READ)
6124 av |= BPF__MAP_READ;
6125 if (fmode & FMODE_WRITE)
6126 av |= BPF__MAP_WRITE;
6127 return av;
6128}
6129
Chenbo Feng0521e0b2017-10-18 13:00:26 -07006130/* This function will check the file pass through unix socket or binder to see
6131 * if it is a bpf related object. And apply correspinding checks on the bpf
6132 * object based on the type. The bpf maps and programs, not like other files and
6133 * socket, are using a shared anonymous inode inside the kernel as their inode.
6134 * So checking that inode cannot identify if the process have privilege to
6135 * access the bpf object and that's why we have to add this additional check in
6136 * selinux_file_receive and selinux_binder_transfer_files.
6137 */
6138static int bpf_fd_pass(struct file *file, u32 sid)
6139{
6140 struct bpf_security_struct *bpfsec;
6141 struct bpf_prog *prog;
6142 struct bpf_map *map;
6143 int ret;
6144
6145 if (file->f_op == &bpf_map_fops) {
6146 map = file->private_data;
6147 bpfsec = map->security;
6148 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6149 bpf_map_fmode_to_av(file->f_mode), NULL);
6150 if (ret)
6151 return ret;
6152 } else if (file->f_op == &bpf_prog_fops) {
6153 prog = file->private_data;
6154 bpfsec = prog->aux->security;
6155 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6156 BPF__PROG_RUN, NULL);
6157 if (ret)
6158 return ret;
6159 }
6160 return 0;
6161}
6162
Chenbo Feng9b629132017-10-18 13:00:25 -07006163static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6164{
6165 u32 sid = current_sid();
6166 struct bpf_security_struct *bpfsec;
6167
6168 bpfsec = map->security;
6169 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6170 bpf_map_fmode_to_av(fmode), NULL);
6171}
6172
6173static int selinux_bpf_prog(struct bpf_prog *prog)
6174{
6175 u32 sid = current_sid();
6176 struct bpf_security_struct *bpfsec;
6177
6178 bpfsec = prog->aux->security;
6179 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6180 BPF__PROG_RUN, NULL);
6181}
6182
6183static int selinux_bpf_map_alloc(struct bpf_map *map)
6184{
6185 struct bpf_security_struct *bpfsec;
6186
6187 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6188 if (!bpfsec)
6189 return -ENOMEM;
6190
6191 bpfsec->sid = current_sid();
6192 map->security = bpfsec;
6193
6194 return 0;
6195}
6196
6197static void selinux_bpf_map_free(struct bpf_map *map)
6198{
6199 struct bpf_security_struct *bpfsec = map->security;
6200
6201 map->security = NULL;
6202 kfree(bpfsec);
6203}
6204
6205static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6206{
6207 struct bpf_security_struct *bpfsec;
6208
6209 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6210 if (!bpfsec)
6211 return -ENOMEM;
6212
6213 bpfsec->sid = current_sid();
6214 aux->security = bpfsec;
6215
6216 return 0;
6217}
6218
6219static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6220{
6221 struct bpf_security_struct *bpfsec = aux->security;
6222
6223 aux->security = NULL;
6224 kfree(bpfsec);
6225}
6226#endif
6227
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006228static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07006229 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6230 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
6231 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
6232 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006233
Casey Schauflere20b0432015-05-02 15:11:36 -07006234 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
6235 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
6236 LSM_HOOK_INIT(capget, selinux_capget),
6237 LSM_HOOK_INIT(capset, selinux_capset),
6238 LSM_HOOK_INIT(capable, selinux_capable),
6239 LSM_HOOK_INIT(quotactl, selinux_quotactl),
6240 LSM_HOOK_INIT(quota_on, selinux_quota_on),
6241 LSM_HOOK_INIT(syslog, selinux_syslog),
6242 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05006243
Casey Schauflere20b0432015-05-02 15:11:36 -07006244 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245
Casey Schauflere20b0432015-05-02 15:11:36 -07006246 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
6247 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
6248 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
6249 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Casey Schauflere20b0432015-05-02 15:11:36 -07006251 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6252 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
6253 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
6254 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6255 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6256 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
6257 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
6258 LSM_HOOK_INIT(sb_mount, selinux_mount),
6259 LSM_HOOK_INIT(sb_umount, selinux_umount),
6260 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
6261 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
6262 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263
Casey Schauflere20b0432015-05-02 15:11:36 -07006264 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Vivek Goyala518b0a2016-07-13 10:44:53 -04006265 LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
Eric Parise0007522008-03-05 10:31:54 -05006266
Casey Schauflere20b0432015-05-02 15:11:36 -07006267 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
6268 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
6269 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
6270 LSM_HOOK_INIT(inode_create, selinux_inode_create),
6271 LSM_HOOK_INIT(inode_link, selinux_inode_link),
6272 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
6273 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
6274 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
6275 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
6276 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
6277 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
6278 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
6279 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
6280 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
6281 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
6282 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
6283 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
6284 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
6285 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
6286 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
6287 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
6288 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
6289 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
6290 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
6291 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Vivek Goyal56909eb2016-07-13 10:44:48 -04006292 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
Vivek Goyal19472b62016-07-13 10:44:50 -04006293 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294
Casey Schauflere20b0432015-05-02 15:11:36 -07006295 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6296 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6297 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
6298 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
6299 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
6300 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
6301 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
6302 LSM_HOOK_INIT(file_lock, selinux_file_lock),
6303 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
6304 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
6305 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
6306 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Casey Schauflere20b0432015-05-02 15:11:36 -07006308 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309
Casey Schauflere20b0432015-05-02 15:11:36 -07006310 LSM_HOOK_INIT(task_create, selinux_task_create),
6311 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6312 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6313 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
6314 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
6315 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
6316 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
6317 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
Jeff Vander Stoep61d612e2016-04-05 13:06:27 -07006318 LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
Casey Schauflere20b0432015-05-02 15:11:36 -07006319 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
6320 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
6321 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
6322 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
6323 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
6324 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
6325 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
6326 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
6327 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
6328 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
6329 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
6330 LSM_HOOK_INIT(task_kill, selinux_task_kill),
6331 LSM_HOOK_INIT(task_wait, selinux_task_wait),
6332 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09006333
Casey Schauflere20b0432015-05-02 15:11:36 -07006334 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
6335 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336
Casey Schauflere20b0432015-05-02 15:11:36 -07006337 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
6338 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006339
Casey Schauflere20b0432015-05-02 15:11:36 -07006340 LSM_HOOK_INIT(msg_queue_alloc_security,
6341 selinux_msg_queue_alloc_security),
6342 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
6343 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
6344 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
6345 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
6346 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347
Casey Schauflere20b0432015-05-02 15:11:36 -07006348 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
6349 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
6350 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6351 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6352 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006353
Casey Schauflere20b0432015-05-02 15:11:36 -07006354 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6355 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6356 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6357 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6358 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359
Casey Schauflere20b0432015-05-02 15:11:36 -07006360 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361
Casey Schauflere20b0432015-05-02 15:11:36 -07006362 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6363 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364
Casey Schauflere20b0432015-05-02 15:11:36 -07006365 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6366 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6367 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6368 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006369 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006370 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6371 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6372 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373
Casey Schauflere20b0432015-05-02 15:11:36 -07006374 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6375 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006376
Casey Schauflere20b0432015-05-02 15:11:36 -07006377 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6378 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6379 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6380 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6381 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6382 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6383 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6384 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6385 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6386 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6387 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6388 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6389 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6390 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6391 LSM_HOOK_INIT(socket_getpeersec_stream,
6392 selinux_socket_getpeersec_stream),
6393 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6394 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6395 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6396 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6397 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6398 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6399 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6400 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6401 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6402 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6403 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6404 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6405 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6406 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6407 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6408 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6409 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6410 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6411 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006412
6413#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006414 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6415 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6416 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6417 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6418 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6419 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6420 selinux_xfrm_state_alloc_acquire),
6421 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6422 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6423 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6424 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6425 selinux_xfrm_state_pol_flow_match),
6426 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006427#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006428
6429#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006430 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6431 LSM_HOOK_INIT(key_free, selinux_key_free),
6432 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6433 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006434#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006435
6436#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006437 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6438 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6439 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6440 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006441#endif
Chenbo Feng9b629132017-10-18 13:00:25 -07006442
6443#ifdef CONFIG_BPF_SYSCALL
6444 LSM_HOOK_INIT(bpf, selinux_bpf),
6445 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
6446 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
6447 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
6448 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
6449 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
6450 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
6451#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452};
6453
6454static __init int selinux_init(void)
6455{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006456 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006457 selinux_enabled = 0;
6458 return 0;
6459 }
6460
Linus Torvalds1da177e2005-04-16 15:20:36 -07006461 if (!selinux_enabled) {
6462 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6463 return 0;
6464 }
6465
6466 printk(KERN_INFO "SELinux: Initializing.\n");
6467
6468 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006469 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006470
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006471 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6472
James Morris7cae7e22006-03-22 00:09:22 -08006473 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6474 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006475 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006476 file_security_cache = kmem_cache_create("selinux_file_security",
6477 sizeof(struct file_security_struct),
6478 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479 avc_init();
6480
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006481 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482
Paul Moore615e51f2014-06-26 14:33:56 -04006483 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6484 panic("SELinux: Unable to register AVC netcache callback\n");
6485
Eric Paris828dfe12008-04-17 13:17:49 -04006486 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006487 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006488 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006489 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006490
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491 return 0;
6492}
6493
Al Viroe8c26252010-03-23 06:36:54 -04006494static void delayed_superblock_init(struct super_block *sb, void *unused)
6495{
6496 superblock_doinit(sb, NULL);
6497}
6498
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499void selinux_complete_init(void)
6500{
Eric Parisfadcdb42007-02-22 18:11:31 -05006501 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006502
6503 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006504 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006505 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006506}
6507
6508/* SELinux requires early initialization in order to label
6509 all processes and objects when they are created. */
6510security_initcall(selinux_init);
6511
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006512#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513
Jiri Pirko25db6be2014-09-03 17:42:13 +02006514static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006515 {
6516 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006517 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006518 .hooknum = NF_INET_POST_ROUTING,
6519 .priority = NF_IP_PRI_SELINUX_LAST,
6520 },
6521 {
6522 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006523 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006524 .hooknum = NF_INET_FORWARD,
6525 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006526 },
6527 {
6528 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006529 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006530 .hooknum = NF_INET_LOCAL_OUT,
6531 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006532 },
Javier Martinez Canillas1a93a6e2016-08-08 13:08:25 -04006533#if IS_ENABLED(CONFIG_IPV6)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006534 {
6535 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006536 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006537 .hooknum = NF_INET_POST_ROUTING,
6538 .priority = NF_IP6_PRI_SELINUX_LAST,
6539 },
6540 {
6541 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006542 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006543 .hooknum = NF_INET_FORWARD,
6544 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006545 },
Huw Davies2917f572016-06-27 15:06:15 -04006546 {
6547 .hook = selinux_ipv6_output,
6548 .pf = NFPROTO_IPV6,
6549 .hooknum = NF_INET_LOCAL_OUT,
6550 .priority = NF_IP6_PRI_SELINUX_FIRST,
6551 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006552#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006553};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554
6555static int __init selinux_nf_ip_init(void)
6556{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006557 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006558
6559 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006560 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006561
6562 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6563
Jiri Pirko25db6be2014-09-03 17:42:13 +02006564 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006565 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006566 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006567
Jiri Pirko25db6be2014-09-03 17:42:13 +02006568 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569}
6570
6571__initcall(selinux_nf_ip_init);
6572
6573#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6574static void selinux_nf_ip_exit(void)
6575{
Eric Parisfadcdb42007-02-22 18:11:31 -05006576 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577
Jiri Pirko25db6be2014-09-03 17:42:13 +02006578 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006579}
6580#endif
6581
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006582#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006583
6584#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6585#define selinux_nf_ip_exit()
6586#endif
6587
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006588#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589
6590#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006591static int selinux_disabled;
6592
Linus Torvalds1da177e2005-04-16 15:20:36 -07006593int selinux_disable(void)
6594{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006595 if (ss_initialized) {
6596 /* Not permitted after initial policy load. */
6597 return -EINVAL;
6598 }
6599
6600 if (selinux_disabled) {
6601 /* Only do this once. */
6602 return -EINVAL;
6603 }
6604
6605 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6606
6607 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006608 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006609
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006610 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006611
Eric Parisaf8ff042009-09-20 21:23:01 -04006612 /* Try to destroy the avc node cache */
6613 avc_disable();
6614
Linus Torvalds1da177e2005-04-16 15:20:36 -07006615 /* Unregister netfilter hooks. */
6616 selinux_nf_ip_exit();
6617
6618 /* Unregister selinuxfs. */
6619 exit_sel_fs();
6620
6621 return 0;
6622}
6623#endif