blob: 8abbd548ece9267172361922f8275be0ee8f814a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800129
Paul Moored621d352008-01-29 08:43:36 -0500130/**
131 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
132 *
133 * Description:
134 * This function checks the SECMARK reference counter to see if any SECMARK
135 * targets are currently configured, if the reference counter is greater than
136 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400137 * enabled, false (0) if SECMARK is disabled. If the always_check_network
138 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500139 *
140 */
141static int selinux_secmark_enabled(void)
142{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400143 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
144}
145
146/**
147 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
148 *
149 * Description:
150 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
151 * (1) if any are enabled or false (0) if neither are enabled. If the
152 * always_check_network policy capability is enabled, peer labeling
153 * is always considered enabled.
154 *
155 */
156static int selinux_peerlbl_enabled(void)
157{
158 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500159}
160
Paul Moore615e51f2014-06-26 14:33:56 -0400161static int selinux_netcache_avc_callback(u32 event)
162{
163 if (event == AVC_CALLBACK_RESET) {
164 sel_netif_flush();
165 sel_netnode_flush();
166 sel_netport_flush();
167 synchronize_net();
168 }
169 return 0;
170}
171
David Howellsd84f4f92008-11-14 10:39:23 +1100172/*
173 * initialise the security for the init task
174 */
175static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
David Howells3b11a1d2008-11-14 10:39:26 +1100177 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 struct task_security_struct *tsec;
179
James Morris89d155e2005-10-30 14:59:21 -0800180 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100182 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
David Howellsd84f4f92008-11-14 10:39:23 +1100184 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100185 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
David Howells275bb412008-11-14 10:39:19 +1100188/*
David Howells88e67f32008-11-14 10:39:21 +1100189 * get the security ID of a set of credentials
190 */
191static inline u32 cred_sid(const struct cred *cred)
192{
193 const struct task_security_struct *tsec;
194
195 tsec = cred->security;
196 return tsec->sid;
197}
198
199/*
David Howells3b11a1d2008-11-14 10:39:26 +1100200 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100201 */
202static inline u32 task_sid(const struct task_struct *task)
203{
David Howells275bb412008-11-14 10:39:19 +1100204 u32 sid;
205
206 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100207 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100208 rcu_read_unlock();
209 return sid;
210}
211
212/*
David Howells3b11a1d2008-11-14 10:39:26 +1100213 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100214 */
215static inline u32 current_sid(void)
216{
Paul Moore5fb49872010-04-22 14:46:19 -0400217 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100218
219 return tsec->sid;
220}
221
David Howells88e67f32008-11-14 10:39:21 +1100222/* Allocate and free functions for each kind of security blob. */
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static int inode_alloc_security(struct inode *inode)
225{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100227 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Josef Bacika02fe132008-04-04 09:35:05 +1100229 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 if (!isec)
231 return -ENOMEM;
232
Eric Paris23970742006-09-25 23:32:01 -0700233 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 isec->inode = inode;
236 isec->sid = SECINITSID_UNLABELED;
237 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100238 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 inode->i_security = isec;
240
241 return 0;
242}
243
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500244static void inode_free_rcu(struct rcu_head *head)
245{
246 struct inode_security_struct *isec;
247
248 isec = container_of(head, struct inode_security_struct, rcu);
249 kmem_cache_free(sel_inode_cache, isec);
250}
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252static void inode_free_security(struct inode *inode)
253{
254 struct inode_security_struct *isec = inode->i_security;
255 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 spin_lock(&sbsec->isec_lock);
258 if (!list_empty(&isec->list))
259 list_del_init(&isec->list);
260 spin_unlock(&sbsec->isec_lock);
261
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500262 /*
263 * The inode may still be referenced in a path walk and
264 * a call to selinux_inode_permission() can be made
265 * after inode_free_security() is called. Ideally, the VFS
266 * wouldn't do this, but fixing that is a much harder
267 * job. For now, simply free the i_security via RCU, and
268 * leave the current inode->i_security pointer intact.
269 * The inode will be freed after the RCU grace period too.
270 */
271 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272}
273
274static int file_alloc_security(struct file *file)
275{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100277 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800279 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!fsec)
281 return -ENOMEM;
282
David Howells275bb412008-11-14 10:39:19 +1100283 fsec->sid = sid;
284 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 file->f_security = fsec;
286
287 return 0;
288}
289
290static void file_free_security(struct file *file)
291{
292 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 file->f_security = NULL;
294 kfree(fsec);
295}
296
297static int superblock_alloc_security(struct super_block *sb)
298{
299 struct superblock_security_struct *sbsec;
300
James Morris89d155e2005-10-30 14:59:21 -0800301 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 if (!sbsec)
303 return -ENOMEM;
304
Eric Parisbc7e9822006-09-25 23:32:02 -0700305 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 INIT_LIST_HEAD(&sbsec->isec_head);
307 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sbsec->sb = sb;
309 sbsec->sid = SECINITSID_UNLABELED;
310 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700311 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 sb->s_security = sbsec;
313
314 return 0;
315}
316
317static void superblock_free_security(struct super_block *sb)
318{
319 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 sb->s_security = NULL;
321 kfree(sbsec);
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324/* The file system's label must be initialized prior to use. */
325
David Quigleyeb9ae682013-05-22 12:50:37 -0400326static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 "uses xattr",
328 "uses transition SIDs",
329 "uses task SIDs",
330 "uses genfs_contexts",
331 "not configured for labeling",
332 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400333 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334};
335
336static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
337
338static inline int inode_doinit(struct inode *inode)
339{
340 return inode_doinit_with_dentry(inode, NULL);
341}
342
343enum {
Eric Paris31e87932007-09-19 17:19:12 -0400344 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 Opt_context = 1,
346 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500347 Opt_defcontext = 3,
348 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500349 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400350 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351};
352
Eric Parisd355987f2012-08-24 15:58:53 -0400353#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
354
Steven Whitehousea447c092008-10-13 10:46:57 +0100355static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400356 {Opt_context, CONTEXT_STR "%s"},
357 {Opt_fscontext, FSCONTEXT_STR "%s"},
358 {Opt_defcontext, DEFCONTEXT_STR "%s"},
359 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500360 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400361 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362};
363
364#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
365
Eric Parisc312feb2006-07-10 04:43:53 -0700366static int may_context_mount_sb_relabel(u32 sid,
367 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100368 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700369{
David Howells275bb412008-11-14 10:39:19 +1100370 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700371 int rc;
372
373 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
374 FILESYSTEM__RELABELFROM, NULL);
375 if (rc)
376 return rc;
377
378 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
379 FILESYSTEM__RELABELTO, NULL);
380 return rc;
381}
382
Eric Paris08089252006-07-10 04:43:55 -0700383static int may_context_mount_inode_relabel(u32 sid,
384 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100385 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700386{
David Howells275bb412008-11-14 10:39:19 +1100387 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700388 int rc;
389 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
390 FILESYSTEM__RELABELFROM, NULL);
391 if (rc)
392 return rc;
393
394 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
395 FILESYSTEM__ASSOCIATE, NULL);
396 return rc;
397}
398
Eric Parisb43e7252012-10-10 14:27:35 -0400399static int selinux_is_sblabel_mnt(struct super_block *sb)
400{
401 struct superblock_security_struct *sbsec = sb->s_security;
402
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500403 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
404 sbsec->behavior == SECURITY_FS_USE_TRANS ||
405 sbsec->behavior == SECURITY_FS_USE_TASK ||
406 /* Special handling. Genfs but also in-core setxattr handler */
407 !strcmp(sb->s_type->name, "sysfs") ||
408 !strcmp(sb->s_type->name, "pstore") ||
409 !strcmp(sb->s_type->name, "debugfs") ||
410 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400411}
412
Eric Parisc9180a52007-11-30 13:00:35 -0500413static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
415 struct superblock_security_struct *sbsec = sb->s_security;
416 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000417 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 int rc = 0;
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
421 /* Make sure that the xattr handler exists and that no
422 error other than -ENODATA is returned by getxattr on
423 the root directory. -ENODATA is ok, as this may be
424 the first boot of the SELinux kernel before we have
425 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500426 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800427 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
428 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 rc = -EOPNOTSUPP;
430 goto out;
431 }
Eric Parisc9180a52007-11-30 13:00:35 -0500432 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 if (rc < 0 && rc != -ENODATA) {
434 if (rc == -EOPNOTSUPP)
435 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800436 "%s) has no security xattr handler\n",
437 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 else
439 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800440 "%s) getxattr errno %d\n", sb->s_id,
441 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 goto out;
443 }
444 }
445
Eric Parisc9180a52007-11-30 13:00:35 -0500446 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800447 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
448 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Eric Pariseadcabc2012-08-24 15:59:14 -0400450 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400451 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400452 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500455 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457 /* Initialize any other inodes associated with the superblock, e.g.
458 inodes created prior to initial policy load or inodes created
459 during get_sb by a pseudo filesystem that directly
460 populates itself. */
461 spin_lock(&sbsec->isec_lock);
462next_inode:
463 if (!list_empty(&sbsec->isec_head)) {
464 struct inode_security_struct *isec =
465 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500466 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400468 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 spin_unlock(&sbsec->isec_lock);
470 inode = igrab(inode);
471 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500472 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 inode_doinit(inode);
474 iput(inode);
475 }
476 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 goto next_inode;
478 }
479 spin_unlock(&sbsec->isec_lock);
480out:
Eric Parisc9180a52007-11-30 13:00:35 -0500481 return rc;
482}
483
484/*
485 * This function should allow an FS to ask what it's mount security
486 * options were so it can use those later for submounts, displaying
487 * mount options, or whatever.
488 */
489static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500490 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500491{
492 int rc = 0, i;
493 struct superblock_security_struct *sbsec = sb->s_security;
494 char *context = NULL;
495 u32 len;
496 char tmp;
497
Eric Parise0007522008-03-05 10:31:54 -0500498 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500499
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500500 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500501 return -EINVAL;
502
503 if (!ss_initialized)
504 return -EINVAL;
505
Eric Parisaf8e50c2012-08-24 15:59:00 -0400506 /* make sure we always check enough bits to cover the mask */
507 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
508
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500509 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500510 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400511 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500512 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500513 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500514 tmp >>= 1;
515 }
David P. Quigley11689d42009-01-16 09:22:03 -0500516 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400517 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500518 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500519
Eric Parise0007522008-03-05 10:31:54 -0500520 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
521 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500522 rc = -ENOMEM;
523 goto out_free;
524 }
525
Eric Parise0007522008-03-05 10:31:54 -0500526 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
527 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500528 rc = -ENOMEM;
529 goto out_free;
530 }
531
532 i = 0;
533 if (sbsec->flags & FSCONTEXT_MNT) {
534 rc = security_sid_to_context(sbsec->sid, &context, &len);
535 if (rc)
536 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500537 opts->mnt_opts[i] = context;
538 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500539 }
540 if (sbsec->flags & CONTEXT_MNT) {
541 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
542 if (rc)
543 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500544 opts->mnt_opts[i] = context;
545 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500546 }
547 if (sbsec->flags & DEFCONTEXT_MNT) {
548 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
549 if (rc)
550 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500551 opts->mnt_opts[i] = context;
552 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500553 }
554 if (sbsec->flags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000555 struct inode *root = d_backing_inode(sbsec->sb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500556 struct inode_security_struct *isec = root->i_security;
557
558 rc = security_sid_to_context(isec->sid, &context, &len);
559 if (rc)
560 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500561 opts->mnt_opts[i] = context;
562 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500563 }
Eric Paris12f348b2012-10-09 10:56:25 -0400564 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500565 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400566 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500567 }
Eric Parisc9180a52007-11-30 13:00:35 -0500568
Eric Parise0007522008-03-05 10:31:54 -0500569 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500570
571 return 0;
572
573out_free:
Eric Parise0007522008-03-05 10:31:54 -0500574 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500575 return rc;
576}
577
578static int bad_option(struct superblock_security_struct *sbsec, char flag,
579 u32 old_sid, u32 new_sid)
580{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500581 char mnt_flags = sbsec->flags & SE_MNTMASK;
582
Eric Parisc9180a52007-11-30 13:00:35 -0500583 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500584 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500585 if (!(sbsec->flags & flag) ||
586 (old_sid != new_sid))
587 return 1;
588
589 /* check if we were passed the same options twice,
590 * aka someone passed context=a,context=b
591 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500592 if (!(sbsec->flags & SE_SBINITIALIZED))
593 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500594 return 1;
595 return 0;
596}
Eric Parise0007522008-03-05 10:31:54 -0500597
Eric Parisc9180a52007-11-30 13:00:35 -0500598/*
599 * Allow filesystems with binary mount data to explicitly set mount point
600 * labeling information.
601 */
Eric Parise0007522008-03-05 10:31:54 -0500602static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400603 struct security_mnt_opts *opts,
604 unsigned long kern_flags,
605 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500606{
David Howells275bb412008-11-14 10:39:19 +1100607 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500608 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500609 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800610 const char *name = sb->s_type->name;
David Howellsc6f493d2015-03-17 22:26:22 +0000611 struct inode *inode = d_backing_inode(sbsec->sb->s_root);
James Morris089be432008-07-15 18:32:49 +1000612 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500613 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
614 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500615 char **mount_options = opts->mnt_opts;
616 int *flags = opts->mnt_opts_flags;
617 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500618
619 mutex_lock(&sbsec->lock);
620
621 if (!ss_initialized) {
622 if (!num_opts) {
623 /* Defer initialization until selinux_complete_init,
624 after the initial policy is loaded and the security
625 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500626 goto out;
627 }
628 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400629 printk(KERN_WARNING "SELinux: Unable to set superblock options "
630 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500631 goto out;
632 }
David Quigley649f6e72013-05-22 12:50:36 -0400633 if (kern_flags && !set_kern_flags) {
634 /* Specifying internal flags without providing a place to
635 * place the results is not allowed */
636 rc = -EINVAL;
637 goto out;
638 }
Eric Parisc9180a52007-11-30 13:00:35 -0500639
640 /*
Eric Parise0007522008-03-05 10:31:54 -0500641 * Binary mount data FS will come through this function twice. Once
642 * from an explicit call and once from the generic calls from the vfs.
643 * Since the generic VFS calls will not contain any security mount data
644 * we need to skip the double mount verification.
645 *
646 * This does open a hole in which we will not notice if the first
647 * mount using this sb set explict options and a second mount using
648 * this sb does not set any security options. (The first options
649 * will be used for both mounts)
650 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500651 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500652 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400653 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500654
655 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500656 * parse the mount options, check if they are valid sids.
657 * also check if someone is trying to mount the same sb more
658 * than once with different security options.
659 */
660 for (i = 0; i < num_opts; i++) {
661 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500662
Eric Paris12f348b2012-10-09 10:56:25 -0400663 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500664 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500665 rc = security_context_to_sid(mount_options[i],
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +0100666 strlen(mount_options[i]), &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500667 if (rc) {
668 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800669 "(%s) failed for (dev %s, type %s) errno=%d\n",
670 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500671 goto out;
672 }
673 switch (flags[i]) {
674 case FSCONTEXT_MNT:
675 fscontext_sid = sid;
676
677 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
678 fscontext_sid))
679 goto out_double_mount;
680
681 sbsec->flags |= FSCONTEXT_MNT;
682 break;
683 case CONTEXT_MNT:
684 context_sid = sid;
685
686 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
687 context_sid))
688 goto out_double_mount;
689
690 sbsec->flags |= CONTEXT_MNT;
691 break;
692 case ROOTCONTEXT_MNT:
693 rootcontext_sid = sid;
694
695 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
696 rootcontext_sid))
697 goto out_double_mount;
698
699 sbsec->flags |= ROOTCONTEXT_MNT;
700
701 break;
702 case DEFCONTEXT_MNT:
703 defcontext_sid = sid;
704
705 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
706 defcontext_sid))
707 goto out_double_mount;
708
709 sbsec->flags |= DEFCONTEXT_MNT;
710
711 break;
712 default:
713 rc = -EINVAL;
714 goto out;
715 }
716 }
717
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500718 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500719 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500720 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500721 goto out_double_mount;
722 rc = 0;
723 goto out;
724 }
725
James Morris089be432008-07-15 18:32:49 +1000726 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500727 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500728
David Quigleyeb9ae682013-05-22 12:50:37 -0400729 if (!sbsec->behavior) {
730 /*
731 * Determine the labeling behavior to use for this
732 * filesystem type.
733 */
Paul Moore98f700f2013-09-18 13:52:20 -0400734 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400735 if (rc) {
736 printk(KERN_WARNING
737 "%s: security_fs_use(%s) returned %d\n",
738 __func__, sb->s_type->name, rc);
739 goto out;
740 }
Eric Parisc9180a52007-11-30 13:00:35 -0500741 }
Eric Parisc9180a52007-11-30 13:00:35 -0500742 /* sets the context of the superblock for the fs being mounted. */
743 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100744 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500745 if (rc)
746 goto out;
747
748 sbsec->sid = fscontext_sid;
749 }
750
751 /*
752 * Switch to using mount point labeling behavior.
753 * sets the label used on all file below the mountpoint, and will set
754 * the superblock context if not already set.
755 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400756 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
757 sbsec->behavior = SECURITY_FS_USE_NATIVE;
758 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
759 }
760
Eric Parisc9180a52007-11-30 13:00:35 -0500761 if (context_sid) {
762 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100763 rc = may_context_mount_sb_relabel(context_sid, sbsec,
764 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500765 if (rc)
766 goto out;
767 sbsec->sid = context_sid;
768 } else {
David Howells275bb412008-11-14 10:39:19 +1100769 rc = may_context_mount_inode_relabel(context_sid, sbsec,
770 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500771 if (rc)
772 goto out;
773 }
774 if (!rootcontext_sid)
775 rootcontext_sid = context_sid;
776
777 sbsec->mntpoint_sid = context_sid;
778 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
779 }
780
781 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100782 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
783 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500784 if (rc)
785 goto out;
786
787 root_isec->sid = rootcontext_sid;
788 root_isec->initialized = 1;
789 }
790
791 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400792 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
793 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500794 rc = -EINVAL;
795 printk(KERN_WARNING "SELinux: defcontext option is "
796 "invalid for this filesystem type\n");
797 goto out;
798 }
799
800 if (defcontext_sid != sbsec->def_sid) {
801 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100802 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500803 if (rc)
804 goto out;
805 }
806
807 sbsec->def_sid = defcontext_sid;
808 }
809
810 rc = sb_finish_set_opts(sb);
811out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700812 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500814out_double_mount:
815 rc = -EINVAL;
816 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800817 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500818 goto out;
819}
820
Jeff Layton094f7b62013-04-01 08:14:24 -0400821static int selinux_cmp_sb_context(const struct super_block *oldsb,
822 const struct super_block *newsb)
823{
824 struct superblock_security_struct *old = oldsb->s_security;
825 struct superblock_security_struct *new = newsb->s_security;
826 char oldflags = old->flags & SE_MNTMASK;
827 char newflags = new->flags & SE_MNTMASK;
828
829 if (oldflags != newflags)
830 goto mismatch;
831 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
832 goto mismatch;
833 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
834 goto mismatch;
835 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
836 goto mismatch;
837 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000838 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
839 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400840 if (oldroot->sid != newroot->sid)
841 goto mismatch;
842 }
843 return 0;
844mismatch:
845 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
846 "different security settings for (dev %s, "
847 "type %s)\n", newsb->s_id, newsb->s_type->name);
848 return -EBUSY;
849}
850
851static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500852 struct super_block *newsb)
853{
854 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
855 struct superblock_security_struct *newsbsec = newsb->s_security;
856
857 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
858 int set_context = (oldsbsec->flags & CONTEXT_MNT);
859 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
860
Eric Paris0f5e6422008-04-21 16:24:11 -0400861 /*
862 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400863 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400864 */
Al Viroe8c26252010-03-23 06:36:54 -0400865 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400866 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500867
Eric Parisc9180a52007-11-30 13:00:35 -0500868 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500869 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500870
Jeff Layton094f7b62013-04-01 08:14:24 -0400871 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500872 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400873 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400874
Eric Parisc9180a52007-11-30 13:00:35 -0500875 mutex_lock(&newsbsec->lock);
876
877 newsbsec->flags = oldsbsec->flags;
878
879 newsbsec->sid = oldsbsec->sid;
880 newsbsec->def_sid = oldsbsec->def_sid;
881 newsbsec->behavior = oldsbsec->behavior;
882
883 if (set_context) {
884 u32 sid = oldsbsec->mntpoint_sid;
885
886 if (!set_fscontext)
887 newsbsec->sid = sid;
888 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000889 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500890 struct inode_security_struct *newisec = newinode->i_security;
891 newisec->sid = sid;
892 }
893 newsbsec->mntpoint_sid = sid;
894 }
895 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000896 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500897 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000898 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500899 struct inode_security_struct *newisec = newinode->i_security;
900
901 newisec->sid = oldisec->sid;
902 }
903
904 sb_finish_set_opts(newsb);
905 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400906 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500907}
908
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200909static int selinux_parse_opts_str(char *options,
910 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500911{
Eric Parise0007522008-03-05 10:31:54 -0500912 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500913 char *context = NULL, *defcontext = NULL;
914 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500915 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500916
Eric Parise0007522008-03-05 10:31:54 -0500917 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500918
919 /* Standard string-based options. */
920 while ((p = strsep(&options, "|")) != NULL) {
921 int token;
922 substring_t args[MAX_OPT_ARGS];
923
924 if (!*p)
925 continue;
926
927 token = match_token(p, tokens, args);
928
929 switch (token) {
930 case Opt_context:
931 if (context || defcontext) {
932 rc = -EINVAL;
933 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
934 goto out_err;
935 }
936 context = match_strdup(&args[0]);
937 if (!context) {
938 rc = -ENOMEM;
939 goto out_err;
940 }
941 break;
942
943 case Opt_fscontext:
944 if (fscontext) {
945 rc = -EINVAL;
946 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
947 goto out_err;
948 }
949 fscontext = match_strdup(&args[0]);
950 if (!fscontext) {
951 rc = -ENOMEM;
952 goto out_err;
953 }
954 break;
955
956 case Opt_rootcontext:
957 if (rootcontext) {
958 rc = -EINVAL;
959 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
960 goto out_err;
961 }
962 rootcontext = match_strdup(&args[0]);
963 if (!rootcontext) {
964 rc = -ENOMEM;
965 goto out_err;
966 }
967 break;
968
969 case Opt_defcontext:
970 if (context || defcontext) {
971 rc = -EINVAL;
972 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
973 goto out_err;
974 }
975 defcontext = match_strdup(&args[0]);
976 if (!defcontext) {
977 rc = -ENOMEM;
978 goto out_err;
979 }
980 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500981 case Opt_labelsupport:
982 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500983 default:
984 rc = -EINVAL;
985 printk(KERN_WARNING "SELinux: unknown mount option\n");
986 goto out_err;
987
988 }
989 }
990
Eric Parise0007522008-03-05 10:31:54 -0500991 rc = -ENOMEM;
992 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
993 if (!opts->mnt_opts)
994 goto out_err;
995
996 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
997 if (!opts->mnt_opts_flags) {
998 kfree(opts->mnt_opts);
999 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001000 }
1001
Eric Parise0007522008-03-05 10:31:54 -05001002 if (fscontext) {
1003 opts->mnt_opts[num_mnt_opts] = fscontext;
1004 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1005 }
1006 if (context) {
1007 opts->mnt_opts[num_mnt_opts] = context;
1008 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1009 }
1010 if (rootcontext) {
1011 opts->mnt_opts[num_mnt_opts] = rootcontext;
1012 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1013 }
1014 if (defcontext) {
1015 opts->mnt_opts[num_mnt_opts] = defcontext;
1016 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1017 }
1018
1019 opts->num_mnt_opts = num_mnt_opts;
1020 return 0;
1021
Eric Parisc9180a52007-11-30 13:00:35 -05001022out_err:
1023 kfree(context);
1024 kfree(defcontext);
1025 kfree(fscontext);
1026 kfree(rootcontext);
1027 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028}
Eric Parise0007522008-03-05 10:31:54 -05001029/*
1030 * string mount options parsing and call set the sbsec
1031 */
1032static int superblock_doinit(struct super_block *sb, void *data)
1033{
1034 int rc = 0;
1035 char *options = data;
1036 struct security_mnt_opts opts;
1037
1038 security_init_mnt_opts(&opts);
1039
1040 if (!data)
1041 goto out;
1042
1043 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1044
1045 rc = selinux_parse_opts_str(options, &opts);
1046 if (rc)
1047 goto out_err;
1048
1049out:
David Quigley649f6e72013-05-22 12:50:36 -04001050 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001051
1052out_err:
1053 security_free_mnt_opts(&opts);
1054 return rc;
1055}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Adrian Bunk3583a712008-07-22 20:21:23 +03001057static void selinux_write_opts(struct seq_file *m,
1058 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001059{
1060 int i;
1061 char *prefix;
1062
1063 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001064 char *has_comma;
1065
1066 if (opts->mnt_opts[i])
1067 has_comma = strchr(opts->mnt_opts[i], ',');
1068 else
1069 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001070
1071 switch (opts->mnt_opts_flags[i]) {
1072 case CONTEXT_MNT:
1073 prefix = CONTEXT_STR;
1074 break;
1075 case FSCONTEXT_MNT:
1076 prefix = FSCONTEXT_STR;
1077 break;
1078 case ROOTCONTEXT_MNT:
1079 prefix = ROOTCONTEXT_STR;
1080 break;
1081 case DEFCONTEXT_MNT:
1082 prefix = DEFCONTEXT_STR;
1083 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001084 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001085 seq_putc(m, ',');
1086 seq_puts(m, LABELSUPP_STR);
1087 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001088 default:
1089 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001090 return;
Eric Paris2069f452008-07-04 09:47:13 +10001091 };
1092 /* we need a comma before each option */
1093 seq_putc(m, ',');
1094 seq_puts(m, prefix);
1095 if (has_comma)
1096 seq_putc(m, '\"');
1097 seq_puts(m, opts->mnt_opts[i]);
1098 if (has_comma)
1099 seq_putc(m, '\"');
1100 }
1101}
1102
1103static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1104{
1105 struct security_mnt_opts opts;
1106 int rc;
1107
1108 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001109 if (rc) {
1110 /* before policy load we may get EINVAL, don't show anything */
1111 if (rc == -EINVAL)
1112 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001113 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001114 }
Eric Paris2069f452008-07-04 09:47:13 +10001115
1116 selinux_write_opts(m, &opts);
1117
1118 security_free_mnt_opts(&opts);
1119
1120 return rc;
1121}
1122
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123static inline u16 inode_mode_to_security_class(umode_t mode)
1124{
1125 switch (mode & S_IFMT) {
1126 case S_IFSOCK:
1127 return SECCLASS_SOCK_FILE;
1128 case S_IFLNK:
1129 return SECCLASS_LNK_FILE;
1130 case S_IFREG:
1131 return SECCLASS_FILE;
1132 case S_IFBLK:
1133 return SECCLASS_BLK_FILE;
1134 case S_IFDIR:
1135 return SECCLASS_DIR;
1136 case S_IFCHR:
1137 return SECCLASS_CHR_FILE;
1138 case S_IFIFO:
1139 return SECCLASS_FIFO_FILE;
1140
1141 }
1142
1143 return SECCLASS_FILE;
1144}
1145
James Morris13402582005-09-30 14:24:34 -04001146static inline int default_protocol_stream(int protocol)
1147{
1148 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1149}
1150
1151static inline int default_protocol_dgram(int protocol)
1152{
1153 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1154}
1155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1157{
1158 switch (family) {
1159 case PF_UNIX:
1160 switch (type) {
1161 case SOCK_STREAM:
1162 case SOCK_SEQPACKET:
1163 return SECCLASS_UNIX_STREAM_SOCKET;
1164 case SOCK_DGRAM:
1165 return SECCLASS_UNIX_DGRAM_SOCKET;
1166 }
1167 break;
1168 case PF_INET:
1169 case PF_INET6:
1170 switch (type) {
1171 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001172 if (default_protocol_stream(protocol))
1173 return SECCLASS_TCP_SOCKET;
1174 else
1175 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001177 if (default_protocol_dgram(protocol))
1178 return SECCLASS_UDP_SOCKET;
1179 else
1180 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001181 case SOCK_DCCP:
1182 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001183 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 return SECCLASS_RAWIP_SOCKET;
1185 }
1186 break;
1187 case PF_NETLINK:
1188 switch (protocol) {
1189 case NETLINK_ROUTE:
1190 return SECCLASS_NETLINK_ROUTE_SOCKET;
1191 case NETLINK_FIREWALL:
1192 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001193 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1195 case NETLINK_NFLOG:
1196 return SECCLASS_NETLINK_NFLOG_SOCKET;
1197 case NETLINK_XFRM:
1198 return SECCLASS_NETLINK_XFRM_SOCKET;
1199 case NETLINK_SELINUX:
1200 return SECCLASS_NETLINK_SELINUX_SOCKET;
1201 case NETLINK_AUDIT:
1202 return SECCLASS_NETLINK_AUDIT_SOCKET;
1203 case NETLINK_IP6_FW:
1204 return SECCLASS_NETLINK_IP6FW_SOCKET;
1205 case NETLINK_DNRTMSG:
1206 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001207 case NETLINK_KOBJECT_UEVENT:
1208 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 default:
1210 return SECCLASS_NETLINK_SOCKET;
1211 }
1212 case PF_PACKET:
1213 return SECCLASS_PACKET_SOCKET;
1214 case PF_KEY:
1215 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001216 case PF_APPLETALK:
1217 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 }
1219
1220 return SECCLASS_SOCKET;
1221}
1222
1223#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001224static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 u16 tclass,
1226 u32 *sid)
1227{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001228 int rc;
1229 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Eric Paris828dfe12008-04-17 13:17:49 -04001231 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 if (!buffer)
1233 return -ENOMEM;
1234
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001235 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1236 if (IS_ERR(path))
1237 rc = PTR_ERR(path);
1238 else {
1239 /* each process gets a /proc/PID/ entry. Strip off the
1240 * PID part to get a valid selinux labeling.
1241 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1242 while (path[1] >= '0' && path[1] <= '9') {
1243 path[1] = '/';
1244 path++;
1245 }
1246 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 free_page((unsigned long)buffer);
1249 return rc;
1250}
1251#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001252static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 u16 tclass,
1254 u32 *sid)
1255{
1256 return -EINVAL;
1257}
1258#endif
1259
1260/* The inode's security attributes must be initialized before first use. */
1261static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1262{
1263 struct superblock_security_struct *sbsec = NULL;
1264 struct inode_security_struct *isec = inode->i_security;
1265 u32 sid;
1266 struct dentry *dentry;
1267#define INITCONTEXTLEN 255
1268 char *context = NULL;
1269 unsigned len = 0;
1270 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272 if (isec->initialized)
1273 goto out;
1274
Eric Paris23970742006-09-25 23:32:01 -07001275 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001277 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
1279 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001280 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 /* Defer initialization until selinux_complete_init,
1282 after the initial policy is loaded and the security
1283 server is ready to handle calls. */
1284 spin_lock(&sbsec->isec_lock);
1285 if (list_empty(&isec->list))
1286 list_add(&isec->list, &sbsec->isec_head);
1287 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001288 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
1290
1291 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001292 case SECURITY_FS_USE_NATIVE:
1293 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 case SECURITY_FS_USE_XATTR:
1295 if (!inode->i_op->getxattr) {
1296 isec->sid = sbsec->def_sid;
1297 break;
1298 }
1299
1300 /* Need a dentry, since the xattr API requires one.
1301 Life would be simpler if we could just pass the inode. */
1302 if (opt_dentry) {
1303 /* Called from d_instantiate or d_splice_alias. */
1304 dentry = dget(opt_dentry);
1305 } else {
1306 /* Called from selinux_complete_init, try to find a dentry. */
1307 dentry = d_find_alias(inode);
1308 }
1309 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001310 /*
1311 * this is can be hit on boot when a file is accessed
1312 * before the policy is loaded. When we load policy we
1313 * may find inodes that have no dentry on the
1314 * sbsec->isec_head list. No reason to complain as these
1315 * will get fixed up the next time we go through
1316 * inode_doinit with a dentry, before these inodes could
1317 * be used again by userspace.
1318 */
Eric Paris23970742006-09-25 23:32:01 -07001319 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 }
1321
1322 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001323 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (!context) {
1325 rc = -ENOMEM;
1326 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001327 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001329 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1331 context, len);
1332 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001333 kfree(context);
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 /* Need a larger buffer. Query for the right size. */
1336 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1337 NULL, 0);
1338 if (rc < 0) {
1339 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001340 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001343 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 if (!context) {
1345 rc = -ENOMEM;
1346 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001347 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001349 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 rc = inode->i_op->getxattr(dentry,
1351 XATTR_NAME_SELINUX,
1352 context, len);
1353 }
1354 dput(dentry);
1355 if (rc < 0) {
1356 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001357 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001358 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 -rc, inode->i_sb->s_id, inode->i_ino);
1360 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001361 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 }
1363 /* Map ENODATA to the default file SID */
1364 sid = sbsec->def_sid;
1365 rc = 0;
1366 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001367 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001368 sbsec->def_sid,
1369 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001371 char *dev = inode->i_sb->s_id;
1372 unsigned long ino = inode->i_ino;
1373
1374 if (rc == -EINVAL) {
1375 if (printk_ratelimit())
1376 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1377 "context=%s. This indicates you may need to relabel the inode or the "
1378 "filesystem in question.\n", ino, dev, context);
1379 } else {
1380 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1381 "returned %d for dev=%s ino=%ld\n",
1382 __func__, context, -rc, dev, ino);
1383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 kfree(context);
1385 /* Leave with the unlabeled SID */
1386 rc = 0;
1387 break;
1388 }
1389 }
1390 kfree(context);
1391 isec->sid = sid;
1392 break;
1393 case SECURITY_FS_USE_TASK:
1394 isec->sid = isec->task_sid;
1395 break;
1396 case SECURITY_FS_USE_TRANS:
1397 /* Default to the fs SID. */
1398 isec->sid = sbsec->sid;
1399
1400 /* Try to obtain a transition SID. */
1401 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001402 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1403 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001405 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 isec->sid = sid;
1407 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001408 case SECURITY_FS_USE_MNTPOINT:
1409 isec->sid = sbsec->mntpoint_sid;
1410 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001412 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 isec->sid = sbsec->sid;
1414
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001415 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001416 /* We must have a dentry to determine the label on
1417 * procfs inodes */
1418 if (opt_dentry)
1419 /* Called from d_instantiate or
1420 * d_splice_alias. */
1421 dentry = dget(opt_dentry);
1422 else
1423 /* Called from selinux_complete_init, try to
1424 * find a dentry. */
1425 dentry = d_find_alias(inode);
1426 /*
1427 * This can be hit on boot when a file is accessed
1428 * before the policy is loaded. When we load policy we
1429 * may find inodes that have no dentry on the
1430 * sbsec->isec_head list. No reason to complain as
1431 * these will get fixed up the next time we go through
1432 * inode_doinit() with a dentry, before these inodes
1433 * could be used again by userspace.
1434 */
1435 if (!dentry)
1436 goto out_unlock;
1437 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1438 rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
1439 dput(dentry);
1440 if (rc)
1441 goto out_unlock;
1442 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 }
1444 break;
1445 }
1446
1447 isec->initialized = 1;
1448
Eric Paris23970742006-09-25 23:32:01 -07001449out_unlock:
1450 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451out:
1452 if (isec->sclass == SECCLASS_FILE)
1453 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 return rc;
1455}
1456
1457/* Convert a Linux signal to an access vector. */
1458static inline u32 signal_to_av(int sig)
1459{
1460 u32 perm = 0;
1461
1462 switch (sig) {
1463 case SIGCHLD:
1464 /* Commonly granted from child to parent. */
1465 perm = PROCESS__SIGCHLD;
1466 break;
1467 case SIGKILL:
1468 /* Cannot be caught or ignored */
1469 perm = PROCESS__SIGKILL;
1470 break;
1471 case SIGSTOP:
1472 /* Cannot be caught or ignored */
1473 perm = PROCESS__SIGSTOP;
1474 break;
1475 default:
1476 /* All other signals. */
1477 perm = PROCESS__SIGNAL;
1478 break;
1479 }
1480
1481 return perm;
1482}
1483
David Howells275bb412008-11-14 10:39:19 +11001484/*
David Howellsd84f4f92008-11-14 10:39:23 +11001485 * Check permission between a pair of credentials
1486 * fork check, ptrace check, etc.
1487 */
1488static int cred_has_perm(const struct cred *actor,
1489 const struct cred *target,
1490 u32 perms)
1491{
1492 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1493
1494 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1495}
1496
1497/*
David Howells88e67f32008-11-14 10:39:21 +11001498 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001499 * fork check, ptrace check, etc.
1500 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001501 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001502 */
1503static int task_has_perm(const struct task_struct *tsk1,
1504 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 u32 perms)
1506{
David Howells275bb412008-11-14 10:39:19 +11001507 const struct task_security_struct *__tsec1, *__tsec2;
1508 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
David Howells275bb412008-11-14 10:39:19 +11001510 rcu_read_lock();
1511 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1512 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1513 rcu_read_unlock();
1514 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515}
1516
David Howells3b11a1d2008-11-14 10:39:26 +11001517/*
1518 * Check permission between current and another task, e.g. signal checks,
1519 * fork check, ptrace check, etc.
1520 * current is the actor and tsk2 is the target
1521 * - this uses current's subjective creds
1522 */
1523static int current_has_perm(const struct task_struct *tsk,
1524 u32 perms)
1525{
1526 u32 sid, tsid;
1527
1528 sid = current_sid();
1529 tsid = task_sid(tsk);
1530 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1531}
1532
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001533#if CAP_LAST_CAP > 63
1534#error Fix SELinux to handle capabilities > 63.
1535#endif
1536
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001538static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001539 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
Thomas Liu2bf49692009-07-14 12:14:09 -04001541 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001542 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001543 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001544 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001545 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001546 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Eric Paris50c205f2012-04-04 15:01:43 -04001548 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 ad.u.cap = cap;
1550
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001551 switch (CAP_TO_INDEX(cap)) {
1552 case 0:
1553 sclass = SECCLASS_CAPABILITY;
1554 break;
1555 case 1:
1556 sclass = SECCLASS_CAPABILITY2;
1557 break;
1558 default:
1559 printk(KERN_ERR
1560 "SELinux: out of range capability %d\n", cap);
1561 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001562 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001563 }
Eric Paris06112162008-11-11 22:02:50 +11001564
David Howells275bb412008-11-14 10:39:19 +11001565 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001566 if (audit == SECURITY_CAP_AUDIT) {
Linus Torvaldsab354062013-10-04 14:05:38 -07001567 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001568 if (rc2)
1569 return rc2;
1570 }
Eric Paris06112162008-11-11 22:02:50 +11001571 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572}
1573
1574/* Check whether a task is allowed to use a system operation. */
1575static int task_has_system(struct task_struct *tsk,
1576 u32 perms)
1577{
David Howells275bb412008-11-14 10:39:19 +11001578 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
David Howells275bb412008-11-14 10:39:19 +11001580 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 SECCLASS_SYSTEM, perms, NULL);
1582}
1583
1584/* Check whether a task has a particular permission to an inode.
1585 The 'adp' parameter is optional and allows other audit
1586 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001587static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 struct inode *inode,
1589 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001590 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001593 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
David Howellse0e81732009-09-02 09:13:40 +01001595 validate_creds(cred);
1596
Eric Paris828dfe12008-04-17 13:17:49 -04001597 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001598 return 0;
1599
David Howells88e67f32008-11-14 10:39:21 +11001600 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 isec = inode->i_security;
1602
Linus Torvalds19e49832013-10-04 12:54:11 -07001603 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604}
1605
1606/* Same as inode_has_perm, but pass explicit audit data containing
1607 the dentry to help the auditing code to more easily generate the
1608 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001609static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 struct dentry *dentry,
1611 u32 av)
1612{
David Howellsc6f493d2015-03-17 22:26:22 +00001613 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001614 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001615
Eric Paris50c205f2012-04-04 15:01:43 -04001616 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001617 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001618 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001619}
1620
1621/* Same as inode_has_perm, but pass explicit audit data containing
1622 the path to help the auditing code to more easily generate the
1623 pathname if needed. */
1624static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001625 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001626 u32 av)
1627{
David Howellsc6f493d2015-03-17 22:26:22 +00001628 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001629 struct common_audit_data ad;
1630
Eric Paris50c205f2012-04-04 15:01:43 -04001631 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001632 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001633 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634}
1635
David Howells13f8e982013-06-13 23:37:55 +01001636/* Same as path_has_perm, but uses the inode from the file struct. */
1637static inline int file_path_has_perm(const struct cred *cred,
1638 struct file *file,
1639 u32 av)
1640{
1641 struct common_audit_data ad;
1642
1643 ad.type = LSM_AUDIT_DATA_PATH;
1644 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001645 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001646}
1647
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648/* Check whether a task can use an open file descriptor to
1649 access an inode in a given way. Check access to the
1650 descriptor itself, and then use dentry_has_perm to
1651 check a particular permission to the file.
1652 Access to the descriptor is implicitly granted if it
1653 has the same SID as the process. If av is zero, then
1654 access to the file is not checked, e.g. for cases
1655 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001656static int file_has_perm(const struct cred *cred,
1657 struct file *file,
1658 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001661 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001662 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001663 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 int rc;
1665
Eric Paris50c205f2012-04-04 15:01:43 -04001666 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001667 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
David Howells275bb412008-11-14 10:39:19 +11001669 if (sid != fsec->sid) {
1670 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 SECCLASS_FD,
1672 FD__USE,
1673 &ad);
1674 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001675 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 }
1677
1678 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001679 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001681 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
David Howells88e67f32008-11-14 10:39:21 +11001683out:
1684 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685}
1686
1687/* Check whether a task can create a file. */
1688static int may_create(struct inode *dir,
1689 struct dentry *dentry,
1690 u16 tclass)
1691{
Paul Moore5fb49872010-04-22 14:46:19 -04001692 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 struct inode_security_struct *dsec;
1694 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001695 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001696 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 int rc;
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 dsec = dir->i_security;
1700 sbsec = dir->i_sb->s_security;
1701
David Howells275bb412008-11-14 10:39:19 +11001702 sid = tsec->sid;
1703 newsid = tsec->create_sid;
1704
Eric Paris50c205f2012-04-04 15:01:43 -04001705 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001706 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
David Howells275bb412008-11-14 10:39:19 +11001708 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 DIR__ADD_NAME | DIR__SEARCH,
1710 &ad);
1711 if (rc)
1712 return rc;
1713
Eric Paris12f348b2012-10-09 10:56:25 -04001714 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001715 rc = security_transition_sid(sid, dsec->sid, tclass,
1716 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 if (rc)
1718 return rc;
1719 }
1720
David Howells275bb412008-11-14 10:39:19 +11001721 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 if (rc)
1723 return rc;
1724
1725 return avc_has_perm(newsid, sbsec->sid,
1726 SECCLASS_FILESYSTEM,
1727 FILESYSTEM__ASSOCIATE, &ad);
1728}
1729
Michael LeMay4eb582c2006-06-26 00:24:57 -07001730/* Check whether a task can create a key. */
1731static int may_create_key(u32 ksid,
1732 struct task_struct *ctx)
1733{
David Howells275bb412008-11-14 10:39:19 +11001734 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001735
David Howells275bb412008-11-14 10:39:19 +11001736 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001737}
1738
Eric Paris828dfe12008-04-17 13:17:49 -04001739#define MAY_LINK 0
1740#define MAY_UNLINK 1
1741#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
1743/* Check whether a task can link, unlink, or rmdir a file/directory. */
1744static int may_link(struct inode *dir,
1745 struct dentry *dentry,
1746 int kind)
1747
1748{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001750 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001751 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 u32 av;
1753 int rc;
1754
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001756 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
Eric Paris50c205f2012-04-04 15:01:43 -04001758 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001759 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
1761 av = DIR__SEARCH;
1762 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001763 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 if (rc)
1765 return rc;
1766
1767 switch (kind) {
1768 case MAY_LINK:
1769 av = FILE__LINK;
1770 break;
1771 case MAY_UNLINK:
1772 av = FILE__UNLINK;
1773 break;
1774 case MAY_RMDIR:
1775 av = DIR__RMDIR;
1776 break;
1777 default:
Eric Paris744ba352008-04-17 11:52:44 -04001778 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1779 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 return 0;
1781 }
1782
David Howells275bb412008-11-14 10:39:19 +11001783 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 return rc;
1785}
1786
1787static inline int may_rename(struct inode *old_dir,
1788 struct dentry *old_dentry,
1789 struct inode *new_dir,
1790 struct dentry *new_dentry)
1791{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001793 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001794 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 u32 av;
1796 int old_is_dir, new_is_dir;
1797 int rc;
1798
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001800 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001801 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 new_dsec = new_dir->i_security;
1803
Eric Paris50c205f2012-04-04 15:01:43 -04001804 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Eric Parisa2694342011-04-25 13:10:27 -04001806 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001807 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1809 if (rc)
1810 return rc;
David Howells275bb412008-11-14 10:39:19 +11001811 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 old_isec->sclass, FILE__RENAME, &ad);
1813 if (rc)
1814 return rc;
1815 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001816 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 old_isec->sclass, DIR__REPARENT, &ad);
1818 if (rc)
1819 return rc;
1820 }
1821
Eric Parisa2694342011-04-25 13:10:27 -04001822 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001824 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001826 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 if (rc)
1828 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001829 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001830 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001831 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001832 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 new_isec->sclass,
1834 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1835 if (rc)
1836 return rc;
1837 }
1838
1839 return 0;
1840}
1841
1842/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001843static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 struct super_block *sb,
1845 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001846 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001849 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001852 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853}
1854
1855/* Convert a Linux mode and permission mask to an access vector. */
1856static inline u32 file_mask_to_av(int mode, int mask)
1857{
1858 u32 av = 0;
1859
Al Virodba19c62011-07-25 20:49:29 -04001860 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 if (mask & MAY_EXEC)
1862 av |= FILE__EXECUTE;
1863 if (mask & MAY_READ)
1864 av |= FILE__READ;
1865
1866 if (mask & MAY_APPEND)
1867 av |= FILE__APPEND;
1868 else if (mask & MAY_WRITE)
1869 av |= FILE__WRITE;
1870
1871 } else {
1872 if (mask & MAY_EXEC)
1873 av |= DIR__SEARCH;
1874 if (mask & MAY_WRITE)
1875 av |= DIR__WRITE;
1876 if (mask & MAY_READ)
1877 av |= DIR__READ;
1878 }
1879
1880 return av;
1881}
1882
1883/* Convert a Linux file to an access vector. */
1884static inline u32 file_to_av(struct file *file)
1885{
1886 u32 av = 0;
1887
1888 if (file->f_mode & FMODE_READ)
1889 av |= FILE__READ;
1890 if (file->f_mode & FMODE_WRITE) {
1891 if (file->f_flags & O_APPEND)
1892 av |= FILE__APPEND;
1893 else
1894 av |= FILE__WRITE;
1895 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001896 if (!av) {
1897 /*
1898 * Special file opened with flags 3 for ioctl-only use.
1899 */
1900 av = FILE__IOCTL;
1901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
1903 return av;
1904}
1905
Eric Paris8b6a5a32008-10-29 17:06:46 -04001906/*
1907 * Convert a file to an access vector and include the correct open
1908 * open permission.
1909 */
1910static inline u32 open_file_to_av(struct file *file)
1911{
1912 u32 av = file_to_av(file);
1913
Eric Paris49b7b8d2010-07-23 11:44:09 -04001914 if (selinux_policycap_openperm)
1915 av |= FILE__OPEN;
1916
Eric Paris8b6a5a32008-10-29 17:06:46 -04001917 return av;
1918}
1919
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920/* Hook functions begin here. */
1921
Stephen Smalley79af7302015-01-21 10:54:10 -05001922static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1923{
1924 u32 mysid = current_sid();
1925 u32 mgrsid = task_sid(mgr);
1926
1927 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1928 BINDER__SET_CONTEXT_MGR, NULL);
1929}
1930
1931static int selinux_binder_transaction(struct task_struct *from,
1932 struct task_struct *to)
1933{
1934 u32 mysid = current_sid();
1935 u32 fromsid = task_sid(from);
1936 u32 tosid = task_sid(to);
1937 int rc;
1938
1939 if (mysid != fromsid) {
1940 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1941 BINDER__IMPERSONATE, NULL);
1942 if (rc)
1943 return rc;
1944 }
1945
1946 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1947 NULL);
1948}
1949
1950static int selinux_binder_transfer_binder(struct task_struct *from,
1951 struct task_struct *to)
1952{
1953 u32 fromsid = task_sid(from);
1954 u32 tosid = task_sid(to);
1955
1956 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
1957 NULL);
1958}
1959
1960static int selinux_binder_transfer_file(struct task_struct *from,
1961 struct task_struct *to,
1962 struct file *file)
1963{
1964 u32 sid = task_sid(to);
1965 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001966 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05001967 struct inode_security_struct *isec = inode->i_security;
1968 struct common_audit_data ad;
1969 int rc;
1970
1971 ad.type = LSM_AUDIT_DATA_PATH;
1972 ad.u.path = file->f_path;
1973
1974 if (sid != fsec->sid) {
1975 rc = avc_has_perm(sid, fsec->sid,
1976 SECCLASS_FD,
1977 FD__USE,
1978 &ad);
1979 if (rc)
1980 return rc;
1981 }
1982
1983 if (unlikely(IS_PRIVATE(inode)))
1984 return 0;
1985
1986 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
1987 &ad);
1988}
1989
Ingo Molnar9e488582009-05-07 19:26:19 +10001990static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001991 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992{
Eric Paris69f594a2012-01-03 12:25:15 -05001993 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001994 u32 sid = current_sid();
1995 u32 csid = task_sid(child);
1996 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001997 }
1998
David Howells3b11a1d2008-11-14 10:39:26 +11001999 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002000}
2001
2002static int selinux_ptrace_traceme(struct task_struct *parent)
2003{
David Howells5cd9c582008-08-14 11:37:28 +01002004 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005}
2006
2007static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002008 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002010 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011}
2012
David Howellsd84f4f92008-11-14 10:39:23 +11002013static int selinux_capset(struct cred *new, const struct cred *old,
2014 const kernel_cap_t *effective,
2015 const kernel_cap_t *inheritable,
2016 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017{
David Howellsd84f4f92008-11-14 10:39:23 +11002018 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019}
2020
James Morris5626d3e2009-01-30 10:05:06 +11002021/*
2022 * (This comment used to live with the selinux_task_setuid hook,
2023 * which was removed).
2024 *
2025 * Since setuid only affects the current process, and since the SELinux
2026 * controls are not based on the Linux identity attributes, SELinux does not
2027 * need to control this operation. However, SELinux does control the use of
2028 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2029 */
2030
Eric Paris6a9de492012-01-03 12:25:14 -05002031static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2032 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033{
Eric Paris6a9de492012-01-03 12:25:14 -05002034 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035}
2036
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2038{
David Howells88e67f32008-11-14 10:39:21 +11002039 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 int rc = 0;
2041
2042 if (!sb)
2043 return 0;
2044
2045 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002046 case Q_SYNC:
2047 case Q_QUOTAON:
2048 case Q_QUOTAOFF:
2049 case Q_SETINFO:
2050 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002051 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002052 break;
2053 case Q_GETFMT:
2054 case Q_GETINFO:
2055 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002056 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002057 break;
2058 default:
2059 rc = 0; /* let the kernel handle invalid cmds */
2060 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 }
2062 return rc;
2063}
2064
2065static int selinux_quota_on(struct dentry *dentry)
2066{
David Howells88e67f32008-11-14 10:39:21 +11002067 const struct cred *cred = current_cred();
2068
Eric Paris2875fa02011-04-28 16:04:24 -04002069 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070}
2071
Eric Paris12b30522010-11-15 18:36:29 -05002072static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073{
2074 int rc;
2075
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002077 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2078 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002079 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2080 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002081 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2082 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2083 /* Set level of messages printed to console */
2084 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002085 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2086 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002087 case SYSLOG_ACTION_CLOSE: /* Close log */
2088 case SYSLOG_ACTION_OPEN: /* Open log */
2089 case SYSLOG_ACTION_READ: /* Read from log */
2090 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2091 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002092 default:
2093 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2094 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 }
2096 return rc;
2097}
2098
2099/*
2100 * Check that a process has enough memory to allocate a new virtual
2101 * mapping. 0 means there is enough memory for the allocation to
2102 * succeed and -ENOMEM implies there is not.
2103 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 * Do not audit the selinux permission check, as this is applied to all
2105 * processes that allocate mappings.
2106 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002107static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002111 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2112 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 if (rc == 0)
2114 cap_sys_admin = 1;
2115
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002116 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117}
2118
2119/* binprm security operations */
2120
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002121static int check_nnp_nosuid(const struct linux_binprm *bprm,
2122 const struct task_security_struct *old_tsec,
2123 const struct task_security_struct *new_tsec)
2124{
2125 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2126 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2127 int rc;
2128
2129 if (!nnp && !nosuid)
2130 return 0; /* neither NNP nor nosuid */
2131
2132 if (new_tsec->sid == old_tsec->sid)
2133 return 0; /* No change in credentials */
2134
2135 /*
2136 * The only transitions we permit under NNP or nosuid
2137 * are transitions to bounded SIDs, i.e. SIDs that are
2138 * guaranteed to only be allowed a subset of the permissions
2139 * of the current SID.
2140 */
2141 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2142 if (rc) {
2143 /*
2144 * On failure, preserve the errno values for NNP vs nosuid.
2145 * NNP: Operation not permitted for caller.
2146 * nosuid: Permission denied to file.
2147 */
2148 if (nnp)
2149 return -EPERM;
2150 else
2151 return -EACCES;
2152 }
2153 return 0;
2154}
2155
David Howellsa6f76f22008-11-14 10:39:24 +11002156static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157{
David Howellsa6f76f22008-11-14 10:39:24 +11002158 const struct task_security_struct *old_tsec;
2159 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002161 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002162 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 int rc;
2164
David Howellsa6f76f22008-11-14 10:39:24 +11002165 /* SELinux context only depends on initial program or script and not
2166 * the script interpreter */
2167 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 return 0;
2169
David Howellsa6f76f22008-11-14 10:39:24 +11002170 old_tsec = current_security();
2171 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 isec = inode->i_security;
2173
2174 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002175 new_tsec->sid = old_tsec->sid;
2176 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
Michael LeMay28eba5b2006-06-27 02:53:42 -07002178 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002179 new_tsec->create_sid = 0;
2180 new_tsec->keycreate_sid = 0;
2181 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
David Howellsa6f76f22008-11-14 10:39:24 +11002183 if (old_tsec->exec_sid) {
2184 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002186 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002187
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002188 /* Fail on NNP or nosuid if not an allowed transition. */
2189 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2190 if (rc)
2191 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 } else {
2193 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002194 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002195 SECCLASS_PROCESS, NULL,
2196 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 if (rc)
2198 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002199
2200 /*
2201 * Fallback to old SID on NNP or nosuid if not an allowed
2202 * transition.
2203 */
2204 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2205 if (rc)
2206 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 }
2208
Eric Paris50c205f2012-04-04 15:01:43 -04002209 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002210 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
David Howellsa6f76f22008-11-14 10:39:24 +11002212 if (new_tsec->sid == old_tsec->sid) {
2213 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2215 if (rc)
2216 return rc;
2217 } else {
2218 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002219 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2221 if (rc)
2222 return rc;
2223
David Howellsa6f76f22008-11-14 10:39:24 +11002224 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2226 if (rc)
2227 return rc;
2228
David Howellsa6f76f22008-11-14 10:39:24 +11002229 /* Check for shared state */
2230 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2231 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2232 SECCLASS_PROCESS, PROCESS__SHARE,
2233 NULL);
2234 if (rc)
2235 return -EPERM;
2236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
David Howellsa6f76f22008-11-14 10:39:24 +11002238 /* Make sure that anyone attempting to ptrace over a task that
2239 * changes its SID has the appropriate permit */
2240 if (bprm->unsafe &
2241 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2242 struct task_struct *tracer;
2243 struct task_security_struct *sec;
2244 u32 ptsid = 0;
2245
2246 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002247 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002248 if (likely(tracer != NULL)) {
2249 sec = __task_cred(tracer)->security;
2250 ptsid = sec->sid;
2251 }
2252 rcu_read_unlock();
2253
2254 if (ptsid != 0) {
2255 rc = avc_has_perm(ptsid, new_tsec->sid,
2256 SECCLASS_PROCESS,
2257 PROCESS__PTRACE, NULL);
2258 if (rc)
2259 return -EPERM;
2260 }
2261 }
2262
2263 /* Clear any possibly unsafe personality bits on exec: */
2264 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
2266
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 return 0;
2268}
2269
Eric Paris828dfe12008-04-17 13:17:49 -04002270static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271{
Paul Moore5fb49872010-04-22 14:46:19 -04002272 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002273 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 int atsecure = 0;
2275
David Howells275bb412008-11-14 10:39:19 +11002276 sid = tsec->sid;
2277 osid = tsec->osid;
2278
2279 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 /* Enable secure mode for SIDs transitions unless
2281 the noatsecure permission is granted between
2282 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002283 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002284 SECCLASS_PROCESS,
2285 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 }
2287
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002288 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289}
2290
Al Viroc3c073f2012-08-21 22:32:06 -04002291static int match_file(const void *p, struct file *file, unsigned fd)
2292{
2293 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2294}
2295
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002297static inline void flush_unauthorized_files(const struct cred *cred,
2298 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002301 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002302 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002303 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002305 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002307 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002308 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002309 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002312 Use file_path_has_perm on the tty path directly
2313 rather than using file_has_perm, as this particular
2314 open file may belong to another process and we are
2315 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002316 file_priv = list_first_entry(&tty->tty_files,
2317 struct tty_file_private, list);
2318 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002319 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002320 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002322 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002323 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002325 /* Reset controlling tty. */
2326 if (drop_tty)
2327 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
2329 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002330 n = iterate_fd(files, 0, match_file, cred);
2331 if (!n) /* none found? */
2332 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
Al Viroc3c073f2012-08-21 22:32:06 -04002334 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002335 if (IS_ERR(devnull))
2336 devnull = NULL;
2337 /* replace all the matching ones with this */
2338 do {
2339 replace_fd(n - 1, devnull, 0);
2340 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2341 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002342 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343}
2344
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345/*
David Howellsa6f76f22008-11-14 10:39:24 +11002346 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 */
David Howellsa6f76f22008-11-14 10:39:24 +11002348static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349{
David Howellsa6f76f22008-11-14 10:39:24 +11002350 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 int rc, i;
2353
David Howellsa6f76f22008-11-14 10:39:24 +11002354 new_tsec = bprm->cred->security;
2355 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 return;
2357
2358 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002359 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
David Howellsa6f76f22008-11-14 10:39:24 +11002361 /* Always clear parent death signal on SID transitions. */
2362 current->pdeath_signal = 0;
2363
2364 /* Check whether the new SID can inherit resource limits from the old
2365 * SID. If not, reset all soft limits to the lower of the current
2366 * task's hard limit and the init task's soft limit.
2367 *
2368 * Note that the setting of hard limits (even to lower them) can be
2369 * controlled by the setrlimit check. The inclusion of the init task's
2370 * soft limit into the computation is to avoid resetting soft limits
2371 * higher than the default soft limit for cases where the default is
2372 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2373 */
2374 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2375 PROCESS__RLIMITINH, NULL);
2376 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002377 /* protect against do_prlimit() */
2378 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002379 for (i = 0; i < RLIM_NLIMITS; i++) {
2380 rlim = current->signal->rlim + i;
2381 initrlim = init_task.signal->rlim + i;
2382 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2383 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002384 task_unlock(current);
2385 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002386 }
2387}
2388
2389/*
2390 * Clean up the process immediately after the installation of new credentials
2391 * due to exec
2392 */
2393static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2394{
2395 const struct task_security_struct *tsec = current_security();
2396 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002397 u32 osid, sid;
2398 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002399
David Howellsa6f76f22008-11-14 10:39:24 +11002400 osid = tsec->osid;
2401 sid = tsec->sid;
2402
2403 if (sid == osid)
2404 return;
2405
2406 /* Check whether the new SID can inherit signal state from the old SID.
2407 * If not, clear itimers to avoid subsequent signal generation and
2408 * flush and unblock signals.
2409 *
2410 * This must occur _after_ the task SID has been updated so that any
2411 * kill done after the flush will be checked against the new SID.
2412 */
2413 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 if (rc) {
2415 memset(&itimer, 0, sizeof itimer);
2416 for (i = 0; i < 3; i++)
2417 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002419 if (!fatal_signal_pending(current)) {
2420 flush_sigqueue(&current->pending);
2421 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002422 flush_signal_handlers(current, 1);
2423 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002424 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 spin_unlock_irq(&current->sighand->siglock);
2427 }
2428
David Howellsa6f76f22008-11-14 10:39:24 +11002429 /* Wake up the parent if it is waiting so that it can recheck
2430 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002431 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002432 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002433 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434}
2435
2436/* superblock security operations */
2437
2438static int selinux_sb_alloc_security(struct super_block *sb)
2439{
2440 return superblock_alloc_security(sb);
2441}
2442
2443static void selinux_sb_free_security(struct super_block *sb)
2444{
2445 superblock_free_security(sb);
2446}
2447
2448static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2449{
2450 if (plen > olen)
2451 return 0;
2452
2453 return !memcmp(prefix, option, plen);
2454}
2455
2456static inline int selinux_option(char *option, int len)
2457{
Eric Paris832cbd92008-04-01 13:24:09 -04002458 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2459 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2460 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002461 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2462 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463}
2464
2465static inline void take_option(char **to, char *from, int *first, int len)
2466{
2467 if (!*first) {
2468 **to = ',';
2469 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002470 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 *first = 0;
2472 memcpy(*to, from, len);
2473 *to += len;
2474}
2475
Eric Paris828dfe12008-04-17 13:17:49 -04002476static inline void take_selinux_option(char **to, char *from, int *first,
2477 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002478{
2479 int current_size = 0;
2480
2481 if (!*first) {
2482 **to = '|';
2483 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002484 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002485 *first = 0;
2486
2487 while (current_size < len) {
2488 if (*from != '"') {
2489 **to = *from;
2490 *to += 1;
2491 }
2492 from += 1;
2493 current_size += 1;
2494 }
2495}
2496
Eric Parise0007522008-03-05 10:31:54 -05002497static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498{
2499 int fnosec, fsec, rc = 0;
2500 char *in_save, *in_curr, *in_end;
2501 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002502 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
2504 in_curr = orig;
2505 sec_curr = copy;
2506
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2508 if (!nosec) {
2509 rc = -ENOMEM;
2510 goto out;
2511 }
2512
2513 nosec_save = nosec;
2514 fnosec = fsec = 1;
2515 in_save = in_end = orig;
2516
2517 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002518 if (*in_end == '"')
2519 open_quote = !open_quote;
2520 if ((*in_end == ',' && open_quote == 0) ||
2521 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 int len = in_end - in_curr;
2523
2524 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002525 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 else
2527 take_option(&nosec, in_curr, &fnosec, len);
2528
2529 in_curr = in_end + 1;
2530 }
2531 } while (*in_end++);
2532
Eric Paris6931dfc2005-06-30 02:58:51 -07002533 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002534 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535out:
2536 return rc;
2537}
2538
Eric Paris026eb162011-03-03 16:09:14 -05002539static int selinux_sb_remount(struct super_block *sb, void *data)
2540{
2541 int rc, i, *flags;
2542 struct security_mnt_opts opts;
2543 char *secdata, **mount_options;
2544 struct superblock_security_struct *sbsec = sb->s_security;
2545
2546 if (!(sbsec->flags & SE_SBINITIALIZED))
2547 return 0;
2548
2549 if (!data)
2550 return 0;
2551
2552 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2553 return 0;
2554
2555 security_init_mnt_opts(&opts);
2556 secdata = alloc_secdata();
2557 if (!secdata)
2558 return -ENOMEM;
2559 rc = selinux_sb_copy_data(data, secdata);
2560 if (rc)
2561 goto out_free_secdata;
2562
2563 rc = selinux_parse_opts_str(secdata, &opts);
2564 if (rc)
2565 goto out_free_secdata;
2566
2567 mount_options = opts.mnt_opts;
2568 flags = opts.mnt_opts_flags;
2569
2570 for (i = 0; i < opts.num_mnt_opts; i++) {
2571 u32 sid;
2572 size_t len;
2573
Eric Paris12f348b2012-10-09 10:56:25 -04002574 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002575 continue;
2576 len = strlen(mount_options[i]);
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002577 rc = security_context_to_sid(mount_options[i], len, &sid,
2578 GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002579 if (rc) {
2580 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002581 "(%s) failed for (dev %s, type %s) errno=%d\n",
2582 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002583 goto out_free_opts;
2584 }
2585 rc = -EINVAL;
2586 switch (flags[i]) {
2587 case FSCONTEXT_MNT:
2588 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2589 goto out_bad_option;
2590 break;
2591 case CONTEXT_MNT:
2592 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2593 goto out_bad_option;
2594 break;
2595 case ROOTCONTEXT_MNT: {
2596 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002597 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002598
2599 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2600 goto out_bad_option;
2601 break;
2602 }
2603 case DEFCONTEXT_MNT:
2604 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2605 goto out_bad_option;
2606 break;
2607 default:
2608 goto out_free_opts;
2609 }
2610 }
2611
2612 rc = 0;
2613out_free_opts:
2614 security_free_mnt_opts(&opts);
2615out_free_secdata:
2616 free_secdata(secdata);
2617 return rc;
2618out_bad_option:
2619 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002620 "during remount (dev %s, type=%s)\n", sb->s_id,
2621 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002622 goto out_free_opts;
2623}
2624
James Morris12204e22008-12-19 10:44:42 +11002625static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
David Howells88e67f32008-11-14 10:39:21 +11002627 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002628 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 int rc;
2630
2631 rc = superblock_doinit(sb, data);
2632 if (rc)
2633 return rc;
2634
James Morris74192242008-12-19 11:41:10 +11002635 /* Allow all mounts performed by the kernel */
2636 if (flags & MS_KERNMOUNT)
2637 return 0;
2638
Eric Paris50c205f2012-04-04 15:01:43 -04002639 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002640 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002641 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643
David Howells726c3342006-06-23 02:02:58 -07002644static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645{
David Howells88e67f32008-11-14 10:39:21 +11002646 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002647 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Eric Paris50c205f2012-04-04 15:01:43 -04002649 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002650 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002651 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652}
2653
Al Viro808d4e32012-10-11 11:42:01 -04002654static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002655 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002656 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002657 unsigned long flags,
2658 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659{
David Howells88e67f32008-11-14 10:39:21 +11002660 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
2662 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002663 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002664 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 else
Eric Paris2875fa02011-04-28 16:04:24 -04002666 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667}
2668
2669static int selinux_umount(struct vfsmount *mnt, int flags)
2670{
David Howells88e67f32008-11-14 10:39:21 +11002671 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
David Howells88e67f32008-11-14 10:39:21 +11002673 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002674 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675}
2676
2677/* inode security operations */
2678
2679static int selinux_inode_alloc_security(struct inode *inode)
2680{
2681 return inode_alloc_security(inode);
2682}
2683
2684static void selinux_inode_free_security(struct inode *inode)
2685{
2686 inode_free_security(inode);
2687}
2688
David Quigleyd47be3d2013-05-22 12:50:34 -04002689static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2690 struct qstr *name, void **ctx,
2691 u32 *ctxlen)
2692{
2693 const struct cred *cred = current_cred();
2694 struct task_security_struct *tsec;
2695 struct inode_security_struct *dsec;
2696 struct superblock_security_struct *sbsec;
David Howellsc6f493d2015-03-17 22:26:22 +00002697 struct inode *dir = d_backing_inode(dentry->d_parent);
David Quigleyd47be3d2013-05-22 12:50:34 -04002698 u32 newsid;
2699 int rc;
2700
2701 tsec = cred->security;
2702 dsec = dir->i_security;
2703 sbsec = dir->i_sb->s_security;
2704
2705 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2706 newsid = tsec->create_sid;
2707 } else {
2708 rc = security_transition_sid(tsec->sid, dsec->sid,
2709 inode_mode_to_security_class(mode),
2710 name,
2711 &newsid);
2712 if (rc) {
2713 printk(KERN_WARNING
2714 "%s: security_transition_sid failed, rc=%d\n",
2715 __func__, -rc);
2716 return rc;
2717 }
2718 }
2719
2720 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2721}
2722
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002723static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002724 const struct qstr *qstr,
2725 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002726 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002727{
Paul Moore5fb49872010-04-22 14:46:19 -04002728 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002729 struct inode_security_struct *dsec;
2730 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002731 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002732 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002733 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002734
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002735 dsec = dir->i_security;
2736 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002737
David Howells275bb412008-11-14 10:39:19 +11002738 sid = tsec->sid;
2739 newsid = tsec->create_sid;
2740
Eric Paris415103f2010-12-02 16:13:40 -05002741 if ((sbsec->flags & SE_SBINITIALIZED) &&
2742 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2743 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002744 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002745 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002746 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002747 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002748 if (rc) {
2749 printk(KERN_WARNING "%s: "
2750 "security_transition_sid failed, rc=%d (dev=%s "
2751 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002752 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002753 -rc, inode->i_sb->s_id, inode->i_ino);
2754 return rc;
2755 }
2756 }
2757
Eric Paris296fddf2006-09-25 23:32:00 -07002758 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002759 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002760 struct inode_security_struct *isec = inode->i_security;
2761 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2762 isec->sid = newsid;
2763 isec->initialized = 1;
2764 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002765
Eric Paris12f348b2012-10-09 10:56:25 -04002766 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002767 return -EOPNOTSUPP;
2768
Tetsuo Handa95489062013-07-25 05:44:02 +09002769 if (name)
2770 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002771
2772 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002773 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002774 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002775 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002776 *value = context;
2777 *len = clen;
2778 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002779
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002780 return 0;
2781}
2782
Al Viro4acdaf22011-07-26 01:42:34 -04002783static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784{
2785 return may_create(dir, dentry, SECCLASS_FILE);
2786}
2787
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2789{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return may_link(dir, old_dentry, MAY_LINK);
2791}
2792
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2794{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 return may_link(dir, dentry, MAY_UNLINK);
2796}
2797
2798static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2799{
2800 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2801}
2802
Al Viro18bb1db2011-07-26 01:41:39 -04002803static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804{
2805 return may_create(dir, dentry, SECCLASS_DIR);
2806}
2807
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2809{
2810 return may_link(dir, dentry, MAY_RMDIR);
2811}
2812
Al Viro1a67aaf2011-07-26 01:52:52 -04002813static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2816}
2817
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002819 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820{
2821 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2822}
2823
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824static int selinux_inode_readlink(struct dentry *dentry)
2825{
David Howells88e67f32008-11-14 10:39:21 +11002826 const struct cred *cred = current_cred();
2827
Eric Paris2875fa02011-04-28 16:04:24 -04002828 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829}
2830
2831static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2832{
David Howells88e67f32008-11-14 10:39:21 +11002833 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
Eric Paris2875fa02011-04-28 16:04:24 -04002835 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836}
2837
Eric Parisd4cf970d2012-04-04 15:01:42 -04002838static noinline int audit_inode_permission(struct inode *inode,
2839 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002840 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002841 unsigned flags)
2842{
2843 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002844 struct inode_security_struct *isec = inode->i_security;
2845 int rc;
2846
Eric Paris50c205f2012-04-04 15:01:43 -04002847 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002848 ad.u.inode = inode;
2849
2850 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002851 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002852 if (rc)
2853 return rc;
2854 return 0;
2855}
2856
Al Viroe74f71e2011-06-20 19:38:15 -04002857static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
David Howells88e67f32008-11-14 10:39:21 +11002859 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002860 u32 perms;
2861 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002862 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002863 struct inode_security_struct *isec;
2864 u32 sid;
2865 struct av_decision avd;
2866 int rc, rc2;
2867 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
Eric Parisb782e0a2010-07-23 11:44:03 -04002869 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002870 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2871
Eric Parisb782e0a2010-07-23 11:44:03 -04002872 /* No permission to check. Existence test. */
2873 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Eric Paris2e334052012-04-04 15:01:42 -04002876 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002877
Eric Paris2e334052012-04-04 15:01:42 -04002878 if (unlikely(IS_PRIVATE(inode)))
2879 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002880
2881 perms = file_mask_to_av(inode->i_mode, mask);
2882
Eric Paris2e334052012-04-04 15:01:42 -04002883 sid = cred_sid(cred);
2884 isec = inode->i_security;
2885
2886 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2887 audited = avc_audit_required(perms, &avd, rc,
2888 from_access ? FILE__AUDIT_ACCESS : 0,
2889 &denied);
2890 if (likely(!audited))
2891 return rc;
2892
Stephen Smalley626b9742014-04-29 11:29:04 -07002893 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002894 if (rc2)
2895 return rc2;
2896 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897}
2898
2899static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2900{
David Howells88e67f32008-11-14 10:39:21 +11002901 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002902 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002903 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002905 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2906 if (ia_valid & ATTR_FORCE) {
2907 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2908 ATTR_FORCE);
2909 if (!ia_valid)
2910 return 0;
2911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002913 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2914 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002915 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
Eric Paris3d2195c2012-07-06 14:13:30 -04002917 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002918 av |= FILE__OPEN;
2919
2920 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921}
2922
Al Viro3f7036a2015-03-08 19:28:30 -04002923static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924{
Al Viro3f7036a2015-03-08 19:28:30 -04002925 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926}
2927
David Howells8f0cfa52008-04-29 00:59:41 -07002928static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002929{
David Howells88e67f32008-11-14 10:39:21 +11002930 const struct cred *cred = current_cred();
2931
Serge E. Hallynb5376772007-10-16 23:31:36 -07002932 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2933 sizeof XATTR_SECURITY_PREFIX - 1)) {
2934 if (!strcmp(name, XATTR_NAME_CAPS)) {
2935 if (!capable(CAP_SETFCAP))
2936 return -EPERM;
2937 } else if (!capable(CAP_SYS_ADMIN)) {
2938 /* A different attribute in the security namespace.
2939 Restrict to administrator. */
2940 return -EPERM;
2941 }
2942 }
2943
2944 /* Not an attribute we recognize, so just check the
2945 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002946 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002947}
2948
David Howells8f0cfa52008-04-29 00:59:41 -07002949static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2950 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
David Howellsc6f493d2015-03-17 22:26:22 +00002952 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 struct inode_security_struct *isec = inode->i_security;
2954 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002955 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002956 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 int rc = 0;
2958
Serge E. Hallynb5376772007-10-16 23:31:36 -07002959 if (strcmp(name, XATTR_NAME_SELINUX))
2960 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
2962 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002963 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 return -EOPNOTSUPP;
2965
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002966 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 return -EPERM;
2968
Eric Paris50c205f2012-04-04 15:01:43 -04002969 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002970 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
David Howells275bb412008-11-14 10:39:19 +11002972 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 FILE__RELABELFROM, &ad);
2974 if (rc)
2975 return rc;
2976
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002977 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002978 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002979 if (!capable(CAP_MAC_ADMIN)) {
2980 struct audit_buffer *ab;
2981 size_t audit_size;
2982 const char *str;
2983
2984 /* We strip a nul only if it is at the end, otherwise the
2985 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002986 if (value) {
2987 str = value;
2988 if (str[size - 1] == '\0')
2989 audit_size = size - 1;
2990 else
2991 audit_size = size;
2992 } else {
2993 str = "";
2994 audit_size = 0;
2995 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002996 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2997 audit_log_format(ab, "op=setxattr invalid_context=");
2998 audit_log_n_untrustedstring(ab, value, audit_size);
2999 audit_log_end(ab);
3000
Stephen Smalley12b29f32008-05-07 13:03:20 -04003001 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003002 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003003 rc = security_context_to_sid_force(value, size, &newsid);
3004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 if (rc)
3006 return rc;
3007
David Howells275bb412008-11-14 10:39:19 +11003008 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 FILE__RELABELTO, &ad);
3010 if (rc)
3011 return rc;
3012
David Howells275bb412008-11-14 10:39:19 +11003013 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003014 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 if (rc)
3016 return rc;
3017
3018 return avc_has_perm(newsid,
3019 sbsec->sid,
3020 SECCLASS_FILESYSTEM,
3021 FILESYSTEM__ASSOCIATE,
3022 &ad);
3023}
3024
David Howells8f0cfa52008-04-29 00:59:41 -07003025static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003026 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003027 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028{
David Howellsc6f493d2015-03-17 22:26:22 +00003029 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 struct inode_security_struct *isec = inode->i_security;
3031 u32 newsid;
3032 int rc;
3033
3034 if (strcmp(name, XATTR_NAME_SELINUX)) {
3035 /* Not an attribute we recognize, so nothing to do. */
3036 return;
3037 }
3038
Stephen Smalley12b29f32008-05-07 13:03:20 -04003039 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003041 printk(KERN_ERR "SELinux: unable to map context to SID"
3042 "for (%s, %lu), rc=%d\n",
3043 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 return;
3045 }
3046
David Quigleyaa9c2662013-05-22 12:50:44 -04003047 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003049 isec->initialized = 1;
3050
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 return;
3052}
3053
David Howells8f0cfa52008-04-29 00:59:41 -07003054static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055{
David Howells88e67f32008-11-14 10:39:21 +11003056 const struct cred *cred = current_cred();
3057
Eric Paris2875fa02011-04-28 16:04:24 -04003058 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059}
3060
Eric Paris828dfe12008-04-17 13:17:49 -04003061static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062{
David Howells88e67f32008-11-14 10:39:21 +11003063 const struct cred *cred = current_cred();
3064
Eric Paris2875fa02011-04-28 16:04:24 -04003065 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066}
3067
David Howells8f0cfa52008-04-29 00:59:41 -07003068static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003070 if (strcmp(name, XATTR_NAME_SELINUX))
3071 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
3073 /* No one is allowed to remove a SELinux security label.
3074 You can change the label, but all data must be labeled. */
3075 return -EACCES;
3076}
3077
James Morrisd381d8a2005-10-30 14:59:22 -08003078/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003079 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003080 *
3081 * Permission check is handled by selinux_inode_getxattr hook.
3082 */
David P. Quigley42492592008-02-04 22:29:39 -08003083static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
David P. Quigley42492592008-02-04 22:29:39 -08003085 u32 size;
3086 int error;
3087 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003090 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3091 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003093 /*
3094 * If the caller has CAP_MAC_ADMIN, then get the raw context
3095 * value even if it is not defined by current policy; otherwise,
3096 * use the in-core value under current policy.
3097 * Use the non-auditing forms of the permission checks since
3098 * getxattr may be called by unprivileged processes commonly
3099 * and lack of permission just means that we fall back to the
3100 * in-core context value, not a denial.
3101 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003102 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3103 SECURITY_CAP_NOAUDIT);
3104 if (!error)
3105 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3106 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003107 if (!error)
3108 error = security_sid_to_context_force(isec->sid, &context,
3109 &size);
3110 else
3111 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003112 if (error)
3113 return error;
3114 error = size;
3115 if (alloc) {
3116 *buffer = context;
3117 goto out_nofree;
3118 }
3119 kfree(context);
3120out_nofree:
3121 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122}
3123
3124static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003125 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126{
3127 struct inode_security_struct *isec = inode->i_security;
3128 u32 newsid;
3129 int rc;
3130
3131 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3132 return -EOPNOTSUPP;
3133
3134 if (!value || !size)
3135 return -EACCES;
3136
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003137 rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if (rc)
3139 return rc;
3140
David Quigleyaa9c2662013-05-22 12:50:44 -04003141 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003143 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 return 0;
3145}
3146
3147static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3148{
3149 const int len = sizeof(XATTR_NAME_SELINUX);
3150 if (buffer && len <= buffer_size)
3151 memcpy(buffer, XATTR_NAME_SELINUX, len);
3152 return len;
3153}
3154
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003155static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3156{
3157 struct inode_security_struct *isec = inode->i_security;
3158 *secid = isec->sid;
3159}
3160
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161/* file security operations */
3162
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003163static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164{
David Howells88e67f32008-11-14 10:39:21 +11003165 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003166 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3169 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3170 mask |= MAY_APPEND;
3171
Paul Moore389fb8002009-03-27 17:10:34 -04003172 return file_has_perm(cred, file,
3173 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174}
3175
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003176static int selinux_file_permission(struct file *file, int mask)
3177{
Al Viro496ad9a2013-01-23 17:07:38 -05003178 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003179 struct file_security_struct *fsec = file->f_security;
3180 struct inode_security_struct *isec = inode->i_security;
3181 u32 sid = current_sid();
3182
Paul Moore389fb8002009-03-27 17:10:34 -04003183 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003184 /* No permission to check. Existence test. */
3185 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003186
Stephen Smalley20dda182009-06-22 14:54:53 -04003187 if (sid == fsec->sid && fsec->isid == isec->sid &&
3188 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003189 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003190 return 0;
3191
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003192 return selinux_revalidate_file_permission(file, mask);
3193}
3194
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195static int selinux_file_alloc_security(struct file *file)
3196{
3197 return file_alloc_security(file);
3198}
3199
3200static void selinux_file_free_security(struct file *file)
3201{
3202 file_free_security(file);
3203}
3204
3205static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3206 unsigned long arg)
3207{
David Howells88e67f32008-11-14 10:39:21 +11003208 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003209 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Eric Paris0b24dcb2011-02-25 15:39:20 -05003211 switch (cmd) {
3212 case FIONREAD:
3213 /* fall through */
3214 case FIBMAP:
3215 /* fall through */
3216 case FIGETBSZ:
3217 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003218 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003219 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003220 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003221 error = file_has_perm(cred, file, FILE__GETATTR);
3222 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Al Viro2f99c362012-03-23 16:04:05 -04003224 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003225 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003226 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003227 error = file_has_perm(cred, file, FILE__SETATTR);
3228 break;
3229
3230 /* sys_ioctl() checks */
3231 case FIONBIO:
3232 /* fall through */
3233 case FIOASYNC:
3234 error = file_has_perm(cred, file, 0);
3235 break;
3236
3237 case KDSKBENT:
3238 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003239 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3240 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003241 break;
3242
3243 /* default case assumes that the command will go
3244 * to the file's ioctl() function.
3245 */
3246 default:
3247 error = file_has_perm(cred, file, FILE__IOCTL);
3248 }
3249 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250}
3251
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003252static int default_noexec;
3253
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3255{
David Howells88e67f32008-11-14 10:39:21 +11003256 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003257 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003258
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003259 if (default_noexec &&
3260 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 /*
3262 * We are making executable an anonymous mapping or a
3263 * private file mapping that will also be writable.
3264 * This has an additional check.
3265 */
David Howellsd84f4f92008-11-14 10:39:23 +11003266 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003268 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
3271 if (file) {
3272 /* read access is always possible with a mapping */
3273 u32 av = FILE__READ;
3274
3275 /* write access only matters if the mapping is shared */
3276 if (shared && (prot & PROT_WRITE))
3277 av |= FILE__WRITE;
3278
3279 if (prot & PROT_EXEC)
3280 av |= FILE__EXECUTE;
3281
David Howells88e67f32008-11-14 10:39:21 +11003282 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 }
David Howellsd84f4f92008-11-14 10:39:23 +11003284
3285error:
3286 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287}
3288
Al Viroe5467852012-05-30 13:30:51 -04003289static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003291 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003292
3293 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3294 u32 sid = current_sid();
3295 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3296 MEMPROTECT__MMAP_ZERO, NULL);
3297 }
3298
3299 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003300}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Al Viroe5467852012-05-30 13:30:51 -04003302static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3303 unsigned long prot, unsigned long flags)
3304{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 if (selinux_checkreqprot)
3306 prot = reqprot;
3307
3308 return file_map_prot_check(file, prot,
3309 (flags & MAP_TYPE) == MAP_SHARED);
3310}
3311
3312static int selinux_file_mprotect(struct vm_area_struct *vma,
3313 unsigned long reqprot,
3314 unsigned long prot)
3315{
David Howells88e67f32008-11-14 10:39:21 +11003316 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317
3318 if (selinux_checkreqprot)
3319 prot = reqprot;
3320
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003321 if (default_noexec &&
3322 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003323 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003324 if (vma->vm_start >= vma->vm_mm->start_brk &&
3325 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003326 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003327 } else if (!vma->vm_file &&
3328 vma->vm_start <= vma->vm_mm->start_stack &&
3329 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003330 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003331 } else if (vma->vm_file && vma->anon_vma) {
3332 /*
3333 * We are making executable a file mapping that has
3334 * had some COW done. Since pages might have been
3335 * written, check ability to execute the possibly
3336 * modified content. This typically should only
3337 * occur for text relocations.
3338 */
David Howellsd84f4f92008-11-14 10:39:23 +11003339 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003340 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003341 if (rc)
3342 return rc;
3343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344
3345 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3346}
3347
3348static int selinux_file_lock(struct file *file, unsigned int cmd)
3349{
David Howells88e67f32008-11-14 10:39:21 +11003350 const struct cred *cred = current_cred();
3351
3352 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353}
3354
3355static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3356 unsigned long arg)
3357{
David Howells88e67f32008-11-14 10:39:21 +11003358 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 int err = 0;
3360
3361 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003362 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003363 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003364 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003366 }
3367 /* fall through */
3368 case F_SETOWN:
3369 case F_SETSIG:
3370 case F_GETFL:
3371 case F_GETOWN:
3372 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003373 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003374 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003375 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003376 break;
3377 case F_GETLK:
3378 case F_SETLK:
3379 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003380 case F_OFD_GETLK:
3381 case F_OFD_SETLK:
3382 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003384 case F_GETLK64:
3385 case F_SETLK64:
3386 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387#endif
David Howells88e67f32008-11-14 10:39:21 +11003388 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003389 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 }
3391
3392 return err;
3393}
3394
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003395static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 struct file_security_struct *fsec;
3398
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003400 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401}
3402
3403static int selinux_file_send_sigiotask(struct task_struct *tsk,
3404 struct fown_struct *fown, int signum)
3405{
Eric Paris828dfe12008-04-17 13:17:49 -04003406 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003407 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 struct file_security_struct *fsec;
3410
3411 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003412 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 fsec = file->f_security;
3415
3416 if (!signum)
3417 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3418 else
3419 perm = signal_to_av(signum);
3420
David Howells275bb412008-11-14 10:39:19 +11003421 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 SECCLASS_PROCESS, perm, NULL);
3423}
3424
3425static int selinux_file_receive(struct file *file)
3426{
David Howells88e67f32008-11-14 10:39:21 +11003427 const struct cred *cred = current_cred();
3428
3429 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430}
3431
Eric Paris83d49852012-04-04 13:45:40 -04003432static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003433{
3434 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003435 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003436
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003437 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003438 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003439 /*
3440 * Save inode label and policy sequence number
3441 * at open-time so that selinux_file_permission
3442 * can determine whether revalidation is necessary.
3443 * Task label is already saved in the file security
3444 * struct as its SID.
3445 */
3446 fsec->isid = isec->sid;
3447 fsec->pseqno = avc_policy_seqno();
3448 /*
3449 * Since the inode label or policy seqno may have changed
3450 * between the selinux_inode_permission check and the saving
3451 * of state above, recheck that access is still permitted.
3452 * Otherwise, access might never be revalidated against the
3453 * new inode label or new policy.
3454 * This check is not redundant - do not remove.
3455 */
David Howells13f8e982013-06-13 23:37:55 +01003456 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003457}
3458
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459/* task security operations */
3460
3461static int selinux_task_create(unsigned long clone_flags)
3462{
David Howells3b11a1d2008-11-14 10:39:26 +11003463 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464}
3465
David Howellsf1752ee2008-11-14 10:39:17 +11003466/*
David Howellsee18d642009-09-02 09:14:21 +01003467 * allocate the SELinux part of blank credentials
3468 */
3469static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3470{
3471 struct task_security_struct *tsec;
3472
3473 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3474 if (!tsec)
3475 return -ENOMEM;
3476
3477 cred->security = tsec;
3478 return 0;
3479}
3480
3481/*
David Howellsf1752ee2008-11-14 10:39:17 +11003482 * detach and free the LSM part of a set of credentials
3483 */
3484static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485{
David Howellsf1752ee2008-11-14 10:39:17 +11003486 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003487
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003488 /*
3489 * cred->security == NULL if security_cred_alloc_blank() or
3490 * security_prepare_creds() returned an error.
3491 */
3492 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003493 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003494 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495}
3496
David Howellsd84f4f92008-11-14 10:39:23 +11003497/*
3498 * prepare a new set of credentials for modification
3499 */
3500static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3501 gfp_t gfp)
3502{
3503 const struct task_security_struct *old_tsec;
3504 struct task_security_struct *tsec;
3505
3506 old_tsec = old->security;
3507
3508 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3509 if (!tsec)
3510 return -ENOMEM;
3511
3512 new->security = tsec;
3513 return 0;
3514}
3515
3516/*
David Howellsee18d642009-09-02 09:14:21 +01003517 * transfer the SELinux data to a blank set of creds
3518 */
3519static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3520{
3521 const struct task_security_struct *old_tsec = old->security;
3522 struct task_security_struct *tsec = new->security;
3523
3524 *tsec = *old_tsec;
3525}
3526
3527/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003528 * set the security data for a kernel service
3529 * - all the creation contexts are set to unlabelled
3530 */
3531static int selinux_kernel_act_as(struct cred *new, u32 secid)
3532{
3533 struct task_security_struct *tsec = new->security;
3534 u32 sid = current_sid();
3535 int ret;
3536
3537 ret = avc_has_perm(sid, secid,
3538 SECCLASS_KERNEL_SERVICE,
3539 KERNEL_SERVICE__USE_AS_OVERRIDE,
3540 NULL);
3541 if (ret == 0) {
3542 tsec->sid = secid;
3543 tsec->create_sid = 0;
3544 tsec->keycreate_sid = 0;
3545 tsec->sockcreate_sid = 0;
3546 }
3547 return ret;
3548}
3549
3550/*
3551 * set the file creation context in a security record to the same as the
3552 * objective context of the specified inode
3553 */
3554static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3555{
3556 struct inode_security_struct *isec = inode->i_security;
3557 struct task_security_struct *tsec = new->security;
3558 u32 sid = current_sid();
3559 int ret;
3560
3561 ret = avc_has_perm(sid, isec->sid,
3562 SECCLASS_KERNEL_SERVICE,
3563 KERNEL_SERVICE__CREATE_FILES_AS,
3564 NULL);
3565
3566 if (ret == 0)
3567 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003568 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003569}
3570
Eric Parisdd8dbf22009-11-03 16:35:32 +11003571static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003572{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003573 u32 sid;
3574 struct common_audit_data ad;
3575
3576 sid = task_sid(current);
3577
Eric Paris50c205f2012-04-04 15:01:43 -04003578 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003579 ad.u.kmod_name = kmod_name;
3580
3581 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3582 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003583}
3584
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3586{
David Howells3b11a1d2008-11-14 10:39:26 +11003587 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588}
3589
3590static int selinux_task_getpgid(struct task_struct *p)
3591{
David Howells3b11a1d2008-11-14 10:39:26 +11003592 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593}
3594
3595static int selinux_task_getsid(struct task_struct *p)
3596{
David Howells3b11a1d2008-11-14 10:39:26 +11003597 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598}
3599
David Quigleyf9008e4c2006-06-30 01:55:46 -07003600static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3601{
David Howells275bb412008-11-14 10:39:19 +11003602 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003603}
3604
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605static int selinux_task_setnice(struct task_struct *p, int nice)
3606{
David Howells3b11a1d2008-11-14 10:39:26 +11003607 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608}
3609
James Morris03e68062006-06-23 02:03:58 -07003610static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3611{
David Howells3b11a1d2008-11-14 10:39:26 +11003612 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003613}
3614
David Quigleya1836a42006-06-30 01:55:49 -07003615static int selinux_task_getioprio(struct task_struct *p)
3616{
David Howells3b11a1d2008-11-14 10:39:26 +11003617 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003618}
3619
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003620static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3621 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003623 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
3625 /* Control the ability to change the hard limit (whether
3626 lowering or raising it), so that the hard limit can
3627 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003628 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003630 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
3632 return 0;
3633}
3634
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003635static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636{
David Howells3b11a1d2008-11-14 10:39:26 +11003637 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638}
3639
3640static int selinux_task_getscheduler(struct task_struct *p)
3641{
David Howells3b11a1d2008-11-14 10:39:26 +11003642 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643}
3644
David Quigley35601542006-06-23 02:04:01 -07003645static int selinux_task_movememory(struct task_struct *p)
3646{
David Howells3b11a1d2008-11-14 10:39:26 +11003647 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003648}
3649
David Quigleyf9008e4c2006-06-30 01:55:46 -07003650static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3651 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652{
3653 u32 perm;
3654 int rc;
3655
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 if (!sig)
3657 perm = PROCESS__SIGNULL; /* null signal; existence test */
3658 else
3659 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003660 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003661 rc = avc_has_perm(secid, task_sid(p),
3662 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003663 else
David Howells3b11a1d2008-11-14 10:39:26 +11003664 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003665 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666}
3667
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668static int selinux_task_wait(struct task_struct *p)
3669{
Eric Paris8a535142007-10-22 16:10:31 -04003670 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671}
3672
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673static void selinux_task_to_inode(struct task_struct *p,
3674 struct inode *inode)
3675{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003677 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
David Howells275bb412008-11-14 10:39:19 +11003679 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681}
3682
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003684static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003685 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686{
3687 int offset, ihlen, ret = -EINVAL;
3688 struct iphdr _iph, *ih;
3689
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003690 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3692 if (ih == NULL)
3693 goto out;
3694
3695 ihlen = ih->ihl * 4;
3696 if (ihlen < sizeof(_iph))
3697 goto out;
3698
Eric Paris48c62af2012-04-02 13:15:44 -04003699 ad->u.net->v4info.saddr = ih->saddr;
3700 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 ret = 0;
3702
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003703 if (proto)
3704 *proto = ih->protocol;
3705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003707 case IPPROTO_TCP: {
3708 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709
Eric Paris828dfe12008-04-17 13:17:49 -04003710 if (ntohs(ih->frag_off) & IP_OFFSET)
3711 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
3713 offset += ihlen;
3714 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3715 if (th == NULL)
3716 break;
3717
Eric Paris48c62af2012-04-02 13:15:44 -04003718 ad->u.net->sport = th->source;
3719 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Eric Paris828dfe12008-04-17 13:17:49 -04003723 case IPPROTO_UDP: {
3724 struct udphdr _udph, *uh;
3725
3726 if (ntohs(ih->frag_off) & IP_OFFSET)
3727 break;
3728
3729 offset += ihlen;
3730 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3731 if (uh == NULL)
3732 break;
3733
Eric Paris48c62af2012-04-02 13:15:44 -04003734 ad->u.net->sport = uh->source;
3735 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003736 break;
3737 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738
James Morris2ee92d42006-11-13 16:09:01 -08003739 case IPPROTO_DCCP: {
3740 struct dccp_hdr _dccph, *dh;
3741
3742 if (ntohs(ih->frag_off) & IP_OFFSET)
3743 break;
3744
3745 offset += ihlen;
3746 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3747 if (dh == NULL)
3748 break;
3749
Eric Paris48c62af2012-04-02 13:15:44 -04003750 ad->u.net->sport = dh->dccph_sport;
3751 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003752 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003753 }
James Morris2ee92d42006-11-13 16:09:01 -08003754
Eric Paris828dfe12008-04-17 13:17:49 -04003755 default:
3756 break;
3757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758out:
3759 return ret;
3760}
3761
3762#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3763
3764/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003765static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003766 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767{
3768 u8 nexthdr;
3769 int ret = -EINVAL, offset;
3770 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003771 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003773 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3775 if (ip6 == NULL)
3776 goto out;
3777
Eric Paris48c62af2012-04-02 13:15:44 -04003778 ad->u.net->v6info.saddr = ip6->saddr;
3779 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 ret = 0;
3781
3782 nexthdr = ip6->nexthdr;
3783 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003784 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 if (offset < 0)
3786 goto out;
3787
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003788 if (proto)
3789 *proto = nexthdr;
3790
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 switch (nexthdr) {
3792 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003793 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
3795 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3796 if (th == NULL)
3797 break;
3798
Eric Paris48c62af2012-04-02 13:15:44 -04003799 ad->u.net->sport = th->source;
3800 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 break;
3802 }
3803
3804 case IPPROTO_UDP: {
3805 struct udphdr _udph, *uh;
3806
3807 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3808 if (uh == NULL)
3809 break;
3810
Eric Paris48c62af2012-04-02 13:15:44 -04003811 ad->u.net->sport = uh->source;
3812 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 break;
3814 }
3815
James Morris2ee92d42006-11-13 16:09:01 -08003816 case IPPROTO_DCCP: {
3817 struct dccp_hdr _dccph, *dh;
3818
3819 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3820 if (dh == NULL)
3821 break;
3822
Eric Paris48c62af2012-04-02 13:15:44 -04003823 ad->u.net->sport = dh->dccph_sport;
3824 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003825 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003826 }
James Morris2ee92d42006-11-13 16:09:01 -08003827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 /* includes fragments */
3829 default:
3830 break;
3831 }
3832out:
3833 return ret;
3834}
3835
3836#endif /* IPV6 */
3837
Thomas Liu2bf49692009-07-14 12:14:09 -04003838static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003839 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840{
David Howellscf9481e2008-07-27 21:31:07 +10003841 char *addrp;
3842 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Eric Paris48c62af2012-04-02 13:15:44 -04003844 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003846 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003847 if (ret)
3848 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003849 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3850 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003851 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
3853#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3854 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003855 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003856 if (ret)
3857 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003858 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3859 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003860 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861#endif /* IPV6 */
3862 default:
David Howellscf9481e2008-07-27 21:31:07 +10003863 addrp = NULL;
3864 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 }
3866
David Howellscf9481e2008-07-27 21:31:07 +10003867parse_error:
3868 printk(KERN_WARNING
3869 "SELinux: failure in selinux_parse_skb(),"
3870 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003872
3873okay:
3874 if (_addrp)
3875 *_addrp = addrp;
3876 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877}
3878
Paul Moore4f6a9932007-03-01 14:35:22 -05003879/**
Paul Moore220deb92008-01-29 08:38:23 -05003880 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003881 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003882 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003883 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003884 *
3885 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003886 * Check the various different forms of network peer labeling and determine
3887 * the peer label/SID for the packet; most of the magic actually occurs in
3888 * the security server function security_net_peersid_cmp(). The function
3889 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3890 * or -EACCES if @sid is invalid due to inconsistencies with the different
3891 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003892 *
3893 */
Paul Moore220deb92008-01-29 08:38:23 -05003894static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003895{
Paul Moore71f1cb02008-01-29 08:51:16 -05003896 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003897 u32 xfrm_sid;
3898 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003899 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003900
Paul Moore817eff72013-12-10 14:57:54 -05003901 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003902 if (unlikely(err))
3903 return -EACCES;
3904 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3905 if (unlikely(err))
3906 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003907
Paul Moore71f1cb02008-01-29 08:51:16 -05003908 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3909 if (unlikely(err)) {
3910 printk(KERN_WARNING
3911 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3912 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003913 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003914 }
Paul Moore220deb92008-01-29 08:38:23 -05003915
3916 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003917}
3918
Paul Moore446b8022013-12-04 16:10:51 -05003919/**
3920 * selinux_conn_sid - Determine the child socket label for a connection
3921 * @sk_sid: the parent socket's SID
3922 * @skb_sid: the packet's SID
3923 * @conn_sid: the resulting connection SID
3924 *
3925 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3926 * combined with the MLS information from @skb_sid in order to create
3927 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3928 * of @sk_sid. Returns zero on success, negative values on failure.
3929 *
3930 */
3931static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3932{
3933 int err = 0;
3934
3935 if (skb_sid != SECSID_NULL)
3936 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3937 else
3938 *conn_sid = sk_sid;
3939
3940 return err;
3941}
3942
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003944
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003945static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3946 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003947{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003948 if (tsec->sockcreate_sid > SECSID_NULL) {
3949 *socksid = tsec->sockcreate_sid;
3950 return 0;
3951 }
3952
3953 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3954 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003955}
3956
Paul Moore253bfae2010-04-22 14:46:19 -04003957static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958{
Paul Moore253bfae2010-04-22 14:46:19 -04003959 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003960 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003961 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003962 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
Paul Moore253bfae2010-04-22 14:46:19 -04003964 if (sksec->sid == SECINITSID_KERNEL)
3965 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Eric Paris50c205f2012-04-04 15:01:43 -04003967 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003968 ad.u.net = &net;
3969 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
Paul Moore253bfae2010-04-22 14:46:19 -04003971 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972}
3973
3974static int selinux_socket_create(int family, int type,
3975 int protocol, int kern)
3976{
Paul Moore5fb49872010-04-22 14:46:19 -04003977 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003978 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003979 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003980 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
3982 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003983 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984
David Howells275bb412008-11-14 10:39:19 +11003985 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003986 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3987 if (rc)
3988 return rc;
3989
Paul Moored4f2d972010-04-22 14:46:18 -04003990 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991}
3992
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003993static int selinux_socket_post_create(struct socket *sock, int family,
3994 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995{
Paul Moore5fb49872010-04-22 14:46:19 -04003996 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003997 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003998 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003999 int err = 0;
4000
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004001 isec->sclass = socket_type_to_security_class(family, type, protocol);
4002
David Howells275bb412008-11-14 10:39:19 +11004003 if (kern)
4004 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004005 else {
4006 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4007 if (err)
4008 return err;
4009 }
David Howells275bb412008-11-14 10:39:19 +11004010
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 isec->initialized = 1;
4012
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004013 if (sock->sk) {
4014 sksec = sock->sk->sk_security;
4015 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004016 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004017 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004018 }
4019
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004020 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021}
4022
4023/* Range of port numbers used to automatically bind.
4024 Need to determine whether we should perform a name_bind
4025 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
4027static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4028{
Paul Moore253bfae2010-04-22 14:46:19 -04004029 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 u16 family;
4031 int err;
4032
Paul Moore253bfae2010-04-22 14:46:19 -04004033 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 if (err)
4035 goto out;
4036
4037 /*
4038 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004039 * Multiple address binding for SCTP is not supported yet: we just
4040 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 */
Paul Moore253bfae2010-04-22 14:46:19 -04004042 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 if (family == PF_INET || family == PF_INET6) {
4044 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004045 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004046 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004047 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048 struct sockaddr_in *addr4 = NULL;
4049 struct sockaddr_in6 *addr6 = NULL;
4050 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004051 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 if (family == PF_INET) {
4054 addr4 = (struct sockaddr_in *)address;
4055 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 addrp = (char *)&addr4->sin_addr.s_addr;
4057 } else {
4058 addr6 = (struct sockaddr_in6 *)address;
4059 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 addrp = (char *)&addr6->sin6_addr.s6_addr;
4061 }
4062
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004063 if (snum) {
4064 int low, high;
4065
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004066 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004067
4068 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004069 err = sel_netport_sid(sk->sk_protocol,
4070 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004071 if (err)
4072 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004073 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004074 ad.u.net = &net;
4075 ad.u.net->sport = htons(snum);
4076 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004077 err = avc_has_perm(sksec->sid, sid,
4078 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004079 SOCKET__NAME_BIND, &ad);
4080 if (err)
4081 goto out;
4082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 }
Eric Paris828dfe12008-04-17 13:17:49 -04004084
Paul Moore253bfae2010-04-22 14:46:19 -04004085 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004086 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 node_perm = TCP_SOCKET__NODE_BIND;
4088 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004089
James Morris13402582005-09-30 14:24:34 -04004090 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 node_perm = UDP_SOCKET__NODE_BIND;
4092 break;
James Morris2ee92d42006-11-13 16:09:01 -08004093
4094 case SECCLASS_DCCP_SOCKET:
4095 node_perm = DCCP_SOCKET__NODE_BIND;
4096 break;
4097
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 default:
4099 node_perm = RAWIP_SOCKET__NODE_BIND;
4100 break;
4101 }
Eric Paris828dfe12008-04-17 13:17:49 -04004102
Paul Moore224dfbd2008-01-29 08:38:13 -05004103 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 if (err)
4105 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004106
Eric Paris50c205f2012-04-04 15:01:43 -04004107 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004108 ad.u.net = &net;
4109 ad.u.net->sport = htons(snum);
4110 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
4112 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004113 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 else
Eric Paris48c62af2012-04-02 13:15:44 -04004115 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
Paul Moore253bfae2010-04-22 14:46:19 -04004117 err = avc_has_perm(sksec->sid, sid,
4118 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 if (err)
4120 goto out;
4121 }
4122out:
4123 return err;
4124}
4125
4126static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4127{
Paul Moore014ab192008-10-10 10:16:33 -04004128 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004129 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 int err;
4131
Paul Moore253bfae2010-04-22 14:46:19 -04004132 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 if (err)
4134 return err;
4135
4136 /*
James Morris2ee92d42006-11-13 16:09:01 -08004137 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 */
Paul Moore253bfae2010-04-22 14:46:19 -04004139 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4140 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004141 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004142 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 struct sockaddr_in *addr4 = NULL;
4144 struct sockaddr_in6 *addr6 = NULL;
4145 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004146 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
4148 if (sk->sk_family == PF_INET) {
4149 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004150 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 return -EINVAL;
4152 snum = ntohs(addr4->sin_port);
4153 } else {
4154 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004155 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 return -EINVAL;
4157 snum = ntohs(addr6->sin6_port);
4158 }
4159
Paul Moore3e112172008-04-10 10:48:14 -04004160 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 if (err)
4162 goto out;
4163
Paul Moore253bfae2010-04-22 14:46:19 -04004164 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004165 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4166
Eric Paris50c205f2012-04-04 15:01:43 -04004167 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004168 ad.u.net = &net;
4169 ad.u.net->dport = htons(snum);
4170 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004171 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 if (err)
4173 goto out;
4174 }
4175
Paul Moore014ab192008-10-10 10:16:33 -04004176 err = selinux_netlbl_socket_connect(sk, address);
4177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178out:
4179 return err;
4180}
4181
4182static int selinux_socket_listen(struct socket *sock, int backlog)
4183{
Paul Moore253bfae2010-04-22 14:46:19 -04004184 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185}
4186
4187static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4188{
4189 int err;
4190 struct inode_security_struct *isec;
4191 struct inode_security_struct *newisec;
4192
Paul Moore253bfae2010-04-22 14:46:19 -04004193 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 if (err)
4195 return err;
4196
4197 newisec = SOCK_INODE(newsock)->i_security;
4198
4199 isec = SOCK_INODE(sock)->i_security;
4200 newisec->sclass = isec->sclass;
4201 newisec->sid = isec->sid;
4202 newisec->initialized = 1;
4203
4204 return 0;
4205}
4206
4207static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004208 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209{
Paul Moore253bfae2010-04-22 14:46:19 -04004210 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211}
4212
4213static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4214 int size, int flags)
4215{
Paul Moore253bfae2010-04-22 14:46:19 -04004216 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217}
4218
4219static int selinux_socket_getsockname(struct socket *sock)
4220{
Paul Moore253bfae2010-04-22 14:46:19 -04004221 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222}
4223
4224static int selinux_socket_getpeername(struct socket *sock)
4225{
Paul Moore253bfae2010-04-22 14:46:19 -04004226 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227}
4228
Eric Paris828dfe12008-04-17 13:17:49 -04004229static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
Paul Mooref8687af2006-10-30 15:22:15 -08004231 int err;
4232
Paul Moore253bfae2010-04-22 14:46:19 -04004233 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004234 if (err)
4235 return err;
4236
4237 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238}
4239
4240static int selinux_socket_getsockopt(struct socket *sock, int level,
4241 int optname)
4242{
Paul Moore253bfae2010-04-22 14:46:19 -04004243 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244}
4245
4246static int selinux_socket_shutdown(struct socket *sock, int how)
4247{
Paul Moore253bfae2010-04-22 14:46:19 -04004248 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249}
4250
David S. Miller3610cda2011-01-05 15:38:53 -08004251static int selinux_socket_unix_stream_connect(struct sock *sock,
4252 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 struct sock *newsk)
4254{
David S. Miller3610cda2011-01-05 15:38:53 -08004255 struct sk_security_struct *sksec_sock = sock->sk_security;
4256 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004257 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004258 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004259 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 int err;
4261
Eric Paris50c205f2012-04-04 15:01:43 -04004262 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004263 ad.u.net = &net;
4264 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
Paul Moore4d1e2452010-04-22 14:46:18 -04004266 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4267 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4269 if (err)
4270 return err;
4271
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004273 sksec_new->peer_sid = sksec_sock->sid;
4274 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4275 &sksec_new->sid);
4276 if (err)
4277 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004278
Paul Moore4d1e2452010-04-22 14:46:18 -04004279 /* connecting socket */
4280 sksec_sock->peer_sid = sksec_new->sid;
4281
4282 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283}
4284
4285static int selinux_socket_unix_may_send(struct socket *sock,
4286 struct socket *other)
4287{
Paul Moore253bfae2010-04-22 14:46:19 -04004288 struct sk_security_struct *ssec = sock->sk->sk_security;
4289 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004290 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004291 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
Eric Paris50c205f2012-04-04 15:01:43 -04004293 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004294 ad.u.net = &net;
4295 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296
Paul Moore253bfae2010-04-22 14:46:19 -04004297 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4298 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299}
4300
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004301static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4302 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004303 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004304{
4305 int err;
4306 u32 if_sid;
4307 u32 node_sid;
4308
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004309 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004310 if (err)
4311 return err;
4312 err = avc_has_perm(peer_sid, if_sid,
4313 SECCLASS_NETIF, NETIF__INGRESS, ad);
4314 if (err)
4315 return err;
4316
4317 err = sel_netnode_sid(addrp, family, &node_sid);
4318 if (err)
4319 return err;
4320 return avc_has_perm(peer_sid, node_sid,
4321 SECCLASS_NODE, NODE__RECVFROM, ad);
4322}
4323
Paul Moore220deb92008-01-29 08:38:23 -05004324static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004325 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004326{
Paul Moore277d3422008-12-31 12:54:11 -05004327 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004328 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004329 u32 sk_sid = sksec->sid;
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,};
Paul Moored8395c82008-10-10 10:16:30 -04004332 char *addrp;
4333
Eric Paris50c205f2012-04-04 15:01:43 -04004334 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004335 ad.u.net = &net;
4336 ad.u.net->netif = skb->skb_iif;
4337 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004338 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4339 if (err)
4340 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004341
Paul Moore58bfbb52009-03-27 17:10:41 -04004342 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004343 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004344 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004345 if (err)
4346 return err;
4347 }
Paul Moore220deb92008-01-29 08:38:23 -05004348
Steffen Klassertb9679a72011-02-23 12:55:21 +01004349 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4350 if (err)
4351 return err;
4352 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004353
James Morris4e5ab4c2006-06-09 00:33:33 -07004354 return err;
4355}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004356
James Morris4e5ab4c2006-06-09 00:33:33 -07004357static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4358{
Paul Moore220deb92008-01-29 08:38:23 -05004359 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004360 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004361 u16 family = sk->sk_family;
4362 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004363 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004364 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004365 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004366 u8 secmark_active;
4367 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004368
James Morris4e5ab4c2006-06-09 00:33:33 -07004369 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004370 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004371
4372 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004373 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004374 family = PF_INET;
4375
Paul Moored8395c82008-10-10 10:16:30 -04004376 /* If any sort of compatibility mode is enabled then handoff processing
4377 * to the selinux_sock_rcv_skb_compat() function to deal with the
4378 * special handling. We do this in an attempt to keep this function
4379 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004380 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004381 return selinux_sock_rcv_skb_compat(sk, skb, family);
4382
4383 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004384 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004385 if (!secmark_active && !peerlbl_active)
4386 return 0;
4387
Eric Paris50c205f2012-04-04 15:01:43 -04004388 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004389 ad.u.net = &net;
4390 ad.u.net->netif = skb->skb_iif;
4391 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004392 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004393 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004394 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004395
Paul Moored8395c82008-10-10 10:16:30 -04004396 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004397 u32 peer_sid;
4398
4399 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4400 if (err)
4401 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004402 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4403 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004404 if (err) {
4405 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004406 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004407 }
Paul Moored621d352008-01-29 08:43:36 -05004408 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4409 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004410 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004411 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004412 return err;
4413 }
Paul Moored621d352008-01-29 08:43:36 -05004414 }
4415
Paul Moored8395c82008-10-10 10:16:30 -04004416 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004417 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4418 PACKET__RECV, &ad);
4419 if (err)
4420 return err;
4421 }
4422
Paul Moored621d352008-01-29 08:43:36 -05004423 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424}
4425
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004426static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4427 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428{
4429 int err = 0;
4430 char *scontext;
4431 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004432 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004433 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Paul Moore253bfae2010-04-22 14:46:19 -04004435 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4436 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004437 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004438 if (peer_sid == SECSID_NULL)
4439 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004441 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004443 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
4445 if (scontext_len > len) {
4446 err = -ERANGE;
4447 goto out_len;
4448 }
4449
4450 if (copy_to_user(optval, scontext, scontext_len))
4451 err = -EFAULT;
4452
4453out_len:
4454 if (put_user(scontext_len, optlen))
4455 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 return err;
4458}
4459
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004460static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004461{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004462 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004463 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004464
Paul Mooreaa862902008-10-10 10:16:29 -04004465 if (skb && skb->protocol == htons(ETH_P_IP))
4466 family = PF_INET;
4467 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4468 family = PF_INET6;
4469 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004470 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004471 else
4472 goto out;
4473
4474 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004475 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004476 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004477 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004478
Paul Moore75e22912008-01-29 08:38:04 -05004479out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004480 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004481 if (peer_secid == SECSID_NULL)
4482 return -EINVAL;
4483 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004484}
4485
Al Viro7d877f32005-10-21 03:20:43 -04004486static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487{
Paul Moore84914b72010-04-22 14:46:18 -04004488 struct sk_security_struct *sksec;
4489
4490 sksec = kzalloc(sizeof(*sksec), priority);
4491 if (!sksec)
4492 return -ENOMEM;
4493
4494 sksec->peer_sid = SECINITSID_UNLABELED;
4495 sksec->sid = SECINITSID_UNLABELED;
4496 selinux_netlbl_sk_security_reset(sksec);
4497 sk->sk_security = sksec;
4498
4499 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500}
4501
4502static void selinux_sk_free_security(struct sock *sk)
4503{
Paul Moore84914b72010-04-22 14:46:18 -04004504 struct sk_security_struct *sksec = sk->sk_security;
4505
4506 sk->sk_security = NULL;
4507 selinux_netlbl_sk_security_free(sksec);
4508 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509}
4510
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004511static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4512{
Eric Parisdd3e7832010-04-07 15:08:46 -04004513 struct sk_security_struct *sksec = sk->sk_security;
4514 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004515
Eric Parisdd3e7832010-04-07 15:08:46 -04004516 newsksec->sid = sksec->sid;
4517 newsksec->peer_sid = sksec->peer_sid;
4518 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004519
Eric Parisdd3e7832010-04-07 15:08:46 -04004520 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004521}
4522
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004523static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004524{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004525 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004526 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004527 else {
4528 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004529
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004530 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004531 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004532}
4533
Eric Paris828dfe12008-04-17 13:17:49 -04004534static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004535{
4536 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4537 struct sk_security_struct *sksec = sk->sk_security;
4538
Paul Moore2873ead2014-07-28 10:42:48 -04004539 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4540 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004541 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004542 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004543}
4544
Adrian Bunk9a673e52006-08-15 00:03:53 -07004545static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4546 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004547{
4548 struct sk_security_struct *sksec = sk->sk_security;
4549 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004550 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004551 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004552 u32 peersid;
4553
Paul Mooreaa862902008-10-10 10:16:29 -04004554 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004555 if (err)
4556 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004557 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4558 if (err)
4559 return err;
4560 req->secid = connsid;
4561 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004562
Paul Moore389fb8002009-03-27 17:10:34 -04004563 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004564}
4565
Adrian Bunk9a673e52006-08-15 00:03:53 -07004566static void selinux_inet_csk_clone(struct sock *newsk,
4567 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004568{
4569 struct sk_security_struct *newsksec = newsk->sk_security;
4570
4571 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004572 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004573 /* NOTE: Ideally, we should also get the isec->sid for the
4574 new socket in sync, but we don't have the isec available yet.
4575 So we will wait until sock_graft to do it, by which
4576 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004577
Paul Moore9f2ad662006-11-17 17:38:53 -05004578 /* We don't need to take any sort of lock here as we are the only
4579 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004580 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581}
4582
Paul Moore014ab192008-10-10 10:16:33 -04004583static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004584{
Paul Mooreaa862902008-10-10 10:16:29 -04004585 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004586 struct sk_security_struct *sksec = sk->sk_security;
4587
Paul Mooreaa862902008-10-10 10:16:29 -04004588 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4589 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4590 family = PF_INET;
4591
4592 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004593}
4594
Eric Paris2606fd12010-10-13 16:24:41 -04004595static int selinux_secmark_relabel_packet(u32 sid)
4596{
4597 const struct task_security_struct *__tsec;
4598 u32 tsid;
4599
4600 __tsec = current_security();
4601 tsid = __tsec->sid;
4602
4603 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4604}
4605
4606static void selinux_secmark_refcount_inc(void)
4607{
4608 atomic_inc(&selinux_secmark_refcount);
4609}
4610
4611static void selinux_secmark_refcount_dec(void)
4612{
4613 atomic_dec(&selinux_secmark_refcount);
4614}
4615
Adrian Bunk9a673e52006-08-15 00:03:53 -07004616static void selinux_req_classify_flow(const struct request_sock *req,
4617 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004618{
David S. Miller1d28f422011-03-12 00:29:39 -05004619 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004620}
4621
Paul Moore5dbbaf22013-01-14 07:12:19 +00004622static int selinux_tun_dev_alloc_security(void **security)
4623{
4624 struct tun_security_struct *tunsec;
4625
4626 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4627 if (!tunsec)
4628 return -ENOMEM;
4629 tunsec->sid = current_sid();
4630
4631 *security = tunsec;
4632 return 0;
4633}
4634
4635static void selinux_tun_dev_free_security(void *security)
4636{
4637 kfree(security);
4638}
4639
Paul Mooreed6d76e2009-08-28 18:12:49 -04004640static int selinux_tun_dev_create(void)
4641{
4642 u32 sid = current_sid();
4643
4644 /* we aren't taking into account the "sockcreate" SID since the socket
4645 * that is being created here is not a socket in the traditional sense,
4646 * instead it is a private sock, accessible only to the kernel, and
4647 * representing a wide range of network traffic spanning multiple
4648 * connections unlike traditional sockets - check the TUN driver to
4649 * get a better understanding of why this socket is special */
4650
4651 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4652 NULL);
4653}
4654
Paul Moore5dbbaf22013-01-14 07:12:19 +00004655static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004656{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004657 struct tun_security_struct *tunsec = security;
4658
4659 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4660 TUN_SOCKET__ATTACH_QUEUE, NULL);
4661}
4662
4663static int selinux_tun_dev_attach(struct sock *sk, void *security)
4664{
4665 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004666 struct sk_security_struct *sksec = sk->sk_security;
4667
4668 /* we don't currently perform any NetLabel based labeling here and it
4669 * isn't clear that we would want to do so anyway; while we could apply
4670 * labeling without the support of the TUN user the resulting labeled
4671 * traffic from the other end of the connection would almost certainly
4672 * cause confusion to the TUN user that had no idea network labeling
4673 * protocols were being used */
4674
Paul Moore5dbbaf22013-01-14 07:12:19 +00004675 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004676 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004677
4678 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004679}
4680
Paul Moore5dbbaf22013-01-14 07:12:19 +00004681static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004682{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004683 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004684 u32 sid = current_sid();
4685 int err;
4686
Paul Moore5dbbaf22013-01-14 07:12:19 +00004687 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004688 TUN_SOCKET__RELABELFROM, NULL);
4689 if (err)
4690 return err;
4691 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4692 TUN_SOCKET__RELABELTO, NULL);
4693 if (err)
4694 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004695 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004696
4697 return 0;
4698}
4699
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4701{
4702 int err = 0;
4703 u32 perm;
4704 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004705 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004706
Hong zhi guo77954982013-03-27 06:49:35 +00004707 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708 err = -EINVAL;
4709 goto out;
4710 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004711 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004712
Paul Moore253bfae2010-04-22 14:46:19 -04004713 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714 if (err) {
4715 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004716 printk(KERN_WARNING
4717 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004718 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4719 sk->sk_protocol, nlh->nlmsg_type,
4720 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004721 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722 err = 0;
4723 }
4724
4725 /* Ignore */
4726 if (err == -ENOENT)
4727 err = 0;
4728 goto out;
4729 }
4730
Paul Moore253bfae2010-04-22 14:46:19 -04004731 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732out:
4733 return err;
4734}
4735
4736#ifdef CONFIG_NETFILTER
4737
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004738static unsigned int selinux_ip_forward(struct sk_buff *skb,
4739 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004740 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741{
Paul Mooredfaebe92008-10-10 10:16:31 -04004742 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004743 char *addrp;
4744 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004745 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004746 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004747 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004748 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004749 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004750
Paul Mooreeffad8d2008-01-29 08:49:27 -05004751 if (!selinux_policycap_netpeer)
4752 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004753
Paul Mooreeffad8d2008-01-29 08:49:27 -05004754 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004755 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004756 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004757 if (!secmark_active && !peerlbl_active)
4758 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004759
Paul Moored8395c82008-10-10 10:16:30 -04004760 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4761 return NF_DROP;
4762
Eric Paris50c205f2012-04-04 15:01:43 -04004763 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004764 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004765 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004766 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004767 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4768 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769
Paul Mooredfaebe92008-10-10 10:16:31 -04004770 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004771 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4772 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004773 if (err) {
4774 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004775 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004776 }
4777 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778
4779 if (secmark_active)
4780 if (avc_has_perm(peer_sid, skb->secmark,
4781 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4782 return NF_DROP;
4783
Paul Moore948bf852008-10-10 10:16:32 -04004784 if (netlbl_active)
4785 /* we do this in the FORWARD path and not the POST_ROUTING
4786 * path because we want to make sure we apply the necessary
4787 * labeling before IPsec is applied so we can leverage AH
4788 * protection */
4789 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4790 return NF_DROP;
4791
Paul Mooreeffad8d2008-01-29 08:49:27 -05004792 return NF_ACCEPT;
4793}
4794
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004795static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004796 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004797 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004798{
David S. Miller238e54c2015-04-03 20:32:56 -04004799 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004800}
4801
4802#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004803static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004804 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004805 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004806{
David S. Miller238e54c2015-04-03 20:32:56 -04004807 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004808}
4809#endif /* IPV6 */
4810
Paul Moore948bf852008-10-10 10:16:32 -04004811static unsigned int selinux_ip_output(struct sk_buff *skb,
4812 u16 family)
4813{
Paul Moore47180062013-12-04 16:10:45 -05004814 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004815 u32 sid;
4816
4817 if (!netlbl_enabled())
4818 return NF_ACCEPT;
4819
4820 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4821 * because we want to make sure we apply the necessary labeling
4822 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004823 sk = skb->sk;
4824 if (sk) {
4825 struct sk_security_struct *sksec;
4826
4827 if (sk->sk_state == TCP_LISTEN)
4828 /* if the socket is the listening state then this
4829 * packet is a SYN-ACK packet which means it needs to
4830 * be labeled based on the connection/request_sock and
4831 * not the parent socket. unfortunately, we can't
4832 * lookup the request_sock yet as it isn't queued on
4833 * the parent socket until after the SYN-ACK is sent.
4834 * the "solution" is to simply pass the packet as-is
4835 * as any IP option based labeling should be copied
4836 * from the initial connection request (in the IP
4837 * layer). it is far from ideal, but until we get a
4838 * security label in the packet itself this is the
4839 * best we can do. */
4840 return NF_ACCEPT;
4841
4842 /* standard practice, label using the parent socket */
4843 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004844 sid = sksec->sid;
4845 } else
4846 sid = SECINITSID_KERNEL;
4847 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4848 return NF_DROP;
4849
4850 return NF_ACCEPT;
4851}
4852
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004853static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004854 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004855 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004856{
4857 return selinux_ip_output(skb, PF_INET);
4858}
4859
Paul Mooreeffad8d2008-01-29 08:49:27 -05004860static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4861 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004862 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004863{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004864 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004865 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004866 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004867 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004868 char *addrp;
4869 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004870
Paul Mooreeffad8d2008-01-29 08:49:27 -05004871 if (sk == NULL)
4872 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004873 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004874
Eric Paris50c205f2012-04-04 15:01:43 -04004875 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004876 ad.u.net = &net;
4877 ad.u.net->netif = ifindex;
4878 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004879 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4880 return NF_DROP;
4881
Paul Moore58bfbb52009-03-27 17:10:41 -04004882 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004883 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004884 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004885 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004886
Steffen Klassertb9679a72011-02-23 12:55:21 +01004887 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4888 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004889
Paul Mooreeffad8d2008-01-29 08:49:27 -05004890 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891}
4892
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004893static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4894 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004895 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004897 u32 secmark_perm;
4898 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004899 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004900 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004901 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004902 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004903 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004904 u8 secmark_active;
4905 u8 peerlbl_active;
4906
Paul Mooreeffad8d2008-01-29 08:49:27 -05004907 /* If any sort of compatibility mode is enabled then handoff processing
4908 * to the selinux_ip_postroute_compat() function to deal with the
4909 * special handling. We do this in an attempt to keep this function
4910 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004911 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004912 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004913
Paul Mooreeffad8d2008-01-29 08:49:27 -05004914 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004915 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004916 if (!secmark_active && !peerlbl_active)
4917 return NF_ACCEPT;
4918
Paul Mooreeffad8d2008-01-29 08:49:27 -05004919 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004920
Paul Mooreeffad8d2008-01-29 08:49:27 -05004921#ifdef CONFIG_XFRM
4922 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4923 * packet transformation so allow the packet to pass without any checks
4924 * since we'll have another chance to perform access control checks
4925 * when the packet is on it's final way out.
4926 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004927 * is NULL, in this case go ahead and apply access control.
4928 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4929 * TCP listening state we cannot wait until the XFRM processing
4930 * is done as we will miss out on the SA label if we do;
4931 * unfortunately, this means more work, but it is only once per
4932 * connection. */
4933 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4934 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004935 return NF_ACCEPT;
4936#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004937
Paul Moored8395c82008-10-10 10:16:30 -04004938 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05004939 /* Without an associated socket the packet is either coming
4940 * from the kernel or it is being forwarded; check the packet
4941 * to determine which and if the packet is being forwarded
4942 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004943 if (skb->skb_iif) {
4944 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004945 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004946 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004947 } else {
4948 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004949 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004950 }
Paul Moore446b8022013-12-04 16:10:51 -05004951 } else if (sk->sk_state == TCP_LISTEN) {
4952 /* Locally generated packet but the associated socket is in the
4953 * listening state which means this is a SYN-ACK packet. In
4954 * this particular case the correct security label is assigned
4955 * to the connection/request_sock but unfortunately we can't
4956 * query the request_sock as it isn't queued on the parent
4957 * socket until after the SYN-ACK packet is sent; the only
4958 * viable choice is to regenerate the label like we do in
4959 * selinux_inet_conn_request(). See also selinux_ip_output()
4960 * for similar problems. */
4961 u32 skb_sid;
4962 struct sk_security_struct *sksec = sk->sk_security;
4963 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4964 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05004965 /* At this point, if the returned skb peerlbl is SECSID_NULL
4966 * and the packet has been through at least one XFRM
4967 * transformation then we must be dealing with the "final"
4968 * form of labeled IPsec packet; since we've already applied
4969 * all of our access controls on this packet we can safely
4970 * pass the packet. */
4971 if (skb_sid == SECSID_NULL) {
4972 switch (family) {
4973 case PF_INET:
4974 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4975 return NF_ACCEPT;
4976 break;
4977 case PF_INET6:
4978 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4979 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04004980 break;
Paul Moorec0828e52013-12-10 14:58:01 -05004981 default:
4982 return NF_DROP_ERR(-ECONNREFUSED);
4983 }
4984 }
Paul Moore446b8022013-12-04 16:10:51 -05004985 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4986 return NF_DROP;
4987 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004988 } else {
Paul Moore446b8022013-12-04 16:10:51 -05004989 /* Locally generated packet, fetch the security label from the
4990 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004991 struct sk_security_struct *sksec = sk->sk_security;
4992 peer_sid = sksec->sid;
4993 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004994 }
4995
Eric Paris50c205f2012-04-04 15:01:43 -04004996 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004997 ad.u.net = &net;
4998 ad.u.net->netif = ifindex;
4999 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005000 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005001 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005002
Paul Mooreeffad8d2008-01-29 08:49:27 -05005003 if (secmark_active)
5004 if (avc_has_perm(peer_sid, skb->secmark,
5005 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005006 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005007
5008 if (peerlbl_active) {
5009 u32 if_sid;
5010 u32 node_sid;
5011
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005012 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005013 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005014 if (avc_has_perm(peer_sid, if_sid,
5015 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005016 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005017
5018 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005019 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005020 if (avc_has_perm(peer_sid, node_sid,
5021 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005022 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005023 }
5024
5025 return NF_ACCEPT;
5026}
5027
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005028static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005029 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005030 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005031{
David S. Miller238e54c2015-04-03 20:32:56 -04005032 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033}
5034
5035#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005036static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005037 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005038 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039{
David S. Miller238e54c2015-04-03 20:32:56 -04005040 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042#endif /* IPV6 */
5043
5044#endif /* CONFIG_NETFILTER */
5045
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5047{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005048 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049}
5050
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051static int ipc_alloc_security(struct task_struct *task,
5052 struct kern_ipc_perm *perm,
5053 u16 sclass)
5054{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005056 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057
James Morris89d155e2005-10-30 14:59:21 -08005058 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059 if (!isec)
5060 return -ENOMEM;
5061
David Howells275bb412008-11-14 10:39:19 +11005062 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005064 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 perm->security = isec;
5066
5067 return 0;
5068}
5069
5070static void ipc_free_security(struct kern_ipc_perm *perm)
5071{
5072 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073 perm->security = NULL;
5074 kfree(isec);
5075}
5076
5077static int msg_msg_alloc_security(struct msg_msg *msg)
5078{
5079 struct msg_security_struct *msec;
5080
James Morris89d155e2005-10-30 14:59:21 -08005081 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 if (!msec)
5083 return -ENOMEM;
5084
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 msec->sid = SECINITSID_UNLABELED;
5086 msg->security = msec;
5087
5088 return 0;
5089}
5090
5091static void msg_msg_free_security(struct msg_msg *msg)
5092{
5093 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094
5095 msg->security = NULL;
5096 kfree(msec);
5097}
5098
5099static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005100 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005103 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005104 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 isec = ipc_perms->security;
5107
Eric Paris50c205f2012-04-04 15:01:43 -04005108 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 ad.u.ipc_id = ipc_perms->key;
5110
David Howells275bb412008-11-14 10:39:19 +11005111 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112}
5113
5114static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5115{
5116 return msg_msg_alloc_security(msg);
5117}
5118
5119static void selinux_msg_msg_free_security(struct msg_msg *msg)
5120{
5121 msg_msg_free_security(msg);
5122}
5123
5124/* message queue security operations */
5125static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5126{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005128 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005129 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 int rc;
5131
5132 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5133 if (rc)
5134 return rc;
5135
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136 isec = msq->q_perm.security;
5137
Eric Paris50c205f2012-04-04 15:01:43 -04005138 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005139 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
David Howells275bb412008-11-14 10:39:19 +11005141 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142 MSGQ__CREATE, &ad);
5143 if (rc) {
5144 ipc_free_security(&msq->q_perm);
5145 return rc;
5146 }
5147 return 0;
5148}
5149
5150static void selinux_msg_queue_free_security(struct msg_queue *msq)
5151{
5152 ipc_free_security(&msq->q_perm);
5153}
5154
5155static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5156{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005158 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005159 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Linus Torvalds1da177e2005-04-16 15:20:36 -07005161 isec = msq->q_perm.security;
5162
Eric Paris50c205f2012-04-04 15:01:43 -04005163 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164 ad.u.ipc_id = msq->q_perm.key;
5165
David Howells275bb412008-11-14 10:39:19 +11005166 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167 MSGQ__ASSOCIATE, &ad);
5168}
5169
5170static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5171{
5172 int err;
5173 int perms;
5174
Eric Paris828dfe12008-04-17 13:17:49 -04005175 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176 case IPC_INFO:
5177 case MSG_INFO:
5178 /* No specific object, just general system-wide information. */
5179 return task_has_system(current, SYSTEM__IPC_INFO);
5180 case IPC_STAT:
5181 case MSG_STAT:
5182 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5183 break;
5184 case IPC_SET:
5185 perms = MSGQ__SETATTR;
5186 break;
5187 case IPC_RMID:
5188 perms = MSGQ__DESTROY;
5189 break;
5190 default:
5191 return 0;
5192 }
5193
Stephen Smalley6af963f2005-05-01 08:58:39 -07005194 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195 return err;
5196}
5197
5198static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5199{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 struct ipc_security_struct *isec;
5201 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005202 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005203 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 int rc;
5205
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 isec = msq->q_perm.security;
5207 msec = msg->security;
5208
5209 /*
5210 * First time through, need to assign label to the message
5211 */
5212 if (msec->sid == SECINITSID_UNLABELED) {
5213 /*
5214 * Compute new sid based on current process and
5215 * message queue this message will be stored in
5216 */
David Howells275bb412008-11-14 10:39:19 +11005217 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005218 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219 if (rc)
5220 return rc;
5221 }
5222
Eric Paris50c205f2012-04-04 15:01:43 -04005223 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 ad.u.ipc_id = msq->q_perm.key;
5225
5226 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005227 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228 MSGQ__WRITE, &ad);
5229 if (!rc)
5230 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005231 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5232 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005233 if (!rc)
5234 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005235 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5236 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
5238 return rc;
5239}
5240
5241static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5242 struct task_struct *target,
5243 long type, int mode)
5244{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 struct ipc_security_struct *isec;
5246 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005247 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005248 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 int rc;
5250
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 isec = msq->q_perm.security;
5252 msec = msg->security;
5253
Eric Paris50c205f2012-04-04 15:01:43 -04005254 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005255 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256
David Howells275bb412008-11-14 10:39:19 +11005257 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 SECCLASS_MSGQ, MSGQ__READ, &ad);
5259 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005260 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261 SECCLASS_MSG, MSG__RECEIVE, &ad);
5262 return rc;
5263}
5264
5265/* Shared Memory security operations */
5266static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5267{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005269 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005270 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 int rc;
5272
5273 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5274 if (rc)
5275 return rc;
5276
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 isec = shp->shm_perm.security;
5278
Eric Paris50c205f2012-04-04 15:01:43 -04005279 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005280 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
David Howells275bb412008-11-14 10:39:19 +11005282 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283 SHM__CREATE, &ad);
5284 if (rc) {
5285 ipc_free_security(&shp->shm_perm);
5286 return rc;
5287 }
5288 return 0;
5289}
5290
5291static void selinux_shm_free_security(struct shmid_kernel *shp)
5292{
5293 ipc_free_security(&shp->shm_perm);
5294}
5295
5296static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5297{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005299 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005300 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302 isec = shp->shm_perm.security;
5303
Eric Paris50c205f2012-04-04 15:01:43 -04005304 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305 ad.u.ipc_id = shp->shm_perm.key;
5306
David Howells275bb412008-11-14 10:39:19 +11005307 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308 SHM__ASSOCIATE, &ad);
5309}
5310
5311/* Note, at this point, shp is locked down */
5312static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5313{
5314 int perms;
5315 int err;
5316
Eric Paris828dfe12008-04-17 13:17:49 -04005317 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318 case IPC_INFO:
5319 case SHM_INFO:
5320 /* No specific object, just general system-wide information. */
5321 return task_has_system(current, SYSTEM__IPC_INFO);
5322 case IPC_STAT:
5323 case SHM_STAT:
5324 perms = SHM__GETATTR | SHM__ASSOCIATE;
5325 break;
5326 case IPC_SET:
5327 perms = SHM__SETATTR;
5328 break;
5329 case SHM_LOCK:
5330 case SHM_UNLOCK:
5331 perms = SHM__LOCK;
5332 break;
5333 case IPC_RMID:
5334 perms = SHM__DESTROY;
5335 break;
5336 default:
5337 return 0;
5338 }
5339
Stephen Smalley6af963f2005-05-01 08:58:39 -07005340 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 return err;
5342}
5343
5344static int selinux_shm_shmat(struct shmid_kernel *shp,
5345 char __user *shmaddr, int shmflg)
5346{
5347 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348
5349 if (shmflg & SHM_RDONLY)
5350 perms = SHM__READ;
5351 else
5352 perms = SHM__READ | SHM__WRITE;
5353
Stephen Smalley6af963f2005-05-01 08:58:39 -07005354 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355}
5356
5357/* Semaphore security operations */
5358static int selinux_sem_alloc_security(struct sem_array *sma)
5359{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005360 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005361 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005362 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363 int rc;
5364
5365 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5366 if (rc)
5367 return rc;
5368
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369 isec = sma->sem_perm.security;
5370
Eric Paris50c205f2012-04-04 15:01:43 -04005371 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005372 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373
David Howells275bb412008-11-14 10:39:19 +11005374 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 SEM__CREATE, &ad);
5376 if (rc) {
5377 ipc_free_security(&sma->sem_perm);
5378 return rc;
5379 }
5380 return 0;
5381}
5382
5383static void selinux_sem_free_security(struct sem_array *sma)
5384{
5385 ipc_free_security(&sma->sem_perm);
5386}
5387
5388static int selinux_sem_associate(struct sem_array *sma, int semflg)
5389{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005391 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005392 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394 isec = sma->sem_perm.security;
5395
Eric Paris50c205f2012-04-04 15:01:43 -04005396 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397 ad.u.ipc_id = sma->sem_perm.key;
5398
David Howells275bb412008-11-14 10:39:19 +11005399 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400 SEM__ASSOCIATE, &ad);
5401}
5402
5403/* Note, at this point, sma is locked down */
5404static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5405{
5406 int err;
5407 u32 perms;
5408
Eric Paris828dfe12008-04-17 13:17:49 -04005409 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410 case IPC_INFO:
5411 case SEM_INFO:
5412 /* No specific object, just general system-wide information. */
5413 return task_has_system(current, SYSTEM__IPC_INFO);
5414 case GETPID:
5415 case GETNCNT:
5416 case GETZCNT:
5417 perms = SEM__GETATTR;
5418 break;
5419 case GETVAL:
5420 case GETALL:
5421 perms = SEM__READ;
5422 break;
5423 case SETVAL:
5424 case SETALL:
5425 perms = SEM__WRITE;
5426 break;
5427 case IPC_RMID:
5428 perms = SEM__DESTROY;
5429 break;
5430 case IPC_SET:
5431 perms = SEM__SETATTR;
5432 break;
5433 case IPC_STAT:
5434 case SEM_STAT:
5435 perms = SEM__GETATTR | SEM__ASSOCIATE;
5436 break;
5437 default:
5438 return 0;
5439 }
5440
Stephen Smalley6af963f2005-05-01 08:58:39 -07005441 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005442 return err;
5443}
5444
5445static int selinux_sem_semop(struct sem_array *sma,
5446 struct sembuf *sops, unsigned nsops, int alter)
5447{
5448 u32 perms;
5449
5450 if (alter)
5451 perms = SEM__READ | SEM__WRITE;
5452 else
5453 perms = SEM__READ;
5454
Stephen Smalley6af963f2005-05-01 08:58:39 -07005455 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456}
5457
5458static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5459{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460 u32 av = 0;
5461
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462 av = 0;
5463 if (flag & S_IRUGO)
5464 av |= IPC__UNIX_READ;
5465 if (flag & S_IWUGO)
5466 av |= IPC__UNIX_WRITE;
5467
5468 if (av == 0)
5469 return 0;
5470
Stephen Smalley6af963f2005-05-01 08:58:39 -07005471 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472}
5473
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005474static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5475{
5476 struct ipc_security_struct *isec = ipcp->security;
5477 *secid = isec->sid;
5478}
5479
Eric Paris828dfe12008-04-17 13:17:49 -04005480static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481{
5482 if (inode)
5483 inode_doinit_with_dentry(inode, dentry);
5484}
5485
5486static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005487 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488{
David Howells275bb412008-11-14 10:39:19 +11005489 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005490 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005492 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493
5494 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005495 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005496 if (error)
5497 return error;
5498 }
5499
David Howells275bb412008-11-14 10:39:19 +11005500 rcu_read_lock();
5501 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502
5503 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005504 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005506 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005508 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005510 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005511 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005512 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005513 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005514 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 else
David Howells275bb412008-11-14 10:39:19 +11005516 goto invalid;
5517 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518
5519 if (!sid)
5520 return 0;
5521
Al Viro04ff9702007-03-12 16:17:58 +00005522 error = security_sid_to_context(sid, value, &len);
5523 if (error)
5524 return error;
5525 return len;
David Howells275bb412008-11-14 10:39:19 +11005526
5527invalid:
5528 rcu_read_unlock();
5529 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530}
5531
5532static int selinux_setprocattr(struct task_struct *p,
5533 char *name, void *value, size_t size)
5534{
5535 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005536 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005537 struct cred *new;
5538 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539 int error;
5540 char *str = value;
5541
5542 if (current != p) {
5543 /* SELinux only allows a process to change its own
5544 security attributes. */
5545 return -EACCES;
5546 }
5547
5548 /*
5549 * Basic control over ability to set these attributes at all.
5550 * current == p, but we'll pass them separately in case the
5551 * above restriction is ever removed.
5552 */
5553 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005554 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005556 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005557 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005558 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005559 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005560 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005562 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563 else
5564 error = -EINVAL;
5565 if (error)
5566 return error;
5567
5568 /* Obtain a SID for the context, if one was specified. */
5569 if (size && str[1] && str[1] != '\n') {
5570 if (str[size-1] == '\n') {
5571 str[size-1] = 0;
5572 size--;
5573 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005574 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005575 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005576 if (!capable(CAP_MAC_ADMIN)) {
5577 struct audit_buffer *ab;
5578 size_t audit_size;
5579
5580 /* We strip a nul only if it is at the end, otherwise the
5581 * context contains a nul and we should audit that */
5582 if (str[size - 1] == '\0')
5583 audit_size = size - 1;
5584 else
5585 audit_size = size;
5586 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5587 audit_log_format(ab, "op=fscreate invalid_context=");
5588 audit_log_n_untrustedstring(ab, value, audit_size);
5589 audit_log_end(ab);
5590
Stephen Smalley12b29f32008-05-07 13:03:20 -04005591 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005592 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005593 error = security_context_to_sid_force(value, size,
5594 &sid);
5595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 if (error)
5597 return error;
5598 }
5599
David Howellsd84f4f92008-11-14 10:39:23 +11005600 new = prepare_creds();
5601 if (!new)
5602 return -ENOMEM;
5603
Linus Torvalds1da177e2005-04-16 15:20:36 -07005604 /* Permission checking based on the specified context is
5605 performed during the actual operation (execve,
5606 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005607 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005608 checks and may_create for the file creation checks. The
5609 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005610 tsec = new->security;
5611 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005613 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005615 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005616 error = may_create_key(sid, p);
5617 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005618 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005619 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005620 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005621 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005622 } else if (!strcmp(name, "current")) {
5623 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005625 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005626
David Howellsd84f4f92008-11-14 10:39:23 +11005627 /* Only allow single threaded processes to change context */
5628 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005629 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005630 error = security_bounded_transition(tsec->sid, sid);
5631 if (error)
5632 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634
5635 /* Check permissions for the transition. */
5636 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005637 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005639 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640
5641 /* Check for ptracing, and update the task SID if ok.
5642 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005643 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005644 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005645 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005646 if (tracer)
5647 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005648 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649
David Howellsd84f4f92008-11-14 10:39:23 +11005650 if (tracer) {
5651 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5652 PROCESS__PTRACE, NULL);
5653 if (error)
5654 goto abort_change;
5655 }
5656
5657 tsec->sid = sid;
5658 } else {
5659 error = -EINVAL;
5660 goto abort_change;
5661 }
5662
5663 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005665
5666abort_change:
5667 abort_creds(new);
5668 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669}
5670
David Quigley746df9b2013-05-22 12:50:35 -04005671static int selinux_ismaclabel(const char *name)
5672{
5673 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5674}
5675
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005676static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5677{
5678 return security_sid_to_context(secid, secdata, seclen);
5679}
5680
David Howells7bf570d2008-04-29 20:52:51 +01005681static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005682{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005683 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005684}
5685
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005686static void selinux_release_secctx(char *secdata, u32 seclen)
5687{
Paul Moore088999e2007-08-01 11:12:58 -04005688 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005689}
5690
David P. Quigley1ee65e32009-09-03 14:25:57 -04005691/*
5692 * called with inode->i_mutex locked
5693 */
5694static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5695{
5696 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5697}
5698
5699/*
5700 * called with inode->i_mutex locked
5701 */
5702static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5703{
5704 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5705}
5706
5707static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5708{
5709 int len = 0;
5710 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5711 ctx, true);
5712 if (len < 0)
5713 return len;
5714 *ctxlen = len;
5715 return 0;
5716}
Michael LeMayd7200242006-06-22 14:47:17 -07005717#ifdef CONFIG_KEYS
5718
David Howellsd84f4f92008-11-14 10:39:23 +11005719static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005720 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005721{
David Howellsd84f4f92008-11-14 10:39:23 +11005722 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005723 struct key_security_struct *ksec;
5724
5725 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5726 if (!ksec)
5727 return -ENOMEM;
5728
David Howellsd84f4f92008-11-14 10:39:23 +11005729 tsec = cred->security;
5730 if (tsec->keycreate_sid)
5731 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005732 else
David Howellsd84f4f92008-11-14 10:39:23 +11005733 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005734
David Howells275bb412008-11-14 10:39:19 +11005735 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005736 return 0;
5737}
5738
5739static void selinux_key_free(struct key *k)
5740{
5741 struct key_security_struct *ksec = k->security;
5742
5743 k->security = NULL;
5744 kfree(ksec);
5745}
5746
5747static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005748 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005749 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005750{
5751 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005752 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005753 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005754
5755 /* if no specific permissions are requested, we skip the
5756 permission check. No serious, additional covert channels
5757 appear to be created. */
5758 if (perm == 0)
5759 return 0;
5760
David Howellsd84f4f92008-11-14 10:39:23 +11005761 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005762
5763 key = key_ref_to_ptr(key_ref);
5764 ksec = key->security;
5765
5766 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005767}
5768
David Howells70a5bb72008-04-29 01:01:26 -07005769static int selinux_key_getsecurity(struct key *key, char **_buffer)
5770{
5771 struct key_security_struct *ksec = key->security;
5772 char *context = NULL;
5773 unsigned len;
5774 int rc;
5775
5776 rc = security_sid_to_context(ksec->sid, &context, &len);
5777 if (!rc)
5778 rc = len;
5779 *_buffer = context;
5780 return rc;
5781}
5782
Michael LeMayd7200242006-06-22 14:47:17 -07005783#endif
5784
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005785static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005786 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5787 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5788 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5789 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Stephen Smalley79af7302015-01-21 10:54:10 -05005790
Casey Schauflere20b0432015-05-02 15:11:36 -07005791 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5792 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5793 LSM_HOOK_INIT(capget, selinux_capget),
5794 LSM_HOOK_INIT(capset, selinux_capset),
5795 LSM_HOOK_INIT(capable, selinux_capable),
5796 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5797 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5798 LSM_HOOK_INIT(syslog, selinux_syslog),
5799 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800
Casey Schauflere20b0432015-05-02 15:11:36 -07005801 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802
Casey Schauflere20b0432015-05-02 15:11:36 -07005803 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5804 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5805 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5806 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807
Casey Schauflere20b0432015-05-02 15:11:36 -07005808 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5809 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5810 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5811 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5812 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5813 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5814 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5815 LSM_HOOK_INIT(sb_mount, selinux_mount),
5816 LSM_HOOK_INIT(sb_umount, selinux_umount),
5817 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5818 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5819 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Eric Parise0007522008-03-05 10:31:54 -05005820
Casey Schauflere20b0432015-05-02 15:11:36 -07005821 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822
Casey Schauflere20b0432015-05-02 15:11:36 -07005823 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5824 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5825 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5826 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5827 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5828 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5829 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5830 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5831 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5832 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5833 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5834 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5835 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5836 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5837 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5838 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5839 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5840 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5841 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5842 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5843 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5844 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5845 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5846 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5847 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848
Casey Schauflere20b0432015-05-02 15:11:36 -07005849 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5850 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5851 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5852 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5853 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5854 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5855 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5856 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5857 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5858 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5859 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5860 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861
Casey Schauflere20b0432015-05-02 15:11:36 -07005862 LSM_HOOK_INIT(file_open, selinux_file_open),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005863
Casey Schauflere20b0432015-05-02 15:11:36 -07005864 LSM_HOOK_INIT(task_create, selinux_task_create),
5865 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5866 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5867 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5868 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5869 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5870 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5871 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5872 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5873 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5874 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5875 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5876 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5877 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5878 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5879 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5880 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5881 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5882 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5883 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5884 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5885 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005886
Casey Schauflere20b0432015-05-02 15:11:36 -07005887 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5888 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889
Casey Schauflere20b0432015-05-02 15:11:36 -07005890 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5891 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892
Casey Schauflere20b0432015-05-02 15:11:36 -07005893 LSM_HOOK_INIT(msg_queue_alloc_security,
5894 selinux_msg_queue_alloc_security),
5895 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5896 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5897 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5898 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5899 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
Casey Schauflere20b0432015-05-02 15:11:36 -07005901 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5902 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5903 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5904 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5905 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906
Casey Schauflere20b0432015-05-02 15:11:36 -07005907 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5908 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5909 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5910 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5911 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Casey Schauflere20b0432015-05-02 15:11:36 -07005913 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914
Casey Schauflere20b0432015-05-02 15:11:36 -07005915 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5916 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005917
Casey Schauflere20b0432015-05-02 15:11:36 -07005918 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5919 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5920 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5921 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5922 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5923 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5924 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005925
Casey Schauflere20b0432015-05-02 15:11:36 -07005926 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
5927 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Casey Schauflere20b0432015-05-02 15:11:36 -07005929 LSM_HOOK_INIT(socket_create, selinux_socket_create),
5930 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
5931 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
5932 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
5933 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
5934 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
5935 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
5936 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
5937 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
5938 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
5939 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
5940 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
5941 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
5942 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
5943 LSM_HOOK_INIT(socket_getpeersec_stream,
5944 selinux_socket_getpeersec_stream),
5945 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
5946 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
5947 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
5948 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
5949 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
5950 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
5951 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
5952 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
5953 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
5954 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
5955 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
5956 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
5957 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
5958 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
5959 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
5960 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
5961 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
5962 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
5963 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005964
5965#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07005966 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
5967 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
5968 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
5969 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
5970 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
5971 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
5972 selinux_xfrm_state_alloc_acquire),
5973 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
5974 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
5975 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
5976 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
5977 selinux_xfrm_state_pol_flow_match),
5978 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005980
5981#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07005982 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
5983 LSM_HOOK_INIT(key_free, selinux_key_free),
5984 LSM_HOOK_INIT(key_permission, selinux_key_permission),
5985 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07005986#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005987
5988#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07005989 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
5990 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
5991 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
5992 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005993#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994};
5995
5996static __init int selinux_init(void)
5997{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005998 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005999 selinux_enabled = 0;
6000 return 0;
6001 }
6002
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003 if (!selinux_enabled) {
6004 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6005 return 0;
6006 }
6007
6008 printk(KERN_INFO "SELinux: Initializing.\n");
6009
6010 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006011 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006013 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6014
James Morris7cae7e22006-03-22 00:09:22 -08006015 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6016 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006017 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 avc_init();
6019
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006020 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021
Paul Moore615e51f2014-06-26 14:33:56 -04006022 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6023 panic("SELinux: Unable to register AVC netcache callback\n");
6024
Eric Paris828dfe12008-04-17 13:17:49 -04006025 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006026 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006027 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006028 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006029
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030 return 0;
6031}
6032
Al Viroe8c26252010-03-23 06:36:54 -04006033static void delayed_superblock_init(struct super_block *sb, void *unused)
6034{
6035 superblock_doinit(sb, NULL);
6036}
6037
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038void selinux_complete_init(void)
6039{
Eric Parisfadcdb42007-02-22 18:11:31 -05006040 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041
6042 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006043 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006044 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045}
6046
6047/* SELinux requires early initialization in order to label
6048 all processes and objects when they are created. */
6049security_initcall(selinux_init);
6050
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006051#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
Jiri Pirko25db6be2014-09-03 17:42:13 +02006053static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006054 {
6055 .hook = selinux_ipv4_postroute,
6056 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006057 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006058 .hooknum = NF_INET_POST_ROUTING,
6059 .priority = NF_IP_PRI_SELINUX_LAST,
6060 },
6061 {
6062 .hook = selinux_ipv4_forward,
6063 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006064 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006065 .hooknum = NF_INET_FORWARD,
6066 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006067 },
6068 {
6069 .hook = selinux_ipv4_output,
6070 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006071 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006072 .hooknum = NF_INET_LOCAL_OUT,
6073 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006074 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006076 {
6077 .hook = selinux_ipv6_postroute,
6078 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006079 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006080 .hooknum = NF_INET_POST_ROUTING,
6081 .priority = NF_IP6_PRI_SELINUX_LAST,
6082 },
6083 {
6084 .hook = selinux_ipv6_forward,
6085 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006086 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006087 .hooknum = NF_INET_FORWARD,
6088 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006089 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006091};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092
6093static int __init selinux_nf_ip_init(void)
6094{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006095 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096
6097 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006098 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006099
6100 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6101
Jiri Pirko25db6be2014-09-03 17:42:13 +02006102 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006103 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006104 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105
Jiri Pirko25db6be2014-09-03 17:42:13 +02006106 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107}
6108
6109__initcall(selinux_nf_ip_init);
6110
6111#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6112static void selinux_nf_ip_exit(void)
6113{
Eric Parisfadcdb42007-02-22 18:11:31 -05006114 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Jiri Pirko25db6be2014-09-03 17:42:13 +02006116 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117}
6118#endif
6119
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006120#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
6122#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6123#define selinux_nf_ip_exit()
6124#endif
6125
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006126#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127
6128#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006129static int selinux_disabled;
6130
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131int selinux_disable(void)
6132{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133 if (ss_initialized) {
6134 /* Not permitted after initial policy load. */
6135 return -EINVAL;
6136 }
6137
6138 if (selinux_disabled) {
6139 /* Only do this once. */
6140 return -EINVAL;
6141 }
6142
6143 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6144
6145 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006146 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006148 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149
Eric Parisaf8ff042009-09-20 21:23:01 -04006150 /* Try to destroy the avc node cache */
6151 avc_disable();
6152
Linus Torvalds1da177e2005-04-16 15:20:36 -07006153 /* Unregister netfilter hooks. */
6154 selinux_nf_ip_exit();
6155
6156 /* Unregister selinuxfs. */
6157 exit_sel_fs();
6158
6159 return 0;
6160}
6161#endif